Repository: intuit/auto
Pull request #730 (2019-11-28 02:24:17)

allow user to configure what branches are treated as prerelease branches
this also refactors how auto was accessing the config in a few places.
<!-- GITHUB_RELEASE PR BODY: canary-version -->
Published PR with canary version: `8.1.0-canary.730.9603.0`
<!-- GITHUB_RELEASE PR BODY: canary-version -->



Patch:
diff --git a/docs/pages/autorc.md b/docs/pages/autorc.md
index 3f250caf..3f9ce699 100644
--- a/docs/pages/autorc.md
+++ b/docs/pages/autorc.md
@@ -22,6 +22,18 @@ auto init
 
 These options can be set exclusively in the `.autorc` and do not exist as CLI flags.
 
+### Prerelease Labels
+
+You can configure what branches `auto` treats as prerelease branches.
+By default only `next` is treated as a prerelease branch.
+If you configure `prereleaseLabels` it will override the default.
+
+```json
+{
+  "prereleaseLabels": ["next", "beta"]
+}
+```
+
 ### Extending
 
 If you want to share your auto configuration between projects you can use the `extends` property. This property will load from a module's package.json or from a custom path. It's expected that the extended configuration be under the `auto` key in the package.json file.
@@ -78,8 +90,7 @@ To override any of the default labels use the `labels` section in the `.autorc`.
     "minor": "Version: Minor",
     "patch": "Version: Patch",
     "skip-release": "NO!",
-    "release": "Autobots, rollout!",
-    "prerelease": "beta"
+    "release": "Autobots, rollout!"
   }
 }
 ```
diff --git a/packages/cli/src/parse-args.ts b/packages/cli/src/parse-args.ts
index e8ba1830..001fbdd7 100644
--- a/packages/cli/src/parse-args.ts
+++ b/packages/cli/src/parse-args.ts
@@ -439,10 +439,10 @@ export const commands: Command[] = [
       Run the full \`auto\` release pipeline. Detects if in a lerna project.
 
       1. call from base branch -> latest version released
-      2. call from next branch -> next version released
+      2. call from prerelease branch -> prerelease version released
       3. call from PR in CI -> canary version released
-      4. call locally when on next branch -> next version released
-      5. call locally when not on base/next branch -> canary version released
+      4. call locally when on prerelease branch -> prerelease version released
+      5. call locally when not on base/prerelease branch -> canary version released
     `,
     examples: ['{green $} auto shipit'],
     options: [baseBranch, dryRun]
@@ -487,10 +487,10 @@ export const commands: Command[] = [
     name: 'next',
     group: 'Release Commands',
     description: dedent`
-      Make a release for your "next" release line.
+      Make a release for your "prerelease" release line.
 
       1. Creates a prerelease on package management platform
-      2. Creates a prerelease on GitHub releases page.
+      2. Creates a "Pre Release" on GitHub releases page.
     `,
     examples: ['{green $} auto next'],
     options: [dryRun]
diff --git a/packages/core/src/auto.ts b/packages/core/src/auto.ts
index 0a893b97..77d52446 100644
--- a/packages/core/src/auto.ts
+++ b/packages/core/src/auto.ts
@@ -405,12 +405,12 @@ export default class Auto {
       const releaseTag = labels.find(l => l === 'release');
 
       const skipReleaseTag = labels.find(l =>
-        this.release?.options.skipReleaseLabels.includes(l)
+        this.config?.skipReleaseLabels.includes(l)
       );
       const semverTag = labels.find(
         l =>
           labelValues.some(labelValue => labelValue.includes(l)) &&
-          !this.release?.options.skipReleaseLabels.includes(l) &&
+          !this.config?.skipReleaseLabels.includes(l) &&
           l !== 'release'
       );
 
@@ -773,7 +773,10 @@ export default class Auto {
     const isPR = 'isPr' in env && env.isPr;
     const isBaseBranch =
       !isPR && 'branch' in env && env.branch === this.baseBranch;
-    const isNextBranch = 'branch' in env && env.branch === 'next';
+    const isNextBranch =
+      'branch' in env &&
+      this.config?.prereleaseBranches?.some(branch => env.branch === branch);
+
     const publishInfo = isBaseBranch
       ? await this.publishLatest(options)
       : isNextBranch
@@ -1066,7 +1069,7 @@ export default class Auto {
       throw this.createErrorMessage();
     }
 
-    return this.release.options.noVersionPrefix || release.startsWith('v')
+    return this.config?.noVersionPrefix || release.startsWith('v')
       ? release
       : `v${release}`;
   };
@@ -1107,7 +1110,7 @@ If a command fails manually run:
         return;
       }
 
-      let { email, name } = this.release.options;
+      let { email, name } = this.release.config;
       this.logger.verbose.warn(
         `Got author from options: email: ${email}, name ${name}`
       );
diff --git a/packages/core/src/config.ts b/packages/core/src/config.ts
index 9b95d133..b08aa850 100644
--- a/packages/core/src/config.ts
+++ b/packages/core/src/config.ts
@@ -121,7 +121,8 @@ export default class Config {
       ...rawConfig,
       ...args,
       labels,
-      skipReleaseLabels
+      skipReleaseLabels,
+      prereleaseBranches: rawConfig.prereleaseBranches || ['next']
     };
   }
 
diff --git a/packages/core/src/release.ts b/packages/core/src/release.ts
index 2f31e896..9386eda1 100644
--- a/packages/core/src/release.ts
+++ b/packages/core/src/release.ts
@@ -47,6 +47,8 @@ export type IAutoConfig = IAuthorOptions &
     baseBranch: string;
     /** Labels to count as "skip-release" */
     skipReleaseLabels: string[];
+    /** Branches to create prereleases from */
+    prereleaseBranches: string[];
     /** Instead of publishing every PR only publish when "release" label is present */
     onlyPublishWithReleaseLabel?: boolean;
     /** Whether to prefix the version with a "v" */
@@ -273,7 +275,7 @@ export default class Release {
   /** Plugin entry points */
   readonly hooks: IReleaseHooks;
   /** Options Release was initialized with */
-  readonly options: IAutoConfig;
+  readonly config: IAutoConfig;
 
   /** A class that handles interacting with git and GitHub */
   private readonly git: Git;
@@ -285,17 +287,18 @@ export default class Release {
   /** Initialize the release manager */
   constructor(
     git: Git,
-    options: IAutoConfig = {
+    config: IAutoConfig = {
       baseBranch: 'master',
       skipReleaseLabels: [],
+      prereleaseBranches: ['next'],
       labels: defaultLabelDefinition
     },
     logger: ILogger = dummyLog()
   ) {
-    this.options = options;
+    this.config = config;
     this.logger = logger;
     this.hooks = makeReleaseHooks();
-    this.versionLabels = getVersionMap(options.labels);
+    this.versionLabels = getVersionMap(config.labels);
     this.git = git;
   }
 
@@ -307,8 +310,8 @@ export default class Release {
       owner: this.git.options.owner,
       repo: this.git.options.repo,
       baseUrl: project.html_url,
-      labels: this.options.labels,
-      baseBranch: this.options.baseBranch
+      labels: this.config.labels,
+      baseBranch: this.config.baseBranch
     });
 
     this.hooks.onCreateChangelog.call(changelog, version);
@@ -464,7 +467,7 @@ export default class Release {
         return '';
       }
 
-      return this.options.noVersionPrefix || version.startsWith('v')
+      return this.config.noVersionPrefix || version.startsWith('v')
         ? version
         : `v${version}`;
     });
@@ -512,14 +515,14 @@ export default class Release {
 
         if (
           versionLabel === 'release' &&
-          !this.options.onlyPublishWithReleaseLabel
+          !this.config.onlyPublishWithReleaseLabel
         ) {
           return false;
         }
 
         if (
           versionLabel === 'skip-release' &&
-          this.options.onlyPublishWithReleaseLabel
+          this.config.onlyPublishWithReleaseLabel
         ) {
           return false;
         }
@@ -582,7 +585,7 @@ export default class Release {
   async getSemverBump(from: string, to = 'HEAD'): Promise<SEMVER> {
     const commits = await this.getCommits(from, to);
     const labels = commits.map(commit => commit.labels);
-    const { onlyPublishWithReleaseLabel, skipReleaseLabels } = this.options;
+    const { onlyPublishWithReleaseLabel, skipReleaseLabels } = this.config;
     const options = { onlyPublishWithReleaseLabel, skipReleaseLabels };
 
     this.logger.verbose.info('Calculating SEMVER bump using:\n', {
diff --git a/plugins/npm/src/index.ts b/plugins/npm/src/index.ts
index dd73abab..71f9be02 100644
--- a/plugins/npm/src/index.ts
+++ b/plugins/npm/src/index.ts
@@ -1,5 +1,6 @@
 import envCi from 'env-ci';
 import * as fs from 'fs';
+import { execSync } from 'child_process';
 import parseAuthor from 'parse-author';
 import path from 'path';
 import { Memoize as memoize } from 'typescript-memoize';
@@ -13,6 +14,9 @@ import setTokenOnCI from './set-npm-token';
 import { loadPackageJson, readFile } from './utils';
 
 const { isCi } = envCi();
+/** When the next hook is running branch is also the tag to publish under (ex: next, beta) */
+const branch = execSync('git symbolic-ref --short HEAD', { encoding: 'utf8' });
+
 const VERSION_COMMIT_MESSAGE = '"Bump version to: %s [skip ci]"';
 
 /** Check if the project is a monorepo */
@@ -32,7 +36,8 @@ async function getPublishedVersion(name: string) {
 export async function greaterRelease(
   prefixRelease: (release: string) => string,
   name: string,
-  packageVersion: string
+  packageVersion: string,
+  prereleaseBranch?: string
 ) {
   const publishedVersion = await getPublishedVersion(name);
 
@@ -41,9 +46,11 @@ export async function greaterRelease(
   }
 
   const publishedPrefixed = prefixRelease(publishedVersion);
-  const baseVersion = packageVersion.includes('next')
-    ? inc(packageVersion, 'patch') || packageVersion
-    : packageVersion;
+  // The branch (ex: next) is also the --preid
+  const baseVersion =
+    prereleaseBranch && packageVersion.includes(prereleaseBranch)
+      ? inc(packageVersion, 'patch') || packageVersion
+      : packageVersion;
 
   return gte(baseVersion, publishedPrefixed)
     ? packageVersion
@@ -249,6 +256,10 @@ export default class NPMPlugin implements IPlugin {
       auto.logger.logLevel === 'verbose' ||
       auto.logger.logLevel === 'veryVerbose';
     const verboseArgs = isVerbose ? verbose : [];
+    const prereleaseBranches = auto.config?.prereleaseBranches!;
+    const prereleaseBranch = prereleaseBranches.includes(branch)
+      ? branch
+      : prereleaseBranches[0];
 
     auto.hooks.beforeShipIt.tap(this.name, async () => {
       if (!isCi) {
@@ -302,7 +313,8 @@ export default class NPMPlugin implements IPlugin {
             previousVersion = await greaterRelease(
               prefixRelease,
               releasedPackage.name,
-              prefixRelease(monorepoVersion)
+              prefixRelease(monorepoVersion),
+              prereleaseBranch
             );
           }
         }
@@ -313,7 +325,12 @@ export default class NPMPlugin implements IPlugin {
         const { version, name } = await loadPackageJson();
 
         previousVersion = version
-          ? await greaterRelease(prefixRelease, name, prefixRelease(version))
+          ? await greaterRelease(
+              prefixRelease,
+              name,
+              prefixRelease(version),
+              prereleaseBranch
+            )
           : '0.0.0';
       }
 
@@ -546,11 +563,13 @@ export default class NPMPlugin implements IPlugin {
 
       if (isMonorepo()) {
         const packages = await this.getLernaPackages();
-        const inPreRelease = packages.find(p => p.version.includes('next'));
+        const inPreRelease = packages.find(p =>
+          p.version.includes(prereleaseBranch)
+        );
         const isIndependent = getLernaJson().version === 'independent';
         const next =
           inPreRelease && !isIndependent
-            ? inc(lastRelease, `pre${bump}` as ReleaseType, 'next') ||
+            ? inc(lastRelease, `pre${bump}` as ReleaseType, prereleaseBranch) ||
               'prerelease'
             : '';
 
@@ -565,9 +584,9 @@ export default class NPMPlugin implements IPlugin {
             ? 'prerelease'
             : `pre${bump}`,
           '--dist-tag',
-          'next',
+          prereleaseBranch,
           '--preid',
-          'next',
+          prereleaseBranch,
           '--message',
           VERSION_COMMIT_MESSAGE,
           '--force-publish', // you always want a next version to publish
@@ -584,7 +603,7 @@ export default class NPMPlugin implements IPlugin {
         } else {
           const packages = await this.getLernaPackages();
           const { version = '' } =
-            packages.find(p => p.version.includes('next')) || {};
+            packages.find(p => p.version.includes(prereleaseBranch)) || {};
 
           preReleaseVersions.push(auto.prefixRelease(version));
         }
@@ -592,7 +611,8 @@ export default class NPMPlugin implements IPlugin {
         auto.logger.verbose.info('Detected single npm package');
 
         const next =
-          inc(lastRelease, `pre${bump}` as ReleaseType, 'next') || 'prerelease';
+          inc(lastRelease, `pre${bump}` as ReleaseType, prereleaseBranch) ||
+          'prerelease';
         const current = await auto.getCurrentVersion(lastRelease);
 
         await execPromise('npm', [
@@ -602,7 +622,12 @@ export default class NPMPlugin implements IPlugin {
           VERSION_COMMIT_MESSAGE,
           ...verboseArgs
         ]);
-        await execPromise('npm', ['publish', '--tag', 'next', ...verboseArgs]);
+        await execPromise('npm', [
+          'publish',
+          '--tag',
+          prereleaseBranch,
+          ...verboseArgs
+        ]);
         await execPromise('git', ['push', '--follow-tags']);
 
         auto.logger.verbose.info('Successfully published next version');
diff --git a/plugins/released/src/index.ts b/plugins/released/src/index.ts
index 4f589fbd..77b3c10f 100644
--- a/plugins/released/src/index.ts
+++ b/plugins/released/src/index.ts
@@ -75,7 +75,7 @@ export default class ReleasedLabelPlugin implements IPlugin {
         }
 
         const isSkipped = head.labels.find(label =>
-          auto.release!.options.skipReleaseLabels.includes(label)
+          auto.config?.skipReleaseLabels.includes(label)
         );
 
         if (isSkipped) {
diff --git a/plugins/slack/src/index.ts b/plugins/slack/src/index.ts
index b62b948b..3e9ab60a 100644
--- a/plugins/slack/src/index.ts
+++ b/plugins/slack/src/index.ts
@@ -64,7 +64,7 @@ export default class SlackPlugin implements IPlugin {
         }
 
         const isSkipped = head.labels.find(label =>
-          auto.release!.options.skipReleaseLabels.includes(label)
+          auto.config?.skipReleaseLabels.includes(label)
         );
 
         if (isSkipped) {


Test patch:
diff --git a/packages/core/src/__tests__/__snapshots__/auto.test.ts.snap b/packages/core/src/__tests__/__snapshots__/auto.test.ts.snap
index d547884b..a2540d54 100644
--- a/packages/core/src/__tests__/__snapshots__/auto.test.ts.snap
+++ b/packages/core/src/__tests__/__snapshots__/auto.test.ts.snap
@@ -120,6 +120,9 @@ Object {
   },
   "onlyPublishWithReleaseLabel": true,
   "owner": "foo",
+  "prereleaseBranches": Array [
+    "next",
+  ],
   "repo": "bar",
   "skipReleaseLabels": Array [
     "skip-release",
@@ -183,6 +186,9 @@ Object {
     ],
   },
   "owner": "foo",
+  "prereleaseBranches": Array [
+    "next",
+  ],
   "repo": "bar",
   "skipReleaseLabels": Array [
     "skip-release",
diff --git a/packages/core/src/__tests__/auto.test.ts b/packages/core/src/__tests__/auto.test.ts
index 8c6d3a70..aebd9499 100644
--- a/packages/core/src/__tests__/auto.test.ts
+++ b/packages/core/src/__tests__/auto.test.ts
@@ -128,7 +128,7 @@ describe('Auto', () => {
     const auto = new Auto();
     auto.logger = dummyLog();
     await auto.loadConfig();
-    expect(auto.release!.options).toMatchSnapshot();
+    expect(auto.release!.config).toMatchSnapshot();
   });
 
   test('should extend local config', async () => {
@@ -144,7 +144,7 @@ describe('Auto', () => {
     const auto = new Auto();
     auto.logger = dummyLog();
     await auto.loadConfig();
-    expect(auto.release!.options).toMatchSnapshot();
+    expect(auto.release!.config).toMatchSnapshot();
     process.cwd = orig;
   });
 
@@ -161,7 +161,7 @@ describe('Auto', () => {
       ['Version: Minor'],
       ['Version: Patch'],
       ['skip-release'],
-      ['release'],
+      ['release']
     ]);
   });
 
@@ -178,7 +178,7 @@ describe('Auto', () => {
     auto.logger = dummyLog();
     await auto.loadConfig();
 
-    expect(auto.release!.options.skipReleaseLabels).toStrictEqual(['NOPE']);
+    expect(auto.release!.config.skipReleaseLabels).toStrictEqual(['NOPE']);
   });
 
   test('should be able to add label as string', async () => {
@@ -194,7 +194,7 @@ describe('Auto', () => {
     auto.logger = dummyLog();
     await auto.loadConfig();
 
-    expect(auto.release!.options.labels.minor).toStrictEqual([
+    expect(auto.config!.labels.minor).toStrictEqual([
       {
         description: 'Increment the minor version when merged',
         name: 'feature',
@@ -218,7 +218,7 @@ describe('Auto', () => {
     auto.logger = dummyLog();
     await auto.loadConfig();
 
-    expect(auto.release!.options.labels.minor).toStrictEqual([
+    expect(auto.config!.labels.minor).toStrictEqual([
       {
         description: 'This is a test',
         name: 'minor',
@@ -242,7 +242,7 @@ describe('Auto', () => {
     auto.logger = dummyLog();
     await auto.loadConfig();
 
-    expect(auto.release!.options.labels.fooBar).toStrictEqual([
+    expect(auto.config!.labels.fooBar).toStrictEqual([
       {
         description: 'This is a test',
         name: 'fooBar'
diff --git a/packages/core/src/__tests__/release.test.ts b/packages/core/src/__tests__/release.test.ts
index bc791167..32bc1c38 100644
--- a/packages/core/src/__tests__/release.test.ts
+++ b/packages/core/src/__tests__/release.test.ts
@@ -352,6 +352,7 @@ describe('Release', () => {
       const gh = new Release(git, {
         noVersionPrefix: true,
         skipReleaseLabels: ['skip-release'],
+        prereleaseBranches: ['next'],
         labels: defaultLabelDefinition,
         baseBranch: 'master'
       });
@@ -810,6 +811,7 @@ describe('Release', () => {
       const gh = new Release(git, {
         onlyPublishWithReleaseLabel: true,
         skipReleaseLabels: [],
+        prereleaseBranches: ['next'],
         labels: defaultLabelDefinition,
         baseBranch: 'master'
       });
@@ -831,6 +833,7 @@ describe('Release', () => {
       const gh = new Release(git, {
         onlyPublishWithReleaseLabel: true,
         skipReleaseLabels: [],
+        prereleaseBranches: ['next'],
         labels: defaultLabelDefinition,
         baseBranch: 'master'
       });
@@ -859,6 +862,7 @@ describe('Release', () => {
       const gh = new Release(git, {
         onlyPublishWithReleaseLabel: true,
         skipReleaseLabels: [],
+        prereleaseBranches: ['next'],
         labels: customLabels,
         baseBranch: 'master'
       });
@@ -918,6 +922,7 @@ describe('Release', () => {
         git,
         {
           skipReleaseLabels: [],
+          prereleaseBranches: ['next'],
           labels: defaultLabelDefinition,
           baseBranch: 'master'
         },
@@ -979,6 +984,7 @@ describe('Release', () => {
     test('should add release label in onlyPublishWithReleaseLabel mode', async () => {
       let gh = new Release(git, {
         skipReleaseLabels: [],
+        prereleaseBranches: ['next'],
         labels: defaultLabelDefinition,
         baseBranch: 'master'
       });
@@ -995,6 +1001,7 @@ describe('Release', () => {
       gh = new Release(git, {
         onlyPublishWithReleaseLabel: true,
         skipReleaseLabels: [],
+        prereleaseBranches: ['next'],
         labels: defaultLabelDefinition,
         baseBranch: 'master'
       });
@@ -1009,6 +1016,7 @@ describe('Release', () => {
       let gh = new Release(git, {
         onlyPublishWithReleaseLabel: true,
         skipReleaseLabels: [],
+        prereleaseBranches: ['next'],
         labels: defaultLabelDefinition,
         baseBranch: 'master'
       });
@@ -1026,6 +1034,7 @@ describe('Release', () => {
 
       gh = new Release(git, {
         skipReleaseLabels: [],
+        prereleaseBranches: ['next'],
         labels: defaultLabelDefinition,
         baseBranch: 'master'
       });
diff --git a/plugins/npm/__tests__/monorepo-log.test.ts b/plugins/npm/__tests__/monorepo-log.test.ts
index 79be1284..12def280 100644
--- a/plugins/npm/__tests__/monorepo-log.test.ts
+++ b/plugins/npm/__tests__/monorepo-log.test.ts
@@ -80,7 +80,11 @@ test('should create sections for packages', async () => {
     baseBranch: 'master'
   });
 
-  plugin.apply({ hooks, logger: dummyLog() } as Auto.Auto);
+  plugin.apply({
+    config: { prereleaseBranches: ['next'] },
+    hooks,
+    logger: dummyLog()
+  } as Auto.Auto);
   hooks.onCreateChangelog.call(changelog, Auto.SEMVER.patch);
   changelog.loadDefaultHooks();
 
@@ -124,7 +128,11 @@ test('should add versions for independent packages', async () => {
     baseBranch: 'master'
   });
 
-  plugin.apply({ hooks, logger: dummyLog() } as Auto.Auto);
+  plugin.apply({
+    config: { prereleaseBranches: ['next'] },
+    hooks,
+    logger: dummyLog()
+  } as Auto.Auto);
   hooks.onCreateChangelog.call(changelog, Auto.SEMVER.patch);
   changelog.loadDefaultHooks();
 
@@ -152,6 +160,7 @@ test('should create extra change logs for sub-packages', async () => {
   const update = jest.fn();
 
   plugin.apply({
+    config: { prereleaseBranches: ['next'] },
     hooks,
     logger: dummyLog(),
     release: {
diff --git a/plugins/npm/__tests__/npm.test.ts b/plugins/npm/__tests__/npm.test.ts
index 8d1c799c..3acec46e 100644
--- a/plugins/npm/__tests__/npm.test.ts
+++ b/plugins/npm/__tests__/npm.test.ts
@@ -161,7 +161,11 @@ describe('getAuthor', () => {
     const plugin = new NPMPlugin();
     const hooks = makeHooks();
 
-    plugin.apply({ hooks, logger: dummyLog() } as Auto.Auto);
+    plugin.apply({
+      config: { prereleaseBranches: ['next'] },
+      hooks,
+      logger: dummyLog()
+    } as Auto.Auto);
 
     readResult = `
       {
@@ -175,7 +179,11 @@ describe('getAuthor', () => {
     const plugin = new NPMPlugin();
     const hooks = makeHooks();
 
-    plugin.apply({ hooks, logger: dummyLog() } as Auto.Auto);
+    plugin.apply({
+      config: { prereleaseBranches: ['next'] },
+      hooks,
+      logger: dummyLog()
+    } as Auto.Auto);
 
     readResult = `
       {
@@ -196,7 +204,11 @@ describe('getAuthor', () => {
     const plugin = new NPMPlugin();
     const hooks = makeHooks();
 
-    plugin.apply({ hooks, logger: dummyLog() } as Auto.Auto);
+    plugin.apply({
+      config: { prereleaseBranches: ['next'] },
+      hooks,
+      logger: dummyLog()
+    } as Auto.Auto);
 
     readResult = `
       {
@@ -218,7 +230,11 @@ describe('getPreviousVersion', () => {
 
     existsSync.mockReturnValueOnce(false);
     existsSync.mockReturnValueOnce(true);
-    plugin.apply({ hooks, logger: dummyLog() } as Auto.Auto);
+    plugin.apply({
+      config: { prereleaseBranches: ['next'] },
+      hooks,
+      logger: dummyLog()
+    } as Auto.Auto);
 
     readResult = `
       {
@@ -234,7 +250,11 @@ describe('getPreviousVersion', () => {
 
     existsSync.mockReturnValueOnce(false);
     existsSync.mockReturnValueOnce(true);
-    plugin.apply({ hooks, logger: dummyLog() } as Auto.Auto);
+    plugin.apply({
+      config: { prereleaseBranches: ['next'] },
+      hooks,
+      logger: dummyLog()
+    } as Auto.Auto);
 
     readResult = `
       {
@@ -251,7 +271,11 @@ describe('getPreviousVersion', () => {
 
     existsSync.mockReturnValueOnce(true);
     monorepoPackages.mockReturnValueOnce([]);
-    plugin.apply({ hooks, logger: dummyLog() } as Auto.Auto);
+    plugin.apply({
+      config: { prereleaseBranches: ['next'] },
+      hooks,
+      logger: dummyLog()
+    } as Auto.Auto);
 
     readResult = `
       {
@@ -278,7 +302,11 @@ describe('getPreviousVersion', () => {
     // published version of test package
     exec.mockReturnValueOnce('0.1.2');
 
-    plugin.apply({ hooks, logger: dummyLog() } as Auto.Auto);
+    plugin.apply({
+      config: { prereleaseBranches: ['next'] },
+      hooks,
+      logger: dummyLog()
+    } as Auto.Auto);
 
     expect(await hooks.getPreviousVersion.promise(str => str)).toBe('0.1.2');
   });
@@ -306,6 +334,7 @@ describe('publish', () => {
     const hooks = makeHooks();
 
     plugin.apply(({
+      config: { prereleaseBranches: ['next'] },
       hooks,
       logger: dummyLog(),
       getCurrentVersion: () => '1.2.3',
@@ -331,7 +360,11 @@ describe('publish', () => {
     const logger = dummyLog();
     logger.logLevel = 'veryVerbose';
 
-    plugin.apply({ hooks, logger } as Auto.Auto);
+    plugin.apply({
+      config: { prereleaseBranches: ['next'] },
+      hooks,
+      logger
+    } as Auto.Auto);
 
     readResult = `
       {
@@ -354,7 +387,11 @@ describe('publish', () => {
     const plugin = new NPMPlugin();
     const hooks = makeHooks();
 
-    plugin.apply({ hooks, logger: dummyLog() } as Auto.Auto);
+    plugin.apply({
+      config: { prereleaseBranches: ['next'] },
+      hooks,
+      logger: dummyLog()
+    } as Auto.Auto);
 
     readResult = `
       {
@@ -375,7 +412,11 @@ describe('publish', () => {
     const plugin = new NPMPlugin();
     const hooks = makeHooks();
 
-    plugin.apply({ hooks, logger: dummyLog() } as Auto.Auto);
+    plugin.apply({
+      config: { prereleaseBranches: ['next'] },
+      hooks,
+      logger: dummyLog()
+    } as Auto.Auto);
 
     existsSync.mockReturnValueOnce(true);
     monorepoPackages.mockReturnValueOnce([]);
@@ -404,7 +445,11 @@ describe('publish', () => {
     const plugin = new NPMPlugin({ forcePublish: false });
     const hooks = makeHooks();
 
-    plugin.apply({ hooks, logger: dummyLog() } as Auto.Auto);
+    plugin.apply({
+      config: { prereleaseBranches: ['next'] },
+      hooks,
+      logger: dummyLog()
+    } as Auto.Auto);
 
     existsSync.mockReturnValueOnce(true);
     monorepoPackages.mockReturnValueOnce([]);
@@ -433,7 +478,11 @@ describe('publish', () => {
     const plugin = new NPMPlugin();
     const hooks = makeHooks();
 
-    plugin.apply({ hooks, logger: dummyLog() } as Auto.Auto);
+    plugin.apply({
+      config: { prereleaseBranches: ['next'] },
+      hooks,
+      logger: dummyLog()
+    } as Auto.Auto);
 
     existsSync.mockReturnValueOnce(true);
 
@@ -450,7 +499,11 @@ describe('publish', () => {
     const plugin = new NPMPlugin();
     const hooks = makeHooks();
 
-    plugin.apply({ hooks, logger: dummyLog() } as Auto.Auto);
+    plugin.apply({
+      config: { prereleaseBranches: ['next'] },
+      hooks,
+      logger: dummyLog()
+    } as Auto.Auto);
 
     exec.mockReturnValueOnce('');
     exec.mockReturnValueOnce('1.0.0');
@@ -475,7 +528,11 @@ describe('publish', () => {
     const plugin = new NPMPlugin();
     const hooks = makeHooks();
 
-    plugin.apply({ hooks, logger: dummyLog() } as Auto.Auto);
+    plugin.apply({
+      config: { prereleaseBranches: ['next'] },
+      hooks,
+      logger: dummyLog()
+    } as Auto.Auto);
 
     existsSync.mockReturnValueOnce(true);
     monorepoPackages.mockReturnValueOnce(monorepoPackagesResult);
@@ -506,7 +563,11 @@ describe('publish', () => {
     const plugin = new NPMPlugin();
     const hooks = makeHooks();
 
-    plugin.apply({ hooks, logger: dummyLog() } as Auto.Auto);
+    plugin.apply({
+      config: { prereleaseBranches: ['next'] },
+      hooks,
+      logger: dummyLog()
+    } as Auto.Auto);
 
     readResult = `
       {
@@ -522,7 +583,11 @@ describe('publish', () => {
     const plugin = new NPMPlugin();
     const hooks = makeHooks();
 
-    plugin.apply({ hooks, logger: dummyLog() } as Auto.Auto);
+    plugin.apply({
+      config: { prereleaseBranches: ['next'] },
+      hooks,
+      logger: dummyLog()
+    } as Auto.Auto);
 
     readResult = `
       {
@@ -546,6 +611,7 @@ describe('canary', () => {
     const hooks = makeHooks();
 
     plugin.apply(({
+      config: { prereleaseBranches: ['next'] },
       hooks,
       logger: dummyLog(),
       getCurrentVersion: () => '1.2.3',
@@ -570,6 +636,7 @@ describe('canary', () => {
     const hooks = makeHooks();
 
     plugin.apply(({
+      config: { prereleaseBranches: ['next'] },
       hooks,
       logger: dummyLog(),
       getCurrentVersion: () => '1.2.3',
@@ -592,6 +659,7 @@ describe('canary', () => {
     const hooks = makeHooks();
 
     plugin.apply(({
+      config: { prereleaseBranches: ['next'] },
       hooks,
       logger: dummyLog(),
       getCurrentVersion: () => '1.2.3',
@@ -612,7 +680,11 @@ describe('canary', () => {
     const plugin = new NPMPlugin();
     const hooks = makeHooks();
 
-    plugin.apply({ hooks, logger: dummyLog() } as Auto.Auto);
+    plugin.apply({
+      config: { prereleaseBranches: ['next'] },
+      hooks,
+      logger: dummyLog()
+    } as Auto.Auto);
     existsSync.mockReturnValueOnce(true);
 
     readResult = `
@@ -636,7 +708,11 @@ describe('canary', () => {
     const plugin = new NPMPlugin();
     const hooks = makeHooks();
 
-    plugin.apply({ hooks, logger: dummyLog() } as Auto.Auto);
+    plugin.apply({
+      config: { prereleaseBranches: ['next'] },
+      hooks,
+      logger: dummyLog()
+    } as Auto.Auto);
     existsSync.mockReturnValueOnce(true);
 
     readResult = `
@@ -661,7 +737,11 @@ describe('canary', () => {
     const plugin = new NPMPlugin();
     const hooks = makeHooks();
 
-    plugin.apply({ hooks, logger: dummyLog() } as Auto.Auto);
+    plugin.apply({
+      config: { prereleaseBranches: ['next'] },
+      hooks,
+      logger: dummyLog()
+    } as Auto.Auto);
     existsSync.mockReturnValueOnce(true);
     readFileSync.mockReturnValue('{ "version": "independent" }');
 
@@ -695,7 +775,11 @@ describe('canary', () => {
     const plugin = new NPMPlugin();
     const hooks = makeHooks();
 
-    plugin.apply({ hooks, logger: dummyLog() } as Auto.Auto);
+    plugin.apply({
+      config: { prereleaseBranches: ['next'] },
+      hooks,
+      logger: dummyLog()
+    } as Auto.Auto);
     existsSync.mockReturnValueOnce(true);
     readFileSync.mockReturnValue('{ "version": "independent" }');
 
diff --git a/plugins/released/__tests__/released-label.test.ts b/plugins/released/__tests__/released-label.test.ts
index 568c34e7..5010dc56 100644
--- a/plugins/released/__tests__/released-label.test.ts
+++ b/plugins/released/__tests__/released-label.test.ts
@@ -160,11 +160,9 @@ describe('release label plugin', () => {
     const releasedLabel = new ReleasedLabelPlugin();
     const autoHooks = makeHooks();
     releasedLabel.apply(({
+      config: { skipReleaseLabels: ['skip-release'] },
       hooks: autoHooks,
       labels: defaultLabelDefinition,
-      release: {
-        options: { skipReleaseLabels: ['skip-release'] }
-      },
       logger: dummyLog(),
       options: {},
       comment,
diff --git a/plugins/slack/__tests__/slack.test.ts b/plugins/slack/__tests__/slack.test.ts
index 6d43a943..c8205261 100644
--- a/plugins/slack/__tests__/slack.test.ts
+++ b/plugins/slack/__tests__/slack.test.ts
@@ -91,7 +91,7 @@ describe('postToSlack', () => {
     plugin.apply({
       hooks,
       options: {},
-      release: { options: { skipReleaseLabels: ['skip-release'] } }
+      config: { skipReleaseLabels: ['skip-release'] }
     } as Auto);
 
     await hooks.afterRelease.promise({