Skip to content

[ENH] Comment on PRs/issues with their release tag#2437

Open
yarikoptic wants to merge 3 commits into
masterfrom
enh-released-in
Open

[ENH] Comment on PRs/issues with their release tag#2437
yarikoptic wants to merge 3 commits into
masterfrom
enh-released-in

Conversation

@yarikoptic

@yarikoptic yarikoptic commented Jun 1, 2026

Copy link
Copy Markdown
Collaborator

Closes #2436.

Summary

After each GitHub release publication, post a comment on every PR included
in the release ("PR released in vX.Y.Z") and on every issue those PRs
closed via Fixes #N / Closes #N ("Issue fixed in vX.Y.Z"). Modeled on
the corresponding logic in datalad/release-action's
make_release_comments — see e.g. datalad/datalad#7832 (comment)
for the effect.

The component pieces:

  • tools/announce_release.py — standalone uv run script that walks
    git log <prev>..<tag> --first-parent to discover PRs in a release
    (handles both squash … (#NNN) subjects and Merge pull request #NNN
    merges), queries closing issues via GraphQL, and posts comments via
    REST. Dry-run by default; --post actually comments. --retroactive [--since TAG] backfills past releases.
  • .github/workflows/publish_schema.yml — rather than a new workflow,
    the existing release-adjacent workflow gets a release: published
    trigger and a new announce_release job. The existing publish job is
    gated to push events only so it doesn't fire on release events.
  • Release_Protocol.md — short note in step 8 + pointer to the script
    for back-filling pre-existing releases.
  • tools/tests/test_announce_release.py — 28 pytest cases covering
    tag-filter regex, comment/link formatting, prs_in_range parsing of
    both commit-subject styles, release_tags filtering, select_tags
    selection logic, and CLI behaviour (argparse rejections, --help
    without token, missing-token error, unknown-tag reported before token).
    Runs standalone via its own # /// script uv-run header.

Idempotency, live-tested

Before posting, the script checks for an existing comment with the exact
target body via GraphQL pagination, so re-runs (workflow or hand-run) do
not duplicate. I exercised this on v1.11.1 — the first run was
interrupted partway through, the second one cleanly skipped the
already-annotated PRs/issues and processed the rest:

Live-test output (after interrupted initial run)
tools/announce_release.py v1.11.1 --post

=== Release v1.11.1 (prev: v1.11.0) ===
  10 PR(s) in this release
  - PR #2346 https://github.com/bids-standard/bids-specification/pull/2346 — comment already exists, skip — '[FIX] Add emg to timeseries rule for physio/stim files'
  - PR #2345 https://github.com/bids-standard/bids-specification/pull/2345 — comment already exists, skip — 'fix: Allow mkdocs to render links in glossary'
      issue #2242 https://github.com/bids-standard/bids-specification/issues/2242 — comment already exists, skip
  - PR #2344 https://github.com/bids-standard/bids-specification/pull/2344 — [POST] comment on PR — '[FIX] Use http://www.dicomlookup.com for DICOM tags'
  - PR #2331 https://github.com/bids-standard/bids-specification/pull/2331 — [POST] comment on PR — '[FIX] Minor syntax updates on microscopy page'
  - PR #2347 https://github.com/bids-standard/bids-specification/pull/2347 — [POST] comment on PR — '[pre-commit.ci] pre-commit autoupdate'
  - PR #2337 https://github.com/bids-standard/bids-specification/pull/2337 — [POST] comment on PR — 'chore(deps): bump aiohttp from 3.12.15 to 3.13.3'
  - PR #2336 https://github.com/bids-standard/bids-specification/pull/2336 — [POST] comment on PR — 'chore(deps): bump urllib3 from 2.5.0 to 2.6.3'
  - PR #2335 https://github.com/bids-standard/bids-specification/pull/2335 — [POST] comment on PR — 'chore(deps): bump the build-dependencies group with 8 updates'
  - PR #2323 https://github.com/bids-standard/bids-specification/pull/2323 — [POST] comment on PR — '[pre-commit.ci] pre-commit autoupdate'
  - PR #2318 https://github.com/bids-standard/bids-specification/pull/2318 — [POST] comment on PR — 'chore(deps): bump lodash from 4.17.21 to 4.17.23'

so can see the effect on e.g.

How to dry-run / backfill manually

# Dry-run one release
GITHUB_TOKEN=$(gh auth token) tools/announce_release.py v1.11.1

# Dry-run all historical releases since a starting point
GITHUB_TOKEN=$(gh auth token) tools/announce_release.py --retroactive --since v1.10.0

# Actually post (write-scoped token required)
GITHUB_TOKEN=$(gh auth token) tools/announce_release.py --post v1.11.1

URLs are inlined next to each #NNN so terminals autolink them.

Here is what I get if I run it for prior release
> tools/announce_release.py v1.11.0

=== Release v1.11.0 (prev: v1.10.1) ===
  58 PR(s) in this release
  - PR #2325 https://github.com/bids-standard/bids-specification/pull/2325 — [DRY] comment on PR — 'REL: 1.11.0'
  - PR #2334 https://github.com/bids-standard/bids-specification/pull/2334 — [DRY] comment on PR — 'chore(deps): bump prettier from 3.7.4 to 3.8.0 in the node-utilities group'
  - PR #2322 https://github.com/bids-standard/bids-specification/pull/2322 — [DRY] comment on PR — 'fix(schema): Check SpatialReference for space, template entities'
  - PR #2019 https://github.com/bids-standard/bids-specification/pull/2019 — [DRY] comment on PR — '[ENH] Add another example to inheritance principle for .json without entities'
  - PR #2210 https://github.com/bids-standard/bids-specification/pull/2210 — [DRY] comment on PR — '[ENH] Clarify that "raw dataset" source data in example layout is a raw BIDS dataset'
  - PR #2315 https://github.com/bids-standard/bids-specification/pull/2315 — [DRY] comment on PR — '[FIX] Update and render schema definition of dataset_description.json'
  - PR #2306 https://github.com/bids-standard/bids-specification/pull/2306 — [DRY] comment on PR — 'Add pre-commit invoked checker to spot bad JSON in .md and also fix detected bad JSONs'
  - PR #2321 https://github.com/bids-standard/bids-specification/pull/2321 — [DRY] comment on PR — '[FIX] Update `Diffusion data in FSL` link'
  - PR #2319 https://github.com/bids-standard/bids-specification/pull/2319 — [DRY] comment on PR — 'Fix a single use of ManufacturerModelName in qmri.md (should be ManufacturersModelName)'
  - PR #2281 https://github.com/bids-standard/bids-specification/pull/2281 — [DRY] comment on PR — '[FIX] Add desc- entity name into descriptions.tsv example'
  - PR #2297 https://github.com/bids-standard/bids-specification/pull/2297 — [DRY] comment on PR — '[FIX] Update navigation with respect to the `bids-starter-kit`'
  - PR #1915 https://github.com/bids-standard/bids-specification/pull/1915 — [DRY] comment on PR — '[ENH] Add human statement to emphasize that _desc is the last entity'
  - PR #2304 https://github.com/bids-standard/bids-specification/pull/2304 — [DRY] comment on PR — '[FIX] Correct `bval` and clarify `bvec` descriptions'
  - PR #2310 https://github.com/bids-standard/bids-specification/pull/2310 — [DRY] comment on PR — '[Schema][Fix] add checks for multiple frame consistency issues '
  - PR #2316 https://github.com/bids-standard/bids-specification/pull/2316 — [DRY] comment on PR — 'fix: correct schema file path in eye tracking documentation comment'
  - PR #2314 https://github.com/bids-standard/bids-specification/pull/2314 — [DRY] comment on PR — '[pre-commit.ci] pre-commit autoupdate'
  - PR #2308 https://github.com/bids-standard/bids-specification/pull/2308 — [DRY] comment on PR — '[FIX] Add DWI recommended metadata table'
  - PR #1128 https://github.com/bids-standard/bids-specification/pull/1128 — [DRY] comment on PR — '[ENH] BEP020 - Eye Tracking'
  - PR #2280 https://github.com/bids-standard/bids-specification/pull/2280 — [DRY] comment on PR — '[pre-commit.ci] pre-commit autoupdate'
  - PR #2294 https://github.com/bids-standard/bids-specification/pull/2294 — [DRY] comment on PR — '[ENH] Make Pharmaceutical metadata terms less PET-specific'
  - PR #1714 https://github.com/bids-standard/bids-specification/pull/1714 — [DRY] comment on PR — '[ENH] BEP038 - Atlases'
  - PR #2291 https://github.com/bids-standard/bids-specification/pull/2291 — [DRY] comment on PR — 'chore(deps): bump the actions-infrastructure group with 3 updates'
  - PR #2292 https://github.com/bids-standard/bids-specification/pull/2292 — [DRY] comment on PR — 'chore(deps): bump the node-utilities group with 2 updates'
  - PR #2288 https://github.com/bids-standard/bids-specification/pull/2288 — [DRY] comment on PR — 'chore: Ignore redirect warnings in link checks'
  - PR #2271 https://github.com/bids-standard/bids-specification/pull/2271 — [DRY] comment on PR — 'chore: Add "serve" rule to Makefile and provide description to what actions available'
  - PR #2237 https://github.com/bids-standard/bids-specification/pull/2237 — [DRY] comment on PR — '[ENH] Updated HED Version to 8.4.0 in examples'
  - PR #2244 https://github.com/bids-standard/bids-specification/pull/2244 — [DRY] comment on PR — 'chore(deps): bump the actions-infrastructure group with 3 updates'
  - PR #1998 https://github.com/bids-standard/bids-specification/pull/1998 — [DRY] comment on PR — '[ENH] BEP042 - extension for electromyography (EMG)'
      issue #1371 https://github.com/bids-standard/bids-specification/issues/1371 — [DRY] comment on issue
  - PR #2270 https://github.com/bids-standard/bids-specification/pull/2270 — [DRY] comment on PR — '[pre-commit.ci] pre-commit autoupdate'
  - PR #2253 https://github.com/bids-standard/bids-specification/pull/2253 — [DRY] comment on PR — '[FIX] Correct typos and formatting in specification documents'
  - PR #2268 https://github.com/bids-standard/bids-specification/pull/2268 — [DRY] comment on PR — '[FIX] Fixed typo in events.md'
  - PR #2259 https://github.com/bids-standard/bids-specification/pull/2259 — [DRY] comment on PR — 'Adding bclenet as BIDS maintainer'
  - PR #2266 https://github.com/bids-standard/bids-specification/pull/2266 — [DRY] comment on PR — 'chore(deps): bump glob from 10.4.5 to 10.5.0'
  - PR #2265 https://github.com/bids-standard/bids-specification/pull/2265 — [DRY] comment on PR — '[FIX] Allowing to render JSON null type'
      issue #2260 https://github.com/bids-standard/bids-specification/issues/2260 — [DRY] comment on issue
  - PR #2245 https://github.com/bids-standard/bids-specification/pull/2245 — [DRY] comment on PR — 'chore(deps): bump astral-sh/setup-uv from 6 to 7'
  - PR #2140 https://github.com/bids-standard/bids-specification/pull/2140 — [DRY] comment on PR — 'feat(schema): Add meta.templates and allow for composing multiple references'
  - PR #2233 https://github.com/bids-standard/bids-specification/pull/2233 — [DRY] comment on PR — 'DOCS: Add ignore rule for rrid.site in link checker'
  - PR #2232 https://github.com/bids-standard/bids-specification/pull/2232 — [DRY] comment on PR — 'DOCS: Fix HED resources link in hierarchical event descriptors documentation'
  - PR #2229 https://github.com/bids-standard/bids-specification/pull/2229 — [DRY] comment on PR — '[pre-commit.ci] pre-commit autoupdate'
  - PR #2216 https://github.com/bids-standard/bids-specification/pull/2216 — [DRY] comment on PR — '[INFRA] Use full page width'
  - PR #2178 https://github.com/bids-standard/bids-specification/pull/2178 — [DRY] comment on PR — '[SCHEMA][MISC][WIP] Update schema docs with BEP Google doc to schema examples.'
  - PR #2225 https://github.com/bids-standard/bids-specification/pull/2225 — [DRY] comment on PR — '[MISC]: Fix placement of picture for Benjamin Dichter'
  - PR #2226 https://github.com/bids-standard/bids-specification/pull/2226 — [DRY] comment on PR — '[INFRA] Replace npm-requirements hack with package.json'
  - PR #2223 https://github.com/bids-standard/bids-specification/pull/2223 — [DRY] comment on PR — 'chore(deps): bump the actions-infrastructure group with 2 updates'
  - PR #2203 https://github.com/bids-standard/bids-specification/pull/2203 — [DRY] comment on PR — '[ENH] Clarify that "source datasets" do not have to be BIDS, and provide definitions for DOI and URL'
  - PR #2217 https://github.com/bids-standard/bids-specification/pull/2217 — [DRY] comment on PR — '[pre-commit.ci] pre-commit autoupdate'
  - PR #1927 https://github.com/bids-standard/bids-specification/pull/1927 — [DRY] comment on PR — '[ENH] Clearly define dual templates (fsaverage, fsaverageSym, and fsLR) in coordinate systems appendix'
      issue #1901 https://github.com/bids-standard/bids-specification/issues/1901 — [DRY] comment on issue
  - PR #2196 https://github.com/bids-standard/bids-specification/pull/2196 — [DRY] comment on PR — '[INFRA] Remove changelog generator CI workflow'
  - PR #2214 https://github.com/bids-standard/bids-specification/pull/2214 — [DRY] comment on PR — 'feat: Add unique() function to schema expression language'
  - PR #2212 https://github.com/bids-standard/bids-specification/pull/2212 — [DRY] comment on PR — '[pre-commit.ci] pre-commit autoupdate'
  - PR #2209 https://github.com/bids-standard/bids-specification/pull/2209 — [DRY] comment on PR — '[ENH] Add entity tables for motion, NIRS and MRS'
  - PR #2207 https://github.com/bids-standard/bids-specification/pull/2207 — [DRY] comment on PR — 'Update current BIDS maintainers list'
  - PR #2205 https://github.com/bids-standard/bids-specification/pull/2205 — [DRY] comment on PR — '[FIX] Update links in common-principles.md'
      issue #2204 https://github.com/bids-standard/bids-specification/issues/2204 — [DRY] comment on issue
  - PR #2201 https://github.com/bids-standard/bids-specification/pull/2201 — [DRY] comment on PR — '[FIX] Update BIDS Starter Kit links'
  - PR #2200 https://github.com/bids-standard/bids-specification/pull/2200 — [DRY] comment on PR — '[SCHEMA] Reorder fields in MRSInstitutionInformation schema'
  - PR #2199 https://github.com/bids-standard/bids-specification/pull/2199 — [DRY] comment on PR — 'fix: Remove Marie Curie from contributors'
  - PR #2190 https://github.com/bids-standard/bids-specification/pull/2190 — [DRY] comment on PR — 'chore(deps): bump the actions-infrastructure group with 2 updates'
  - PR #2177 https://github.com/bids-standard/bids-specification/pull/2177 — [DRY] comment on PR — 'DOC: make mentioning of pipeline_name consistent'

Test plan

  • Dry-run on v1.11.1 lists the expected 10 PRs + 1 closing issue.
  • --post on v1.11.1 actually comments; re-run skips them all (idempotency verified live, see above).
  • pytest tools/tests/test_announce_release.py — 28 passed.
  • --help works without GITHUB_TOKEN; the uv run … -- --help invocation pattern reports "not a known release tag" rather than a misleading token error.
  • On the first release: published after merge, confirm the announce_release job fires and posts comments. Maintainers can also run the retroactive sweep (tools/announce_release.py --retroactive --post) to backfill prior releases.

Closes #2436

After each GitHub release publication, post a "PR released in vX.Y.Z"
comment on every PR included in the release and a "Issue fixed in
vX.Y.Z" comment on every issue those PRs closed via Fixes/Closes.

Modeled after the corresponding logic in datalad/release-action's
make_release_comments. The check before posting matches on exact
comment body, so re-runs of the workflow or of the script are
idempotent (no duplicates, no edits).

Components:

- tools/announce_release.py: standalone `uv run` script that walks
  `git log <prev>..<tag> --first-parent` to discover PRs in a release
  (handles both `... (#NNN)` squash subjects and `Merge pull request
  #NNN` merges), then queries closing issues via GraphQL and posts
  comments via REST. Dry-run by default; --post to actually comment.
  Supports `--retroactive [--since TAG]` for back-filling past releases.
  Argument validation happens before the GITHUB_TOKEN check so --help
  and bogus invocations don't surface as confusing token errors.

- .github/workflows/publish_schema.yml: rather than a new workflow,
  the existing release-adjacent workflow gets a `release: published`
  trigger and a new `announce_release` job that runs the script with
  --post. The existing `publish` job is gated to push events only so
  it doesn't run on release events.

- Release_Protocol.md: documents the new auto-announcement step and
  points at the script for retroactive back-fills.

- tools/tests/test_announce_release.py: pytest suite (28 tests) for
  the pure-logic units — tag-filter regex, comment-body and
  release-link formatting, PR-extraction from canned `git log` output,
  release-tag filtering, `select_tags` selection logic, and CLI
  argparse / token-check behaviour. Runs standalone via its own
  `# /// script` uv-run header, no project test infra required.

Co-Authored-By: Claude Code 2.1.159 / Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added the exclude-from-changelog This item will not feature in the automatically generated changelog label Jun 1, 2026
@github-actions

github-actions Bot commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

I have applied any labels matching special text in your title and description.

Please review the labels and make any necessary changes.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I don't think it makes sense to use this workflow.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

initially the beast created a separate one but I thought it would make sense to incorporate with existing release one... remind me which one does releasing? or would you prefer an entirely separate?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

ok, with the last commit I moved it out -- it is all by itself now -- neat and reusable... should I make it a reusable action may be ? (uff -- long road to perfection)

Comment thread tools/announce_release.py Outdated
Co-authored-by: Chris Markiewicz <markiewicz@stanford.edu>
@yarikoptic

Copy link
Copy Markdown
Collaborator Author
research/comparison to "alternatives" potentially to adopt

Off-the-shelf alternative: apexskier/github-release-commenter

Before we merge our own script, worth flagging that there is a marketplace
action that already does most of what this PR implements:
apexskier/github-release-commenter
(marketplace) —
TypeScript, MIT, 27★, actively maintained (last release 2026-01-21).

I surveyed four candidates that came up for "comment on PRs/issues at
release time":

Action Stars Comments on PRs Comments on closed issues Notes
apexskier/github-release-commenter 27 yes yes Closest match to #2436
rdlf0/comment-released-prs-action 6 yes no PR-only
duncanmcclean/post-release-comments 3 yes yes Requires you to feed in a parsed CHANGELOG.md
Blackjacx/backlog-notifier 7 n/a n/a Posts on external backlog-repo tickets via a custom ID prefix — different use case

The intuit/auto "released" plugin referenced in the issue is part of a much
larger release-management framework — adopting it just for the comment side
is overkill.

How apexskier/github-release-commenter works (relevant to compare)

Discovery mechanism (read from src/index.ts):

  1. Fetches the two most recent releases via repos.listReleases.
  2. Calls repos.compareCommits(prev_tag, current_tag).
  3. For each commit in the comparison, one GraphQL query pulls
    associatedPullRequests and each PR's timelineItems filtered to
    ConnectedEvent / DisconnectedEvent.
  4. The ConnectedEvent set is the union of Fixes/Closes #N references
    and the GitHub-UI "Linked issues" sidebar; DisconnectedEvent honors
    un-links.
  5. Posts the configured comment on every PR + every still-connected issue.

Minimal workflow integration:

on:
  release:
    types: [published]
permissions:
  issues: write
  pull-requests: write
jobs:
  announce_release:
    runs-on: ubuntu-latest
    steps:
      - uses: apexskier/github-release-commenter@v1
        with:
          comment-template: |
            Released in {release_link}
          skip-label: exclude-from-changelog

Comparison vs. this PR's tools/announce_release.py

apexskier/github-release-commenter tools/announce_release.py (this PR)
Comments on PRs in the release yes yes
Comments on issues closed by those PRs yes (timeline ConnectedEvent) yes (GraphQL closingIssuesReferences)
Trigger release: published same
Code we own / maintain 0 lines ~300 LOC + 28 tests
Idempotent on re-run no — re-publishing duplicates yes — exact-body check before posting
Skip-label support built-in (default: dependencies) not implemented
Retroactive back-fill of past releases no yes (--retroactive [--since TAG])
Linked-issues semantics Fixes #N plus manual sidebar links Fixes #N only
First-ever release on a repo intentionally ignored works (no prev_tag ⇒ full history)

Proposed compromise

Switch the recurring on-release path to apexskier/github-release-commenter
and keep tools/announce_release.py solely for the one-time retroactive
back-fill
(which no marketplace action provides):

  1. Replace this PR's announce_release job in publish_schema.yml with a
    single uses: apexskier/github-release-commenter@v1 step.
  2. Keep tools/announce_release.py (and its tests) in-tree, used by a
    maintainer to run --retroactive --post once to backfill comments on
    past releases. After that, it can stay around as documentation /
    recoverability tooling, or be removed.

That gives us:

  • ~20-line workflow step instead of a Python script in CI;
  • proven third-party action for the recurring path;
  • a small in-repo tool for the historical sweep, with body-equality
    idempotency that's actually useful while backfilling (since you might
    iterate a few times).

Trade-offs worth weighing before switching

  1. No idempotency in the marketplace action. If a release is ever
    un-published and re-published, every linked PR/issue gets a second
    comment. Their codebase has no comment-existence check; it's not on
    their roadmap.
  2. Linked-issues semantics differ. The marketplace action picks up
    both Fixes #N and the GitHub-UI "Linked issues" sidebar; ours
    picks up only closingIssuesReferences. Theirs is arguably more
    complete; whether maintainers ever populate the manual sidebar in this
    repo is the question.
  3. Third-party-action supply chain. We'd be pinning a non-Anthropic /
    non-GitHub-published binary blob into our release path. Pinning by SHA
    rather than @v1 mitigates this. The MIT license is declared in
    package.json (no top-level LICENSE file, FYI).
  4. Comment template flexibility. We use a rich-Markdown body
    PR released in [`vX.Y.Z`](https://.../releases/tag/vX.Y.Z); theirs
    supports {release_link} / {release_name} / {release_tag}
    templating, which can produce an equivalent body. No blocker.

Happy to push a follow-up commit that swaps the workflow job over and
trims Release_Protocol.md accordingly, if folks prefer the third-party
action.

Per @effigies's review on #2437: bolting `release: published` onto
`publish_schema.yml` was a forced fit — that workflow is about
schema publishing to JSR on push to master/maint, not about
GitHub-release events. There is no existing "release workflow" in
this repo (releases are manual per `Release_Protocol.md`), so the
right answer is a small dedicated one.

- Revert `.github/workflows/publish_schema.yml` to master state.
- Add `.github/workflows/announce_release.yml`: triggers on
  `release: published`, runs `tools/announce_release.py --post` for
  the published tag. Same job content as before, just isolated.
- Repoint `Release_Protocol.md` at the new workflow.

Co-Authored-By: Claude Code 2.1.159 / Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

exclude-from-changelog This item will not feature in the automatically generated changelog infrastructure

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add comment to merged PRs/closed issues in which version they were "released"

2 participants