Skip to content

Commit 8c64ce7

Browse files
pmaxhoganclaude
andcommitted
ci: signal release readiness when a version milestone completes
Adds .github/workflows/release-ready.yml. When every issue in a version milestone (v0.3.0, v1.0.0, ...) is closed, it comments on + labels the open release-please PR and @-pings the maintainer to review + merge it. Signal-only by design - it NEVER auto-merges: a GITHUB_TOKEN bot merge would not trigger release-please.yml/release.yml, so no v* tag would be cut and nothing would ship. Pairs with the new GitHub Project roadmap (milestones = versions). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012CyiRqk2DVwmJjEu5gcD1m
1 parent 685fcf1 commit 8c64ce7

1 file changed

Lines changed: 88 additions & 0 deletions

File tree

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
name: release-ready
2+
3+
# Signal-only release readiness - NEVER merges anything (chosen 2026-06-26; see
4+
# the roadmap in github.com/users/pmaxhogan/projects/1 and the V2 epic #34).
5+
#
6+
# Versions are tracked as GitHub milestones (v0.3.0, v1.0.0, v2.0.0, ...). When
7+
# every issue in a version milestone is closed, this comments on + labels the
8+
# open release-please PR and @-pings the maintainer so they review the computed
9+
# version + CHANGELOG and merge it themselves. release-please.yml (opens the
10+
# release PR) and release.yml (builds/signs/publishes on the v* tag) stay the
11+
# human gate.
12+
#
13+
# Why signal-only and not auto-merge: a bot merging the release PR with
14+
# GITHUB_TOKEN does NOT trigger release-please.yml/release.yml (token-authored
15+
# events start no new workflow run), so no tag is cut and nothing ships - it
16+
# would look merged while releasing nothing. Plus a milestone title is not
17+
# guaranteed to equal release-please's commit-computed version, and milestone
18+
# 100% says nothing about main being green. Keep the merge a human click.
19+
20+
on:
21+
issues:
22+
types: [closed]
23+
schedule:
24+
# Daily backstop (14:17 UTC) in case an issues:closed event is missed or a
25+
# milestone completes by other means.
26+
- cron: "17 14 * * *"
27+
workflow_dispatch:
28+
29+
permissions:
30+
contents: read
31+
issues: write
32+
pull-requests: write
33+
34+
concurrency:
35+
group: release-ready
36+
cancel-in-progress: false
37+
38+
jobs:
39+
signal:
40+
runs-on: ubuntu-latest
41+
steps:
42+
- name: Signal readiness on completed version milestones
43+
env:
44+
GH_TOKEN: ${{ github.token }}
45+
REPO: ${{ github.repository }}
46+
MAINTAINER: pmaxhogan
47+
run: |
48+
set -euo pipefail
49+
50+
# Find the open release-please PR (branch prefixed "release-please--",
51+
# and/or carrying an "autorelease:" label). Nothing to do if none open.
52+
pr="$(gh pr list --repo "$REPO" --state open \
53+
--json number,headRefName,labels \
54+
--jq '[.[] | select((.headRefName | startswith("release-please--")) or (any(.labels[]?; .name | startswith("autorelease:"))))][0].number // empty')"
55+
if [ -z "$pr" ]; then
56+
echo "No open release PR; nothing to signal."
57+
exit 0
58+
fi
59+
echo "Open release PR: #$pr"
60+
61+
# Completed milestone = open state, has issues, zero still open.
62+
completed="$(gh api "repos/$REPO/milestones?state=open&per_page=100" \
63+
--jq '.[] | select(.open_issues == 0 and .closed_issues > 0) | .title')"
64+
if [ -z "$completed" ]; then
65+
echo "No fully-completed milestones."
66+
exit 0
67+
fi
68+
69+
# Existing PR comments, to dedup via a hidden per-milestone sentinel.
70+
existing="$(gh api "repos/$REPO/issues/$pr/comments?per_page=100" --jq '.[].body' || true)"
71+
72+
signalled=0
73+
while IFS= read -r ms; do
74+
[ -z "$ms" ] && continue
75+
marker="<!-- release-ready:${ms} -->"
76+
if printf '%s' "$existing" | grep -qF "$marker"; then
77+
echo "Already signalled ${ms}."
78+
continue
79+
fi
80+
echo "Signalling ${ms} on PR #${pr}."
81+
body="${marker}"$'\n'"@${MAINTAINER} every issue in the **${ms}** milestone is now closed - this release looks ready. Review the version + CHANGELOG in this PR and merge when you are happy (nothing is auto-merged). If release-please computed a version other than ${ms}, that is expected: the milestone title is just a planning label."
82+
gh pr comment "$pr" --repo "$REPO" --body "$body"
83+
signalled=1
84+
done <<< "$completed"
85+
86+
if [ "$signalled" = "1" ]; then
87+
gh pr edit "$pr" --repo "$REPO" --add-label ready-to-release || true
88+
fi

0 commit comments

Comments
 (0)