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
26 changes: 26 additions & 0 deletions .github/workflows/release-tag-guard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ name: Release Tag Guard
# no-op. If it didn't, the guard creates the tag + Release so the release can
# never silently fail to ship again. Uses the PAT (not GITHUB_TOKEN) so the
# `release: published` event propagates and deploy.yml fires.
#
# It also reconciles the merged release PR's `autorelease: pending -> tagged`
# label (#1561): when the guard creates the Release, release-please never flips
# that label, so its NEXT run aborts ("untagged, merged release PR outstanding").

on:
push:
Expand Down Expand Up @@ -63,3 +67,25 @@ jobs:
--title "${tag}" \
--notes "Automated release created by release-tag-guard (release-please did not auto-release). See CHANGELOG.md." \
--verify-tag

- name: Reconcile release PR label (autorelease pending -> tagged, #1561)
env:
GH_TOKEN: ${{ secrets.RELEASE_PLEASE_TOKEN }}
run: |
set -euo pipefail
version="$(node -p "require('./.release-please-manifest.json')['.']")"
# release-please flips this label to 'tagged' when IT creates the Release.
# When this guard creates the Release instead (the common case here), the
# label stays 'autorelease: pending', so release-please's NEXT run sees an
# "untagged, merged release PR outstanding" and aborts the next release
# (#1561). Separate step (not gated by the early-exit above) so it always
# reconciles, idempotently, and the next release can never silently block.
pr="$(gh pr list --state merged --label 'autorelease: pending' \
--search "chore: release ${version} in:title" \
--json number --jq '.[0].number // empty')"
if [ -n "${pr}" ]; then
echo "::notice::flipping release PR #${pr} label autorelease: pending -> tagged (#1561 backstop)"
gh pr edit "${pr}" --add-label 'autorelease: tagged' --remove-label 'autorelease: pending'
else
echo "::notice::no merged 'autorelease: pending' release PR for ${version} — already reconciled."
fi
2 changes: 2 additions & 0 deletions decisions/2026-06-22-release-please-group-title-pattern.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ Negative / residual risk:

- Two mechanisms can now create the release (release-please + guard). The guard's Release-existence check makes this safe (no double-release), but a future release-please that _does_ tag will make the guard a silent no-op — fine, but worth knowing when debugging.

**Follow-up (2026-06-24, #1561):** the guard created the Release but did **not** flip the merged release PR's `autorelease: pending → tagged` label, so release-please still saw an "untagged, merged release PR outstanding" and aborted the _next_ release. This recurred at **v2.24.0 → v2.25.0**, again forcing a manual relabel. Fixed by adding a **label-reconcile step** to `release-tag-guard.yml` — a _separate_ step (not gated by the create-step's early-exit), idempotent, that flips `autorelease: pending → tagged` on the merged release PR for the current version. The guard now reconciles **both** the Release _and_ the label state release-please tracks, so the next release can never silently block. The original "Negative / residual risk" above (release-please's label tracking) is thereby closed.

Neutral:

- The stale #1519 (old title) was closed so release-please regenerated a correctly-titled PR (#1522).
Expand Down
Loading