Skip to content

build(cli): post release notes and binary status to Slack - #1428

Open
Chase J (chajac) wants to merge 4 commits into
mainfrom
chajac/slack-release-notifications
Open

build(cli): post release notes and binary status to Slack#1428
Chase J (chajac) wants to merge 4 commits into
mainfrom
chajac/slack-release-notifications

Conversation

@chajac

@chajac Chase J (chajac) commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Note

PR body AI drafted & edited as needed

Overview of Changes

Releases currently announce themselves nowhere, the changesets action publishes to npm and creates the GitHub Release, but anyone following deployments has to poll the repo. The binaries matrix also runs with fail-fast: false, so a partially failed binary set is invisible unless someone opens the workflow run.

This adds a two-phase Slack notification driven entirely from release.yml, no hosted service, no incoming webhook.

  • scripts/slackReleaseMessage.ts: CLI entry — takes gh release view --json body,url,tagName[,assets] on stdin plus --phase publish|binaries --channel [--ts], prints a chat.postMessage / chat.update payload. Dependency free by design so the notify jobs skip bun install.
  • scripts/slackMrkdwn.ts: converts changeset markdown to Slack mrkdwn (bold/link/bullet translation, escaping) and splits notes into per-group blocks (✨ Minor changes / 🩹 Patch changes). Strips changesets' commit-hash bullet prefixes — noise in Slack; the GitHub-release link covers provenance.
  • scripts/slackReleaseBlocks.ts: validates the release JSON and assembles the Block Kit layout, including the binaries line — ⏳ Binaries building… at publish, per-target ✅/❌ on update. Sections are clamped under Slack's 3000-char limit.
  • release.yml: a Notify Slack of release step (gated on published == 'true', continue-on-error so a Slack outage can never fail a release) exports the message ts; a notify-binaries job (needs: [release, binaries], if: always() to report partial failures) updates the message in place. Binary status comes from diffing the release's uploaded assets against the five expected targets — matrix jobs share one output namespace, so assets are the reliable per-leg ground truth, and they also catch upload failures.

Testing

bun run test
bun run typecheck
bun run lint
bun run format:check
bun run knip
  • 23 new tests across slackMrkdwn.test.ts / slackReleaseBlocks.test.ts: mrkdwn conversion (escaping, hash stripping, dedent-vs-sub-bullet indent), change-group splitting, payload shape for both phases, ✅/❌ rendering against partial asset lists, 3000-char truncation, ts omitted from the publish payload.
  • End-to-end against the real v1.4.0 release with the live bot token and channel: message posted with release notes and ⏳ line, then updated in place to five ✅s via chat.update. Both API calls returned ok: true.

Checklist

  • Changes follow the code style of this project
  • Self-review completed
  • Tests added/updated
  • No breaking changes

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

The change adds Slack mrkdwn conversion, release-note grouping, release payload validation, binary status formatting, and a Bun CLI. The release workflow posts a publish announcement, exports its Slack timestamp, and updates the message after binary builds with uploaded or missing asset status. Tests cover formatting, validation, payload construction, truncation, and binary reporting.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ReleaseWorkflow
  participant slackReleaseMessage
  participant Slack
  participant BinaryBuilds
  ReleaseWorkflow->>slackReleaseMessage: generate publish payload
  slackReleaseMessage->>Slack: post release announcement
  Slack-->>ReleaseWorkflow: return message timestamp
  BinaryBuilds-->>ReleaseWorkflow: provide release assets
  ReleaseWorkflow->>slackReleaseMessage: generate binary status payload
  slackReleaseMessage->>Slack: update release announcement
Loading

Suggested reviewers: smonn

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title uses the required Conventional Commits format, an allowed type and scope, imperative wording, and a specific subject under 72 characters.
Description check ✅ Passed The description includes the required overview, testing details, checklist, test coverage, and operational behavior.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chajac/slack-release-notifications

Comment @coderabbitai help to get the list of available commands.

@chajac
Chase J (chajac) marked this pull request as ready for review July 31, 2026 17:07

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/release.yml:
- Around line 80-84: Add explicit curl timeouts to both Slack API calls,
`chat.postMessage` and `chat.update`, by applying `--connect-timeout` and/or
`--max-time` in their shared request options. Keep the existing request
payloads, headers, and response validation unchanged while ensuring unresponsive
Slack requests terminate promptly.
- Around line 121-134: Add continue-on-error: true to the “Update release
message with binary status” workflow step, matching the existing Slack publish
notification step so failures from chat.update or jq do not fail the release
workflow.

In `@scripts/slackMrkdwn.ts`:
- Around line 32-50: Extract the existing Slack mrkdwn escaping logic from
toMrkdwn into a reusable escapeMrkdwn helper, then apply it to each group title
in splitReleaseNotes before returning the mapped groups. Preserve the current
fixed groupTitles mappings and continue using toMrkdwn for group.text.

In `@scripts/slackReleaseBlocks.ts`:
- Around line 5-12: Add an automated validation for the expectedBinaries list
that compares its asset/label entries against the release matrix defined in
.github/workflows/release-binaries.yml, and fail clearly when targets are added,
removed, or changed so binariesLine cannot silently become stale.

In `@scripts/slackReleaseMessage.ts`:
- Around line 13-29: Add a colocated Bun test file for the CLI validation
surrounding parseArgs and the phase/channel/ts checks. Exercise missing --phase,
missing --channel, and binaries without --ts by spawning the script with
Bun.spawn or testing an extracted exported validator, and assert each case exits
unsuccessfully with the expected stderr usage/error message.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 0f4d8d5a-1c09-4b42-8fa7-23b83696c9dd

📥 Commits

Reviewing files that changed from the base of the PR and between 1e460b4 and 434db04.

📒 Files selected for processing (6)
  • .github/workflows/release.yml
  • scripts/slackMrkdwn.test.ts
  • scripts/slackMrkdwn.ts
  • scripts/slackReleaseBlocks.test.ts
  • scripts/slackReleaseBlocks.ts
  • scripts/slackReleaseMessage.ts

Comment thread .github/workflows/release.yml Outdated
Comment thread .github/workflows/release.yml
Comment thread scripts/slackMrkdwn.ts
Comment thread scripts/slackReleaseBlocks.ts
Comment thread scripts/slackReleaseMessage.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/slackMrkdwn.ts`:
- Line 51: Update the title mapping logic in scripts/slackMrkdwn.ts to use
groupTitles only when it owns the requested heading key, preventing inherited
keys such as toString or __proto__ from reaching escapeMrkdwn as non-string
values. Preserve undefined for unmapped headings, and add a regression test
covering a prototype-like heading.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: b9c2dc59-f542-4248-811f-b62f1f491a72

📥 Commits

Reviewing files that changed from the base of the PR and between 434db04 and 52dab94.

📒 Files selected for processing (5)
  • .github/workflows/release.yml
  • scripts/slackMrkdwn.test.ts
  • scripts/slackMrkdwn.ts
  • scripts/slackReleaseBlocks.test.ts
  • scripts/slackReleaseBlocks.ts

Comment thread scripts/slackMrkdwn.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants