Skip to content

ci(release): make the Discord announcement dispatchable on its own - #289

Merged
EtienneLescot merged 2 commits into
mainfrom
ci/announce-release-standalone
Aug 8, 2026
Merged

ci(release): make the Discord announcement dispatchable on its own#289
EtienneLescot merged 2 commits into
mainfrom
ci/announce-release-standalone

Conversation

@EtienneLescot

@EtienneLescot EtienneLescot commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

Why

Announcing a release only ever existed as the last step of prerelease.yml and promote.yml. Both promotions so far failed before reaching it:

  • v1.8.0Merge release branch into main failed on merge conflicts
  • v1.9.0 — same step, This branch can't be rebased

Each time the announcement was skipped along with everything downstream of the failure. Recovering it meant re-running a whole promotion over an already-tagged release — which re-attempts tagging and the main merge — so nobody was going to do that for a Discord post. v1.9.0 shipped unannounced.

What this does

Wraps the existing .github/scripts/discord-release-announce.mjs in a workflow_dispatch. No change to the script, and no change to either release workflow.

The message is derived entirely from the tag and the matching milestone, so a late announcement is byte-identical to the one that would have gone out on time. That is what makes this safe to run after the fact rather than a reconstruction.

One non-obvious detail

The destination is chosen by blanking one of the two channel variables, not by the KIND input:

DISCORD_RELEASE_CHANNEL_ID: ${{ inputs.kind == 'stable' && vars.DISCORD_RELEASE_CHANNEL_ID || '' }}
DISCORD_RC_TESTING_CHANNEL_ID: ${{ inputs.kind == 'rc' && vars.DISCORD_RC_TESTING_CHANNEL_ID || '' }}

because that is what the script actually branches on — it prefers DISCORD_RC_TESTING_CHANNEL_ID whenever it is non-empty, and KIND only selects the embed's wording and colour. Setting both would post a "released" embed into the RC testing channel.

After merging

gh workflow run announce-release.yml -f tag=v1.9.0 -f kind=stable

That sends the announcement v1.9.0 never got. It is safe to re-run — the only consequence of a double dispatch is a duplicate post, and allowed_mentions is empty so nothing is pinged either way.

Not addressed here

The reason promotions keep failing at the main-sync step is separate and still open: main and the release branch accumulate the same fixes under different SHAs, so GitHub's rebase-merge replays commits already present. Worth its own change — this PR only stops one recurring casualty of it.

Summary by CodeRabbit

  • New Features

    • Added a manually triggered workflow for announcing releases in Discord.
    • Supports stable and release-candidate announcements with optional custom messaging.
  • Bug Fixes

    • Release announcements now report failures clearly when strict handling is enabled.
    • Non-strict announcements continue gracefully when posting issues occur.
  • Tests

    • Added coverage for successful announcements, configuration errors, lookup failures, and posting failures.

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The pull request adds a manually dispatched GitHub Actions workflow for Discord release announcements. The announcement script now supports strict failure reporting, with tests covering strict and non-strict execution.

Changes

Release announcement workflow

Layer / File(s) Summary
Manual dispatch and Discord announcement
.github/workflows/announce-release.yml
The workflow accepts release inputs, sets up Node.js, selects the stable or RC channel, and runs the announcement script with release metadata and STRICT=1.
Strict failure handling and compatibility
.github/scripts/discord-release-announce.mjs
The script reports missing configuration, channel lookup errors, and posting errors as workflow failures when STRICT is enabled. Non-strict runs retain non-fatal behavior.
Strict-mode validation
.github/scripts/discord-release-announce.test.mjs
Tests cover strict failures, successful strict announcements, non-strict failures, mocked setFailed calls, and environment cleanup.

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

Sequence Diagram(s)

sequenceDiagram
  actor ReleaseOperator
  participant GitHubActions
  participant DiscordReleaseAnnounce
  participant Discord

  ReleaseOperator->>GitHubActions: Dispatch workflow with tag, kind, and extra text
  GitHubActions->>DiscordReleaseAnnounce: Run with channel, tokens, release metadata, and STRICT=1
  DiscordReleaseAnnounce->>Discord: Look up channel and post announcement
  Discord-->>DiscordReleaseAnnounce: Return lookup or posting result
  DiscordReleaseAnnounce-->>GitHubActions: Report success or workflow failure
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description explains the change and motivation, but it omits most required template sections, including issue, change type, release impact, desktop impact, screenshots, and testing. Complete the required template sections and document testing commands, results, and any applicable release or platform impact.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: making Discord release announcements independently dispatchable.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci/announce-release-standalone

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@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 @.github/workflows/announce-release.yml:
- Line 60: Update the announcement script invocation in the workflow and the
corresponding logic in discord-release-announce.mjs to support strict mode for
manual announcements. Enable strict mode from announce-release.yml, and ensure
missing Discord configuration, channel lookup failures, and post failures exit
with a non-zero status while preserving current behavior when strict mode is not
enabled.
🪄 Autofix

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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2b72a33b-5ca6-48d5-bf53-2bc95d26de24

📥 Commits

Reviewing files that changed from the base of the PR and between af1ff35 and d206fa2.

📒 Files selected for processing (1)
  • .github/workflows/announce-release.yml

Comment thread .github/workflows/announce-release.yml
Announcing a release only ever existed as the final step of prerelease.yml and
promote.yml. Both promotions so far failed before reaching it — v1.8.0 on a
merge conflict, v1.9.0 on a non-rebasable sync branch — and each time the
announcement was skipped along with everything downstream of the failure.

Recovering it meant re-running a promotion over an already-tagged release,
which re-attempts tagging and the main merge; nobody was going to do that for a
Discord post, so v1.9.0 simply shipped unannounced.

This wraps the existing discord-release-announce.mjs in a workflow_dispatch and
changes nothing else. The message is derived entirely from the tag and the
matching milestone, so a late announcement is identical to the one that would
have gone out on time.

The destination is selected by blanking one of the two channel variables rather
than by KIND, because that is what the script actually branches on: it prefers
DISCORD_RC_TESTING_CHANNEL_ID whenever it is non-empty.
discord-release-announce.mjs exits 0 on four paths that never announce: no
STABLE_TAG, missing bot token or channel id, a failed channel lookup, and a
failed post. That is correct for prerelease.yml and promote.yml — the release
is already published there, the announcement is bookkeeping, and failing the
job would misreport a successful release.

A manual dispatch has the opposite contract. This workflow exists *because* an
announcement was missed, so a green run that posted nothing recreates the exact
failure it was invoked to repair — which is how v1.9.0 shipped unannounced.

STRICT, set only by announce-release.yml, makes those four paths exit non-zero
via setFailed. Default behaviour is unchanged, and the existing suite still
passes untouched. The catch deliberately does not route through bail(): it is
the last statement, and 'handles 4xx gracefully without throwing' pins that the
module finishes on its own rather than calling process.exit.

Five tests added, covering each strict path, the nominal announcement, and the
non-strict case staying non-fatal.
@EtienneLescot
EtienneLescot force-pushed the ci/announce-release-standalone branch from d206fa2 to a65d1e4 Compare August 8, 2026 21:23

@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.

🧹 Nitpick comments (1)
.github/scripts/discord-release-announce.test.mjs (1)

202-205: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add strict-mode coverage for a missing STABLE_TAG.

The strict test set does not exercise the bail("STABLE_TAG missing; skipping.") branch. Add a test that sets STRICT: "1" and an empty STABLE_TAG. Assert setFailed receives the missing-tag message.

Proposed test
+	it("fails when the release tag is missing", async () => {
+		await expect(
+			loadScript({ ...BASE_ENV, STABLE_TAG: "", STRICT: "1", DISCORD_RELEASE_CHANNEL_ID: "123" }),
+		).rejects.toThrow(exits1);
+		expect(vi.mocked(setFailed)).toHaveBeenCalledWith(expect.stringContaining("STABLE_TAG missing"));
+	});
+
 	it("fails when the Discord configuration is missing", async () => {
🤖 Prompt for 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.

In @.github/scripts/discord-release-announce.test.mjs around lines 202 - 205,
Add a strict-mode test alongside the existing missing Discord configuration test
that invokes loadScript with STRICT set to "1" and an empty STABLE_TAG, then
assert setFailed is called with the exact missing-tag message "STABLE_TAG
missing; skipping.".
🤖 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.

Nitpick comments:
In @.github/scripts/discord-release-announce.test.mjs:
- Around line 202-205: Add a strict-mode test alongside the existing missing
Discord configuration test that invokes loadScript with STRICT set to "1" and an
empty STABLE_TAG, then assert setFailed is called with the exact missing-tag
message "STABLE_TAG missing; skipping.".

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2ac5edba-23e4-4eb6-951f-4a53226bb3ef

📥 Commits

Reviewing files that changed from the base of the PR and between d206fa2 and a65d1e4.

📒 Files selected for processing (3)
  • .github/scripts/discord-release-announce.mjs
  • .github/scripts/discord-release-announce.test.mjs
  • .github/workflows/announce-release.yml

@EtienneLescot
EtienneLescot merged commit 446d2e0 into main Aug 8, 2026
17 checks passed
@EtienneLescot
EtienneLescot deleted the ci/announce-release-standalone branch August 8, 2026 21:26
@EtienneLescot

Copy link
Copy Markdown
Collaborator Author

Nitpick applied — the strict set covered three of the four bail() paths and missed STABLE_TAG. Added fails when the release tag is missing, asserting setFailed receives the missing-tag message. 13 tests, suite green.

@EtienneLescot

Copy link
Copy Markdown
Collaborator Author

Correction to my previous comment: this PR merged before that test landed, so the nitpick fix is not in 446d2e00. Moved to #314 against main. The strict mode itself did merge here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant