Skip to content

Commit

Permalink
Merge pull request #1609 from intuit/hook-context
Browse files Browse the repository at this point in the history
simplify hook APIs for easier future extensibility
  • Loading branch information
hipstersmoothie authored Oct 27, 2020
2 parents 7ffc7df + 593e973 commit f71a3b1
Show file tree
Hide file tree
Showing 20 changed files with 136 additions and 93 deletions.
4 changes: 4 additions & 0 deletions docs/pages/docs/plugins/changelog-hooks.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ The hooks it provides allow you to customize everything about how the changelog
This is where you hook into the changelog's hooks.
See examples below.

```ts
auto.hooks.onCreateChangelog.tapPromise('Giphy', (changelog, { bump }) => {});
```

## addToBody

Add extra content to your changelogs.
Expand Down
52 changes: 28 additions & 24 deletions docs/pages/docs/plugins/release-lifecycle-hooks.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,10 @@ You must push the tags to github!
This hooks is required for plugin that facilitate publishing.

```ts
auto.hooks.publish.tapPromise("NPM", async (version: SEMVER) => {
auto.hooks.publish.tapPromise("NPM", async ({ bump }) => {
await execPromise("npm", [
"version",
version,
bump,
"-m",
"Bump version to: %s [skip ci]",
]);
Expand Down Expand Up @@ -187,19 +187,26 @@ You can either return a string value of just the version or an object containing
- `details` - The body of the details element

```ts
auto.hooks.canary.tapPromise(this.name, async ({ bump, canaryIdentifier, dryRun, quiet }) => {
const lastRelease = await auto.git!.getLatestRelease();
const current = await auto.getCurrentVersion(lastRelease);
const nextVersion = inc(current, bump as ReleaseType);
const isScopedPackage = name.match(/@\S+\/\S+/);
const canaryVersion = `${nextVersion}-canary${canaryIdentifier}`;

await execPromise("npm", ["version", canaryVersion, "--no-git-tag-version"]);
await execPromise("npm", ["publish", "--tag", "canary"]);

auto.logger.verbose.info("Successfully published canary version");
return canaryVersion;
});
auto.hooks.canary.tapPromise(
this.name,
async ({ bump, canaryIdentifier, dryRun, quiet }) => {
const lastRelease = await auto.git!.getLatestRelease();
const current = await auto.getCurrentVersion(lastRelease);
const nextVersion = inc(current, bump as ReleaseType);
const isScopedPackage = name.match(/@\S+\/\S+/);
const canaryVersion = `${nextVersion}-canary${canaryIdentifier}`;

await execPromise("npm", [
"version",
canaryVersion,
"--no-git-tag-version",
]);
await execPromise("npm", ["publish", "--tag", "canary"]);

auto.logger.verbose.info("Successfully published canary version");
return canaryVersion;
}
);
```

`canary` version should not produce any of the following:
Expand Down Expand Up @@ -230,7 +237,7 @@ import {

auto.hooks.next.tapPromise(
this.name,
async (preReleaseVersions, bump, { dryRun }) => {
async (preReleaseVersions, { bump, dryRun }) => {
const branch = getCurrentBranch() || "";
const lastRelease = await auto.git.getLatestRelease();
const current =
Expand Down Expand Up @@ -328,18 +335,15 @@ _Other examples:_

Ran after the `shipit` command has run.

- `newVersion` - The new version that was release
- `commits` - the commits in the release
- `data`
- `newVersion` - The new version that was release
- `commits` - the commits in the release
- `context` - The type of release that was created (`latest`, `next`, `canary`, or `old`)

```ts
auto.hooks.afterShipIt.tap(
"MyPlugin",
async (newVersion, commits, { context }) => {
// do something
}
);
auto.hooks.afterShipIt.tap("MyPlugin", async ({ context }) => {
// do something
});
```

_Other examples:_
Expand Down
44 changes: 33 additions & 11 deletions packages/core/src/auto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ interface BeforeShipitContext extends DryRunOption {
}

interface NextContext extends DryRunOption {
/** The bump to apply to the version */
bump: SEMVER;
/** The commits in the next release */
commits: IExtendedCommit[];
/** The release notes for all the commits in the next release */
Expand All @@ -151,9 +153,11 @@ export interface IAutoHooks {
/** Ran after the `shipit` command has run. */
afterShipIt: AsyncParallelHook<
[
string | undefined,
IExtendedCommit[],
{
/** The version published in the shipit run */
newVersion: string | undefined;
/** The commits the version was published for */
commitsInRelease: IExtendedCommit[];
/** The type of release made by shipit */
context: ShipitContext;
}
Expand Down Expand Up @@ -214,7 +218,15 @@ export interface IAutoHooks {
* This is where you hook into the changelog's hooks.
* This hook is exposed for convenience during `this.hooks.onCreateRelease` and at the root `this.hooks`
*/
onCreateChangelog: SyncHook<[Changelog, SEMVER | undefined]>;
onCreateChangelog: SyncHook<
[
Changelog,
{
/** The bump the changelog will make */
bump: SEMVER | undefined;
}
]
>;
/** Version the package. This is a good opportunity to `git tag` the release also. */
version: AsyncParallelHook<
[
Expand All @@ -228,13 +240,20 @@ export interface IAutoHooks {
/** Ran after the package has been versioned. */
afterVersion: AsyncParallelHook<[DryRunOption]>;
/** Publish the package to some package distributor. You must push the tags to github! */
publish: AsyncParallelHook<[SEMVER]>;
publish: AsyncParallelHook<
[
{
/** The semver bump that was applied in the version hook */
bump: SEMVER;
}
]
>;
/** Used to publish a canary release. In this hook you get the semver bump and the unique canary postfix ID. */
canary: AsyncSeriesBailHook<
[
DryRunOption &
QuietOption & {
/** The bump to apply to the version */
/** The bump being applied to the version */
bump: SEMVER;
/** The post-version identifier to add to the version */
canaryIdentifier: string;
Expand All @@ -258,7 +277,7 @@ export interface IAutoHooks {
* and an array of next versions that been released. If you make another
* next release be sure to add it the the array.
*/
next: AsyncSeriesWaterfallHook<[string[], SEMVER, NextContext]>;
next: AsyncSeriesWaterfallHook<[string[], NextContext]>;
/** Ran after the package has been published. */
afterPublish: AsyncParallelHook<[]>;
/** Ran after the package has been published. */
Expand Down Expand Up @@ -392,8 +411,8 @@ export default class Auto {
this.hooks.onCreateRelease.tap("Link onCreateChangelog", (release) => {
release.hooks.onCreateChangelog.tap(
"Link onCreateChangelog",
(changelog, version) => {
this.hooks.onCreateChangelog.call(changelog, version);
(changelog, bump) => {
this.hooks.onCreateChangelog.call(changelog, { bump });
}
);
});
Expand Down Expand Up @@ -1317,7 +1336,8 @@ export default class Auto {
}

this.logger.verbose.info(`Calling "next" hook with: ${bump}`);
const result = await this.hooks.next.promise([], bump, {
const result = await this.hooks.next.promise([], {
bump,
commits,
fullReleaseNotes,
releaseNotes,
Expand Down Expand Up @@ -1484,7 +1504,9 @@ export default class Auto {
}

const { newVersion, commitsInRelease, context } = publishInfo;
await this.hooks.afterShipIt.promise(newVersion, commitsInRelease, {
await this.hooks.afterShipIt.promise({
newVersion,
commitsInRelease,
context,
});
}
Expand Down Expand Up @@ -1584,7 +1606,7 @@ export default class Auto {

if (!options.dryRun) {
this.logger.verbose.info("Calling publish hook");
await this.hooks.publish.promise(bump);
await this.hooks.publish.promise({ bump });
this.logger.verbose.info("Calling after publish hook");
await this.hooks.afterPublish.promise();
}
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/utils/make-hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const makeHooks = (): IAutoHooks => ({
beforeShipIt: new AsyncSeriesHook(["context"]),
afterChangelog: new AsyncSeriesHook(["context"]),
beforeCommitChangelog: new AsyncSeriesHook(["context"]),
afterShipIt: new AsyncParallelHook(["version", "commits", "context"]),
afterShipIt: new AsyncParallelHook(["context"]),
makeRelease: new AsyncSeriesBailHook(["releaseInfo"]),
afterRelease: new AsyncParallelHook(["releaseInfo"]),
onCreateRelease: new SyncHook(["options"]),
Expand All @@ -35,7 +35,7 @@ export const makeHooks = (): IAutoHooks => ({
publish: new AsyncParallelHook(["version"]),
afterPublish: new AsyncParallelHook(),
canary: new AsyncSeriesBailHook(["canaryContext"]),
next: new AsyncSeriesWaterfallHook(["preReleaseVersions", "bump", "context"]),
next: new AsyncSeriesWaterfallHook(["preReleaseVersions", "context"]),
});

/** Make the hooks for "Release" */
Expand Down
14 changes: 7 additions & 7 deletions plugins/cocoapods/__tests__/cocoapods.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ describe("Cocoapods Plugin", () => {
prefixRelease,
} as Auto.Auto);

await hook.publish.promise(Auto.SEMVER.patch);
await hook.publish.promise({ bump: Auto.SEMVER.patch });

expect(exec).toBeCalledTimes(2);
expect(exec).lastCalledWith("pod", ["trunk", "push", "./Test.podspec"]);
Expand All @@ -264,7 +264,7 @@ describe("Cocoapods Plugin", () => {
prefixRelease,
} as Auto.Auto);

await hook.publish.promise(Auto.SEMVER.patch);
await hook.publish.promise({ bump: Auto.SEMVER.patch });

expect(exec).toBeCalledTimes(2);
expect(exec).lastCalledWith("notpod", [
Expand All @@ -288,7 +288,7 @@ describe("Cocoapods Plugin", () => {
prefixRelease,
} as Auto.Auto);

await hook.publish.promise(Auto.SEMVER.patch);
await hook.publish.promise({ bump: Auto.SEMVER.patch });

expect(exec).toBeCalledTimes(2);
expect(exec).lastCalledWith("bundle", [
Expand Down Expand Up @@ -317,7 +317,7 @@ describe("Cocoapods Plugin", () => {
prefixRelease,
} as Auto.Auto);

await hook.publish.promise(Auto.SEMVER.patch);
await hook.publish.promise({ bump: Auto.SEMVER.patch });

expect(exec).toBeCalledTimes(2);
expect(exec).lastCalledWith("pod", [
Expand Down Expand Up @@ -347,7 +347,7 @@ describe("Cocoapods Plugin", () => {
prefixRelease,
} as Auto.Auto);

await hook.publish.promise(Auto.SEMVER.patch);
await hook.publish.promise({ bump: Auto.SEMVER.patch });

expect(exec).toBeCalledTimes(5);
expect(exec).toHaveBeenNthCalledWith(2, "pod", ["repo", "list"]);
Expand Down Expand Up @@ -391,7 +391,7 @@ describe("Cocoapods Plugin", () => {
prefixRelease,
} as Auto.Auto);

await hook.publish.promise(Auto.SEMVER.patch);
await hook.publish.promise({ bump: Auto.SEMVER.patch });

expect(exec).toBeCalledTimes(5);
expect(exec).toHaveBeenNthCalledWith(2, "pod", ["repo", "list"]);
Expand Down Expand Up @@ -454,7 +454,7 @@ trunk
prefixRelease,
} as Auto.Auto);

await hook.publish.promise(Auto.SEMVER.patch);
await hook.publish.promise({ bump: Auto.SEMVER.patch });

expect(exec).toBeCalledTimes(6);
expect(exec).toHaveBeenNthCalledWith(2, "pod", ["repo", "list"]);
Expand Down
2 changes: 1 addition & 1 deletion plugins/crates/__tests__/crates.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ describe("CratesPlugin", () => {
remote: "origin",
baseBranch: "master",
} as Auto.Auto);
await hooks.publish.promise(Auto.SEMVER.patch);
await hooks.publish.promise({ bump: Auto.SEMVER.patch });
expect(exec).toHaveBeenCalledWith("cargo", ["publish"]);
expect(exec).toHaveBeenCalledWith("git", [
"push",
Expand Down
13 changes: 7 additions & 6 deletions plugins/docker/__tests__/docker.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ describe("Docker Plugin", () => {
describe("canary", () => {
test("should do nothing without git", async () => {
const hooks = setup();
await hooks.next.promise([], Auto.SEMVER.patch, {} as any);
await hooks.next.promise([], { bump: Auto.SEMVER.patch } as any);
expect(exec).not.toHaveBeenCalled();
});

Expand Down Expand Up @@ -223,7 +223,7 @@ describe("Docker Plugin", () => {
describe("next", () => {
test("should do nothing without git", async () => {
const hooks = setup();
await hooks.next.promise([], Auto.SEMVER.patch, {} as any);
await hooks.next.promise([], { bump: Auto.SEMVER.patch } as any);
expect(exec).not.toHaveBeenCalled();
});

Expand All @@ -237,7 +237,7 @@ describe("Docker Plugin", () => {
{ registry, image: sourceImage }
);

await hooks.next.promise([], Auto.SEMVER.patch, {} as any);
await hooks.next.promise([], { bump: Auto.SEMVER.patch } as any);

expect(exec).toHaveBeenCalledWith("git", [
"tag",
Expand Down Expand Up @@ -273,7 +273,8 @@ describe("Docker Plugin", () => {
);

expect(
await hooks.next.promise([], Auto.SEMVER.patch, {
await hooks.next.promise([], {
bump: Auto.SEMVER.patch,
dryRun: true,
quiet: true,
} as any)
Expand All @@ -295,7 +296,7 @@ describe("Docker Plugin", () => {
);
await hooks.version.promise({ bump: Auto.SEMVER.patch });

await hooks.publish.promise(Auto.SEMVER.patch);
await hooks.publish.promise({ bump: Auto.SEMVER.patch });
expect(exec).toHaveBeenCalledWith("docker", [
"push",
`${registry}:1.0.1`,
Expand All @@ -314,7 +315,7 @@ describe("Docker Plugin", () => {
);
await hooks.version.promise({ bump: Auto.SEMVER.patch });

await hooks.publish.promise(Auto.SEMVER.patch);
await hooks.publish.promise({ bump: Auto.SEMVER.patch });
expect(exec).toHaveBeenCalledWith("docker", [
"push",
`${registry}:1.0.1`,
Expand Down
2 changes: 1 addition & 1 deletion plugins/docker/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ export default class DockerPlugin implements IPlugin {

auto.hooks.next.tapPromise(
this.name,
async (preReleaseVersions, bump, { dryRun }) => {
async (preReleaseVersions, { bump, dryRun }) => {
if (!auto.git) {
return preReleaseVersions;
}
Expand Down
2 changes: 1 addition & 1 deletion plugins/exec/__tests__/exec.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ describe("Exec Plugin", () => {
plugins.apply({ hooks } as Auto);
hooks.onCreateChangelog.call(
{ hooks: changelogHooks } as any,
SEMVER.patch
{ bump: SEMVER.patch }
);

expect(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ const graphql = jest.fn();
const exec = jest.fn();
exec.mockReturnValue("");
// @ts-ignore
jest.mock("../../../packages/core/dist/utils/exec-promise", () => (...args: any[]) =>
exec(...args)
jest.mock(
"../../../packages/core/dist/utils/exec-promise",
() => (...args: any[]) => exec(...args)
);

const setup = (
Expand Down Expand Up @@ -45,7 +46,7 @@ const setup = (
hooks: changelogHooks,
options: { baseUrl: "https://github.com" },
} as Changelog,
Auto.SEMVER.patch
{ bump: Auto.SEMVER.patch }
);

return changelogHooks;
Expand Down
Loading

0 comments on commit f71a3b1

Please sign in to comment.