Repository: intuit/auto
Pull request #829 (2019-12-22 00:19:38)

fix: prevent slack from default publishing on prerelease branches
# What Changed

Prohibit slack to run on prerelease branches, but make it configurable so users can opt in if they do want the functionality. I didn't write tests or docs yet because I'd like the blessing from @hipstersmoothie that this is the right direction.

# Why

See #828 

Todo:

- [x] Add tests
- [x] Add docs

<!-- GITHUB_RELEASE PR BODY: canary-version -->
Published PR with canary version: <details><summary>Published under canary scope @auto-canary</summary>
- `@auto-canary/auto@8.7.4-canary.829.11185.0`
- `@auto-canary/core@8.7.4-canary.829.11185.0`
- `@auto-canary/all-contributors@8.7.4-canary.829.11185.0`
- `@auto-canary/chrome@8.7.4-canary.829.11185.0`
- `@auto-canary/conventional-commits@8.7.4-canary.829.11185.0`
- `@auto-canary/crates@8.7.4-canary.829.11185.0`
- `@auto-canary/first-time-contributor@8.7.4-canary.829.11185.0`
- `@auto-canary/git-tag@8.7.4-canary.829.11185.0`
- `@auto-canary/jira@8.7.4-canary.829.11185.0`
- `@auto-canary/maven@8.7.4-canary.829.11185.0`
- `@auto-canary/npm@8.7.4-canary.829.11185.0`
- `@auto-canary/omit-commits@8.7.4-canary.829.11185.0`
- `@auto-canary/omit-release-notes@8.7.4-canary.829.11185.0`
- `@auto-canary/released@8.7.4-canary.829.11185.0`
- `@auto-canary/s3@8.7.4-canary.829.11185.0`
- `@auto-canary/slack@8.7.4-canary.829.11185.0`
- `@auto-canary/twitter@8.7.4-canary.829.11185.0`
- `@auto-canary/upload-assets@8.7.4-canary.829.11185.0`</details>
<!-- GITHUB_RELEASE PR BODY: canary-version -->



Patch:
diff --git a/plugins/slack/README.md b/plugins/slack/README.md
index 5f9626aa..6c42d94f 100644
--- a/plugins/slack/README.md
+++ b/plugins/slack/README.md
@@ -14,7 +14,7 @@ yarn add -D @auto-it/slack
 
 ## Usage
 
-To use the plugin include it in your `.autorc`
+To use the plugin include it in your `.autorc`.
 
 ```json
 {
@@ -31,4 +31,30 @@ To use the plugin include it in your `.autorc`
 }
 ```
 
-This URL should be to you webhook. If you require a token to post to a slack hook, make sure you have a SLACK_TOKEN variable available on your environment. This token will be added to eh URL as a query string parameter.
+This URL should be to you webhook. If you require a token to post to a slack hook, make sure you have a `SLACK_TOKEN` variable available on your environment. This token will be added to eh URL as a query string parameter.
+
+### Next
+
+If you are using a `prerelease` branch like `next`, Slack will not post a message by default. This is done to avoid spamming your consumers every time you make a preview release. However, if you would like to configure it such that Slack _does_ post on prerelease, you can add the `publishPreRelease` to your `.autorc` like so:
+
+```json
+{
+  "plugins": [
+    [
+      "slack",
+      { "url": "https://url-to-your-slack-hook.com", "publishPreRelease": true }
+    ],
+    // or
+    ["slack", "https://url-to-your-slack-hook.com"],
+    // or
+    [
+      "slack",
+      {
+        "url": "https://url-to-your-slack-hook.com",
+        "atTarget": "here",
+        "publishPreRelease": true
+      }
+    ]
+  ]
+}
+```
diff --git a/plugins/slack/src/index.ts b/plugins/slack/src/index.ts
index 01cdbd4b..3573464f 100644
--- a/plugins/slack/src/index.ts
+++ b/plugins/slack/src/index.ts
@@ -1,5 +1,5 @@
 import { githubToSlack } from '@atomist/slack-messages';
-import { Auto, IPlugin } from '@auto-it/core';
+import { Auto, IPlugin, getCurrentBranch } from '@auto-it/core';
 import fetch from 'node-fetch';
 import join from 'url-join';
 
@@ -22,6 +22,8 @@ interface ISlackPluginOptions {
   url: string;
   /** Who to bother when posting to the channel */
   atTarget?: string;
+  /** Allow users to opt into having prereleases posted to slack */
+  publishPreRelease?: boolean;
 }
 
 /** Post your release notes to Slack during `auto release` */
@@ -39,7 +41,10 @@ export default class SlackPlugin implements IPlugin {
     } else {
       this.options = {
         url: options.url ? options.url : '',
-        atTarget: options.atTarget ? options.atTarget : 'channel'
+        atTarget: options.atTarget ? options.atTarget : 'channel',
+        publishPreRelease: options.publishPreRelease
+          ? options.publishPreRelease
+          : false
       };
     }
   }
@@ -49,6 +54,16 @@ export default class SlackPlugin implements IPlugin {
     auto.hooks.afterRelease.tapPromise(
       this.name,
       async ({ newVersion, commits, releaseNotes }) => {
+        // Avoid publishing on prerelease branches by default, but allow folks to opt in if they care to
+        const currentBranch = getCurrentBranch();
+        if (
+          currentBranch &&
+          auto.config?.prereleaseBranches?.includes(currentBranch) &&
+          !this.options.publishPreRelease
+        ) {
+          return;
+        }
+
         if (!newVersion) {
           return;
         }


Test patch:
diff --git a/plugins/slack/__tests__/slack.test.ts b/plugins/slack/__tests__/slack.test.ts
index 176f8542..58a0e779 100644
--- a/plugins/slack/__tests__/slack.test.ts
+++ b/plugins/slack/__tests__/slack.test.ts
@@ -3,6 +3,7 @@ import makeCommitFromMsg from '@auto-it/core/src/__tests__/make-commit-from-msg'
 import { dummyLog } from '@auto-it/core/src/utils/logger';
 import { makeHooks } from '@auto-it/core/src/utils/make-hooks';
 import { defaultLabels } from '@auto-it/core/dist/release';
+import { execSync } from 'child_process';
 
 import SlackPlugin from '../src';
 
@@ -16,6 +17,11 @@ beforeEach(() => {
   fetchSpy.mockClear();
 });
 
+// For the purpose of this test, we use the current branch as the "prerelease" branch to fake being on a "next" branch
+const nextBranch = execSync('git rev-parse --abbrev-ref HEAD', {
+  encoding: 'utf8'
+}).trim();
+
 const mockGit = {
   options: {
     owner: 'adierkens',
@@ -107,6 +113,88 @@ describe('postToSlack', () => {
     ).rejects.toBeInstanceOf(Error);
   });
 
+  test("doesn't post when prelease branch and using default prereleasePublish setting", async () => {
+    // @ts-ignore
+    const plugin = new SlackPlugin({
+      url: 'https://custom-slack-url',
+    });
+    const hooks = makeHooks();
+
+    jest.spyOn(plugin, 'postToSlack').mockImplementation();
+    // @ts-ignore
+    plugin.apply({
+      ...mockAuto,
+      hooks,
+      options: {},
+      config: {
+        prereleaseBranches: [nextBranch],
+        labels: defaultLabels
+      }
+    } as Auto);
+
+    await hooks.afterRelease.promise({
+      newVersion: '1.0.0',
+      lastRelease: '0.1.0',
+      commits: [makeCommitFromMsg('a patch')],
+      releaseNotes: '# My Notes'
+    });
+    expect(fetchSpy).not.toHaveBeenCalled();
+  });
+  test("doesn't post when prelease branch setting is false", async () => {
+    // @ts-ignore
+    const plugin = new SlackPlugin({
+      url: 'https://custom-slack-url',
+      publishPreRelease: false
+    });
+    const hooks = makeHooks();
+
+    jest.spyOn(plugin, 'postToSlack').mockImplementation();
+    // @ts-ignore
+    plugin.apply({
+      ...mockAuto,
+      hooks,
+      options: {},
+      config: {
+        prereleaseBranches: [nextBranch],
+        labels: defaultLabels
+      }
+    } as Auto);
+
+    await hooks.afterRelease.promise({
+      newVersion: '1.0.0',
+      lastRelease: '0.1.0',
+      commits: [makeCommitFromMsg('a patch')],
+      releaseNotes: '# My Notes'
+    });
+    expect(fetchSpy).not.toHaveBeenCalled();
+  });
+
+  test('posts when prelease branch setting is true', async () => {
+    // @ts-ignore
+    const plugin = new SlackPlugin({
+      url: 'https://custom-slack-url',
+      publishPreRelease: true
+    });
+    const hooks = makeHooks();
+
+    jest.spyOn(plugin, 'postToSlack').mockImplementation();
+    // @ts-ignore
+    plugin.apply({
+      ...mockAuto,
+      hooks,
+      options: {},
+      config: { prereleaseBranches: ['next'], labels: defaultLabels }
+    } as Auto);
+
+    await hooks.afterRelease.promise({
+      newVersion: '1.0.0',
+      lastRelease: '0.1.0',
+      commits: [makeCommitFromMsg('a patch')],
+      releaseNotes: '# My Notes'
+    });
+    expect(plugin.postToSlack).toHaveBeenCalledTimes(1);
+  });
+
   test('should warn when no token', async () => {
     const plugin = new SlackPlugin('https://custom-slack-url');
     const logger = dummyLog();