From b06441983b413f7346a91bcc8d7b8d95bbdd1472 Mon Sep 17 00:00:00 2001 From: Trent Mick Date: Wed, 18 Dec 2024 16:28:05 -0800 Subject: [PATCH 1/2] chore: Slack notifications for issue/PR open/close actions I am proposing this as an alternative to the issue and PR Slack notifications we currently get from https://github.com/integrations/slack because of the following issues with that integration: - It is over-wordy, resulting in notification noise masking any other conversation in the channel. This lowers the signal-to-noise ratio in the channel, which discourages meaningful conversation. - It includes some body content from issues/PRs. This may be a nice idea for a repo with commonly simple and short issue/PR descriptions. However, in general it is just spam. It can also get silly for PRs that have large `
` blocks, which the Slack rendering doesn't hide. E.g. https://github.com/elastic/opbeans-node/pull/304 - It includes some issue metadata, sometimes some chat-ops buttons ("Comment", "Close"). - It includes a variable-height summary of actions/checks on PRs. This sounds nice, but it results in dynamic-height content in the chat area that discourages ongoing conversation. - It `@-`names people listed as reviewers for PRs and makes a *threads* of every PR to show when it is merged. This sounds like a nice idea, but in practice means that the "Threads" section of Slack is spammed with useless unread threads for merged PRs that I've reviewed. - Basically the Slack integration is trying to be a fancy full-on chat-ops thingy, and I don't want the noise. I want higher signal. - It doesn't support ignoring some PR categories: specifically ignoring dependabot/renovate PRs. Currently we have those scheduled for Sunday. Every Monday morning is a multi-page scroll of useless notifications about regular dependabot maintenance work. It is very easy to lose *meaningful* conversation from Friday or over the weekend in that noise. --- .github/workflows/slack.yml | 118 ++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 .github/workflows/slack.yml diff --git a/.github/workflows/slack.yml b/.github/workflows/slack.yml new file mode 100644 index 0000000..e683c6e --- /dev/null +++ b/.github/workflows/slack.yml @@ -0,0 +1,118 @@ +# Post a slack message something like the following for issue and PR actions: +# <$url|$title> +# | $repo#$num · issue opened by $user +# +# Configuration: +# 1. Set `SLACK_CHANNEL`. +# 2. Add a `SLACK_BOT_TOKEN` secret to your repo. This is the "Bot User OAuth +# Token" from the "OAuth & Permissions" section of your Slack App +# (https://api.slack.com/apps). The token must have the `chat:write` +# permission. +# 3. Optionally tweak the `if:` and `on:` sections below to control which issue +# and PR events are skipped. + +name: slack + +env: + SLACK_CHANNEL: "#apm-agent-node" + +on: + issues: + types: [opened, reopened, closed] + pull_request: + types: [opened, ready_for_review, reopened, closed] + +jobs: + slack: + # Skip notification if: + # - dependabot PRs, too noisy + # - draft PRs + if: ${{ github.event.pull_request.user.login != 'dependabot[bot]' || !(github.event.action == 'opened' && github.event.pull_request.draft) }} + runs-on: ubuntu-latest + steps: + - name: Prepare Slack message + id: prepare + shell: python + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: | + import os + from pprint import pprint + import json + from html import escape + + CLOSED_RED = '#cb2431' + GITHUB_BLACK = '#24292f' + MERGED_PURPLE = '#6f42c1' + OPEN_GREEN = '#36a64f' + DRAFT_GRAY = '#6a737d' + + ctx = json.loads(os.environ["GITHUB_CONTEXT"]) + pprint(ctx) // debug dump for now + event = ctx["event"] + action = event["action"] + if "issue" in event: + title = event["issue"]["title"] + url = event["issue"]["html_url"] + num = event["issue"]["number"] + action_str = f"issue {action}" + color = { + "opened": OPEN_GREEN, + "reopened": OPEN_GREEN, + "closed": CLOSED_RED, + }.get(action, "#ffffff") + elif "pull_request" in event: + title = event["pull_request"]["title"] + url = event["pull_request"]["html_url"] + num = event["pull_request"]["number"] + if action == "closed": + if event["pull_request"]["merged"]: + action_str = "PR merged" + color = MERGED_PURPLE + else: + action_str = "PR closed" + color = CLOSED_RED + elif event["pull_request"]["draft"]: + action_str = "PR in draft" + color = DRAFT_GRAY + elif action == "ready_for_review": + action_str = "PR ready for review" + color = OPEN_GREEN + elif: + action_str = "PR opened" + color = OPEN_GREEN + else: + pprint(ctx) + raise ValueError('unexpected event: not an issue or PR event') + + # Use https://app.slack.com/block-kit-builder to play with styling. + payload = { + "channel": os.environ["SLACK_CHANNEL"], + "text": f"<{url}|{escape(title)}>", # escape angle-brackets + "attachments": [ + { + "color": color, + "blocks": [ + { + "type": "context", + "elements": [ + { + "type": "mrkdwn", + "text": f"{ctx['repository']}#{num} · *{action_str}* by {event['sender']['login']}" + } + ] + } + ] + } + ] + } + + with open(os.environ.get("GITHUB_OUTPUT"), "a") as f: + f.write("payload={}".format(json.dumps(payload))) + + - name: Post Slack message + uses: slackapi/slack-github-action@v2.0.0 + with: + method: chat.postMessage + token: ${{ secrets.SLACK_BOT_TOKEN }} + payload: ${{ steps.prepare.outputs.payload }} From 15b2c98741e3ab1b87c9c9f890850ee5a26232fc Mon Sep 17 00:00:00 2001 From: Trent Mick Date: Wed, 18 Dec 2024 16:47:36 -0800 Subject: [PATCH 2/2] oops, wrong lang --- .github/workflows/slack.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/slack.yml b/.github/workflows/slack.yml index e683c6e..bf395eb 100644 --- a/.github/workflows/slack.yml +++ b/.github/workflows/slack.yml @@ -48,7 +48,7 @@ jobs: DRAFT_GRAY = '#6a737d' ctx = json.loads(os.environ["GITHUB_CONTEXT"]) - pprint(ctx) // debug dump for now + pprint(ctx) # debug dump for now event = ctx["event"] action = event["action"] if "issue" in event: