Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions .github/workflows/announce.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,17 @@ jobs:
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

# Both triggers end up with the same file, so the manual run and the automatic one cannot drift apart.
# Both triggers end up with the same file, so the manual run and the automatic one cannot drift apart. A step cannot
# change GITHUB_EVENT_PATH, which is why a manual run used to fail with "The event carries no release"; the script
# reads this file by its own name instead.
- name: Gather the release
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ github.event.release.tag_name || inputs.tag }}
run: |
set -euo pipefail
gh api "repos/${GITHUB_REPOSITORY}/releases/tags/${TAG}" > release.json
jq '{release: .}' release.json > event.json
echo "GITHUB_EVENT_PATH=$PWD/event.json" >> "$GITHUB_ENV"
echo "RELEASE_FILE=$PWD/release.json" >> "$GITHUB_ENV"

- name: Post it
env:
Expand Down
8 changes: 6 additions & 2 deletions tools/announce-release.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -220,9 +220,13 @@ async function post(webhook, message, loaded) {

async function main() {
const dryRun = process.argv.includes('--dry-run')
// A manual run has no release in GitHub's own event file, and a step cannot change GITHUB_EVENT_PATH, so the
// workflow fetches the release itself and names the file in RELEASE_FILE. An automatic run reads the event.
const releaseFile = process.env.RELEASE_FILE
const eventPath = process.env.GITHUB_EVENT_PATH
if (!eventPath) throw new Error('No GITHUB_EVENT_PATH; run this from the workflow, which writes one either way')
const { release } = JSON.parse(readFileSync(eventPath, 'utf8'))
if (!releaseFile && !eventPath) throw new Error('No RELEASE_FILE or GITHUB_EVENT_PATH; run this from the workflow')
const parsed = JSON.parse(readFileSync(releaseFile || eventPath, 'utf8'))
const release = releaseFile ? parsed : parsed.release
if (!release) throw new Error('The event carries no release')

if (release.draft) return console.log('Draft release, nothing posted.')
Expand Down
22 changes: 22 additions & 0 deletions tools/announce-release.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -198,3 +198,25 @@ test('two servers each receive their own ping, and the wall is downloaded once',
assert.doesNotMatch(mmd.message.content, /1553093586705449062/)
assert.ok(mmd.hasFile)
})

test('a manual re-post reads the release from RELEASE_FILE, which is the release itself and not an event around it', async () => {
const { spawn } = await import('node:child_process')
const { mkdtempSync, writeFileSync } = await import('node:fs')
const { tmpdir } = await import('node:os')
const { join } = await import('node:path')
const dir = mkdtempSync(join(tmpdir(), 'announce-'))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Import the helpers used by the new test

Running node --test tools/announce-release.test.mjs now fails immediately with ReferenceError: mkdtempSync is not defined, so the new test never exercises RELEASE_FILE. The required mkdtempSync, writeFileSync, tmpdir, join, and spawn bindings are declared only inside the preceding test and are not visible here; import them at module scope or within this test.

Useful? React with 👍 / 👎.

const file = join(dir, 'release.json')
writeFileSync(file, JSON.stringify(release))
const out = await new Promise((resolve) => {
let text = ''
const child = spawn(process.execPath, [new URL('./announce-release.mjs', import.meta.url).pathname, '--dry-run'], {
// GITHUB_EVENT_PATH points at an event with no release, as GitHub's own file does for a manual run.
env: { ...process.env, RELEASE_FILE: file, GITHUB_EVENT_PATH: join(dir, 'missing.json') },
})
child.stdout.on('data', (d) => (text += d))
child.on('exit', (code) => resolve({ code, text }))
})
assert.equal(out.code, 0)
assert.match(out.text, /Dry run\. This is the message:/)
assert.match(out.text, /v0\.6\.6|0\.6\.6/)
})
Loading