diff --git a/docs/pages/docs/plugins/configuration-hooks.mdx b/docs/pages/docs/plugins/configuration-hooks.mdx index baf3a251d8..10d027e2ef 100644 --- a/docs/pages/docs/plugins/configuration-hooks.mdx +++ b/docs/pages/docs/plugins/configuration-hooks.mdx @@ -139,3 +139,15 @@ auto.hooks.validateConfig.tapPromise("test", (name, options) => { } }); ``` + +## afterRun + +Happens after any command run. +This is a great place to trigger post-actions. + +```ts +auto.hooks.afterRun.tapPromise("afterCheck", async (config) => { + ... + } +}); +``` diff --git a/packages/cli/src/run.ts b/packages/cli/src/run.ts index 0aa51983fd..a1b4394086 100644 --- a/packages/cli/src/run.ts +++ b/packages/cli/src/run.ts @@ -136,6 +136,8 @@ export async function execute(command: string, args: ApiOptions) { } process.exit(1); + } finally { + await auto.teardown(); } } diff --git a/packages/core/src/__tests__/auto.test.ts b/packages/core/src/__tests__/auto.test.ts index 0fd28aed19..bf52261485 100644 --- a/packages/core/src/__tests__/auto.test.ts +++ b/packages/core/src/__tests__/auto.test.ts @@ -1580,6 +1580,33 @@ describe("Auto", () => { expect(spy).not.toHaveBeenCalled(); }); }); + + describe("teardown", () => { + test("should throw when not initialized", async () => { + const auto = new Auto(defaults); + // @ts-ignore + auto.checkClean = () => Promise.resolve(true); + auto.logger = dummyLog(); + + await expect(auto.teardown()).rejects.not.toBeUndefined(); + }); + + test("should call afterRun hooks", async () => { + const auto = new Auto({ ...defaults, plugins: [] }); + // @ts-ignore + auto.checkClean = () => Promise.resolve(true); + auto.logger = dummyLog(); + await auto.loadConfig(); + + const afterRun = jest.fn(); + auto.hooks.afterRun.tap("test", afterRun); + + await auto.shipit(); + expect(afterRun).toHaveBeenCalledWith({ + dryRun: undefined, + }); + }); + }); }); describe("hooks", () => { diff --git a/packages/core/src/auto.ts b/packages/core/src/auto.ts index 68d0973eaa..98d7e2269d 100644 --- a/packages/core/src/auto.ts +++ b/packages/core/src/auto.ts @@ -151,6 +151,8 @@ export interface IAutoHooks { validateConfig: ValidatePluginHook; /** Happens before anything is done. This is a great place to check for platform specific secrets. */ beforeRun: AsyncSeriesHook<[LoadedAutoRc]>; + /** Happens after everything else is done. This is a great place to trigger post-actions. */ + afterRun: AsyncSeriesHook<[LoadedAutoRc]>; /** Happens before `shipit` is run. This is a great way to throw an error if a token or key is not present. */ beforeShipIt: AsyncSeriesHook<[BeforeShipitContext]>; /** Ran before the `changelog` command commits the new release notes to `CHANGELOG.md`. */ @@ -663,6 +665,14 @@ export default class Auto { return config; } + /** + * Gracefully teardown auto + */ + async teardown() { + this.logger.verbose.success("Teardown `auto`"); + await this.hooks.afterRun.promise(this.config!); + } + /** Determine the remote we have auth to push to. */ private async getRemote(): Promise { const [, configuredRemote = "origin"] = await on( diff --git a/packages/core/src/utils/make-hooks.ts b/packages/core/src/utils/make-hooks.ts index c2abab99e9..12df2540b3 100644 --- a/packages/core/src/utils/make-hooks.ts +++ b/packages/core/src/utils/make-hooks.ts @@ -14,6 +14,7 @@ import { InteractiveInitHooks } from "../init"; /** Make the hooks for "auto" */ export const makeHooks = (): IAutoHooks => ({ beforeRun: new AsyncSeriesHook(["config"]), + afterRun: new AsyncSeriesHook(["config"]), modifyConfig: new AsyncSeriesWaterfallHook(["config"]), validateConfig: new AsyncSeriesBailHook(["name", "options"]), beforeShipIt: new AsyncSeriesHook(["context"]), diff --git a/yarn.lock b/yarn.lock index fd3b613b66..e5866ea770 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13,10 +13,10 @@ integrity sha512-K1kQv1BZVtMXQqdpNZt9Pgh85KwamsWX9gYyq1xG4cpyb+EacfMiNfumrju16piFXanCUrCR0P1DowPjV2qV/A== "@auto-it/bot-list@link:packages/bot-list": - version "10.36.2" + version "10.37.1" "@auto-it/core@link:packages/core": - version "10.36.2" + version "10.37.1" dependencies: "@auto-it/bot-list" "link:packages/bot-list" "@endemolshinegroup/cosmiconfig-typescript-loader" "^3.0.2" @@ -59,7 +59,7 @@ url-join "^4.0.0" "@auto-it/npm@link:plugins/npm": - version "10.36.2" + version "10.37.1" dependencies: "@auto-it/core" "link:packages/core" "@auto-it/package-json-utils" "link:packages/package-json-utils" @@ -77,13 +77,13 @@ user-home "^2.0.0" "@auto-it/package-json-utils@link:packages/package-json-utils": - version "10.36.2" + version "10.37.1" dependencies: parse-author "^2.0.0" parse-github-url "1.0.2" "@auto-it/released@link:plugins/released": - version "10.36.2" + version "10.37.1" dependencies: "@auto-it/bot-list" "link:packages/bot-list" "@auto-it/core" "link:packages/core" @@ -92,6 +92,15 @@ io-ts "^2.1.2" tslib "2.1.0" +"@auto-it/version-file@link:plugins/version-file": + version "10.37.1" + dependencies: + "@auto-it/core" "link:packages/core" + fp-ts "^2.5.3" + io-ts "^2.1.2" + semver "^7.0.0" + tslib "1.10.0" + "@babel/code-frame@7.12.11": version "7.12.11" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" @@ -11531,12 +11540,7 @@ path-key@^3.0.0, path-key@^3.1.0: resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== -path-parse@^1.0.5, path-parse@^1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -path-parse@^1.0.7: +path-parse@^1.0.5, path-parse@^1.0.6, path-parse@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==