From d206fa238b41917aa959685dbedb1fc4c9eae52d Mon Sep 17 00:00:00 2001 From: Etienne Lescot Date: Wed, 5 Aug 2026 17:57:56 +0200 Subject: [PATCH] ci(release): make the Discord announcement dispatchable on its own MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- .github/workflows/announce-release.yml | 60 ++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 .github/workflows/announce-release.yml diff --git a/.github/workflows/announce-release.yml b/.github/workflows/announce-release.yml new file mode 100644 index 000000000..56b840f68 --- /dev/null +++ b/.github/workflows/announce-release.yml @@ -0,0 +1,60 @@ +# Announcing a release lived only inside prerelease.yml and promote.yml, as the +# last step of each. 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 silently skipped along with everything downstream of the +# failure, with no way to send it afterwards short of re-running the whole +# promotion over an already-tagged release. +# +# This exposes the same script on its own, so a missed announcement is a dispatch +# rather than a recovery operation. It reads nothing but the tag and the matching +# milestone, so it produces the identical message whenever it runs. +name: Announce a release on Discord + +on: + workflow_dispatch: + inputs: + tag: + description: "Release tag to announce (e.g. v1.9.0)" + required: true + type: string + kind: + description: "stable posts to the release channel, rc to the testing channel" + required: true + type: choice + options: [stable, rc] + default: stable + release_notes_extra: + description: "Optional message prepended to the announcement" + required: false + type: string + default: "" + +permissions: + contents: read + +jobs: + announce: + name: Announce ${{ inputs.tag }} + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: ./.github/actions/setup + + - name: Announce on Discord + env: + DISCORD_BOT_TOKEN: ${{ secrets.DISCORD_BOT_TOKEN }} + # The script prefers the RC channel whenever that variable is non-empty, + # so exactly one of these may be set — blanking the other is what selects + # the destination, not the KIND value. + 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 || '' }} + # Only used to list the closed issues of the matching milestone; the + # announcement still posts without it, just without that section. + GITHUB_TOKEN: ${{ secrets.OPENSCREEN_RELEASE_TOKEN }} + STABLE_TAG: ${{ inputs.tag }} + EXTRA: ${{ inputs.release_notes_extra }} + KIND: ${{ inputs.kind }} + run: node .github/scripts/discord-release-announce.mjs