Skip to content

ci: make releases manually dispatched - #106

Merged
nicholls73 merged 4 commits into
mainfrom
codex/manual-release-workflow
Jul 31, 2026
Merged

ci: make releases manually dispatched#106
nicholls73 merged 4 commits into
mainfrom
codex/manual-release-workflow

Conversation

@nicholls73

@nicholls73 nicholls73 commented Jul 30, 2026

Copy link
Copy Markdown
Owner

Summary

  • make Actions > Release > Run workflow the single manual release approval
  • let Release Please refresh the candidate, then rebase it onto latest main
  • run fresh CI and merge only the exact checked head commit
  • stop CI from creating automatic waiting Release runs
  • document the manual release flow

Safety

  • fail unless started from main
  • require exactly one bot-authored Release Please PR from this repository
  • compare the candidate with current main before checks
  • fail if main or the candidate head changes before merge
  • serialize release workflows without cancelling an in-progress publish

Testing

  • YAML parse for both workflows
  • embedded Bash syntax check
  • SemVer valid and invalid cases
  • pnpm lint
  • pnpm build
  • pnpm test (128 passed, 1 skipped)
  • git diff --check

Summary by CodeRabbit

  • New Features

    • Added a manual release workflow that validates, checks, and merges the correct release pull request before publishing.
    • Improved release safeguards by verifying branch status, ownership, synchronization, and version information.
  • Documentation

    • Updated release instructions to explain the new manual workflow and release pull request process.

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b5fc6f88-e648-47f7-8e9a-cd5dfc2c3d34

📥 Commits

Reviewing files that changed from the base of the PR and between 14fcae0 and 12b6992.

📒 Files selected for processing (1)
  • .github/workflows/release.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/release.yml

📝 Walkthrough

Walkthrough

The release process changes from repository-dispatch approval to manual workflow dispatch. It validates a Release Please PR, runs CI, rechecks repository state, merges the PR, and uses workflow outputs for release verification and publishing. Contributor guidance is updated.

Changes

Release orchestration

Layer / File(s) Summary
CI release preparation
.github/workflows/ci.yml
The prepare-release job retains the required permissions. The previous CI-waiting and release-approval dispatch logic is removed or changed.
Release candidate preparation
.github/workflows/release.yml
The workflow runs manually from main. It validates the Release Please PR, checks its version and ownership, runs CI, verifies repository state, and merges the PR.
Release validation and publication
.github/workflows/release.yml, CONTRIBUTING.md
Release-version checks and the publish job name use the candidate version from the workflow. Contributor guidance describes the manual release process.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Maintainer
  participant ReleaseWorkflow
  participant ReleasePleasePR
  participant CIWorkflow
  Maintainer->>ReleaseWorkflow: manually dispatch from main
  ReleaseWorkflow->>ReleasePleasePR: discover and validate release PR
  ReleaseWorkflow->>CIWorkflow: dispatch ci.yml and monitor completion
  ReleaseWorkflow->>ReleasePleasePR: merge validated release PR
  ReleaseWorkflow->>ReleaseWorkflow: validate released version and publish
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: making releases manually dispatched through the workflow.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/manual-release-workflow

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (4)
.github/workflows/release.yml (4)

35-40: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Paginate the PR listing. With more than 100 open PRs against main, the release-please PR can fall off page 1 and the run fails with a misleading "found 0".

♻️ Use --paginate and flatten
           pulls="$(
-            gh api --method GET "repos/${GITHUB_REPOSITORY}/pulls" \
+            gh api --paginate --slurp --method GET "repos/${GITHUB_REPOSITORY}/pulls" \
               -f state=open \
               -f base=main \
               -F per_page=100
           )"
           candidates="$(
-            jq -c --arg repo "${GITHUB_REPOSITORY}" '[
-              .[] | select(
+            jq -c --arg repo "${GITHUB_REPOSITORY}" '[
+              (.[] | .[]) | select(
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml around lines 35 - 40, Update the gh api
invocation assigned to pulls to use pagination and flatten the returned page
arrays into one PR collection. Preserve the existing open-state and main-branch
filters so release-please can find matching PRs beyond the first 100 results.

90-103: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Pin the watched CI run to the validated commit, and bound the wait.

The dispatch targets a branch ref, so the run may execute a commit other than candidate.outputs.head_sha. Asserting the run's headSha closes that gap directly instead of inferring it from the later PR check. A timeout-minutes on the job also avoids a stuck CI run holding the release for the 6h default.

♻️ Assert the run commit
           ci_run_id="$(jq -er '.workflow_run_id' <<< "${dispatch}")"
+          run_head="$(gh run view "${ci_run_id}" --repo "${GITHUB_REPOSITORY}" --json headSha --jq '.headSha')"
+          if [[ "${run_head}" != "${{ steps.candidate.outputs.head_sha }}" ]]; then
+            echo "::error::CI run ${ci_run_id} is for ${run_head}, not the validated candidate commit"
+            exit 1
+          fi
           gh run watch "${ci_run_id}" --repo "${GITHUB_REPOSITORY}" --exit-status
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml around lines 90 - 103, Update the “Run checks”
workflow job to assert that the dispatched CI run’s headSha matches
candidate.outputs.head_sha, and add a timeout-minutes limit to bound waiting for
the run. Keep the existing dispatch and gh run watch --exit-status behavior
while ensuring the watched run is the one for the validated commit.

104-136: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract the repeated candidate-invariant check. The same main SHA compare, jq -e PR predicate, and package.json version compare are duplicated across both jobs, differing only in error strings — a future tightening of the predicate has to be applied in two places.

  • .github/workflows/release.yml#L104-L136: move this logic into a shared script (e.g. .github/scripts/verify-release-candidate.sh) invoked with a context label, and call it here.
  • .github/workflows/release.yml#L159-L187: replace this block with a call to the same shared script (keeping the numeric RELEASE_PR guard in the workflow).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml around lines 104 - 136, Extract the duplicated
candidate-invariant validation from the “Verify release candidate” block at
.github/workflows/release.yml:104-136 and the corresponding block at
.github/workflows/release.yml:159-187 into a shared script such as
.github/scripts/verify-release-candidate.sh, parameterized by a context label
for error messages. Move the main SHA check, PR jq predicate, and package.json
version check into that script, then invoke it from both workflow sites with
their existing environment values; retain the numeric RELEASE_PR guard in the
later workflow block.

188-199: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Pin the merge to the validated head commit. The main recheck leaves a gap before gh pr merge; pass needs.prepare.outputs.head_sha and use --match-head-commit so a push to the release PR can’t slip in.

♻️ Pass the expected head commit
         env:
           EXPECTED_MAIN_SHA: ${{ needs.prepare.outputs.main_sha }}
+          EXPECTED_HEAD_SHA: ${{ needs.prepare.outputs.head_sha }}
           GH_TOKEN: ${{ github.token }}
@@
-          gh pr merge "${RELEASE_PR}" --repo "${GITHUB_REPOSITORY}" --merge
+          gh pr merge "${RELEASE_PR}" --repo "${GITHUB_REPOSITORY}" --merge \
+            --match-head-commit "${EXPECTED_HEAD_SHA}"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml around lines 188 - 199, Update the “Merge
release PR” step to pass needs.prepare.outputs.head_sha as the expected
pull-request head commit, and add gh pr merge’s --match-head-commit option using
that value. Preserve the existing main SHA validation and merge behavior while
ensuring the merge is pinned to the validated PR head.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/release.yml:
- Around line 58-71: Replace the base.sha checks in the release PR update flow
with a comparison between the current main branch and the PR head, using the
repository compare API and its behind_by value. Update the polling loop and
final failure check to treat behind_by == 0 as current, while preserving the
existing rebase, retry, error, and exit behavior.

---

Nitpick comments:
In @.github/workflows/release.yml:
- Around line 35-40: Update the gh api invocation assigned to pulls to use
pagination and flatten the returned page arrays into one PR collection. Preserve
the existing open-state and main-branch filters so release-please can find
matching PRs beyond the first 100 results.
- Around line 90-103: Update the “Run checks” workflow job to assert that the
dispatched CI run’s headSha matches candidate.outputs.head_sha, and add a
timeout-minutes limit to bound waiting for the run. Keep the existing dispatch
and gh run watch --exit-status behavior while ensuring the watched run is the
one for the validated commit.
- Around line 104-136: Extract the duplicated candidate-invariant validation
from the “Verify release candidate” block at
.github/workflows/release.yml:104-136 and the corresponding block at
.github/workflows/release.yml:159-187 into a shared script such as
.github/scripts/verify-release-candidate.sh, parameterized by a context label
for error messages. Move the main SHA check, PR jq predicate, and package.json
version check into that script, then invoke it from both workflow sites with
their existing environment values; retain the numeric RELEASE_PR guard in the
later workflow block.
- Around line 188-199: Update the “Merge release PR” step to pass
needs.prepare.outputs.head_sha as the expected pull-request head commit, and add
gh pr merge’s --match-head-commit option using that value. Preserve the existing
main SHA validation and merge behavior while ensuring the merge is pinned to the
validated PR head.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 7d1f0b67-7d55-4f2a-a6bb-bd1d34a14def

📥 Commits

Reviewing files that changed from the base of the PR and between a5e6fcf and c908cc2.

📒 Files selected for processing (3)
  • .github/workflows/ci.yml
  • .github/workflows/release.yml
  • CONTRIBUTING.md
💤 Files with no reviewable changes (1)
  • .github/workflows/ci.yml

Comment thread .github/workflows/release.yml Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
.github/workflows/release.yml (1)

7-9: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

The concurrency settings do not cancel stale runs.

The pull request description states that the workflow cancels stale waiting approvals. cancel-in-progress: false queues a second run instead of cancelling the first. Align the setting with the intended behavior, or update the description.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml around lines 7 - 9, Update the release
workflow’s concurrency configuration to cancel stale runs by changing
cancel-in-progress to true, aligning it with the documented behavior while
preserving the release concurrency group.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/release.yml:
- Around line 55-66: Update the jq validation in the release workflow to stop
comparing `.base.sha` with `$main`, since that value may be stale on reused
Release Please pull requests. Instead, validate that the pull request head is
current by requiring `.behind_by == 0`, while preserving the existing open,
main-target, repository, and bot-author checks.
- Around line 42-51: Update the Release Please PR filter in the candidate query
to match the default single-package branch name release-please--branches--main,
while preserving support for component-specific branch names when present. Keep
the exactly-one candidate validation in the surrounding candidate_count check
unchanged.

---

Nitpick comments:
In @.github/workflows/release.yml:
- Around line 7-9: Update the release workflow’s concurrency configuration to
cancel stale runs by changing cancel-in-progress to true, aligning it with the
documented behavior while preserving the release concurrency group.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ac017e58-b545-4c9a-aee0-ecdf0b854982

📥 Commits

Reviewing files that changed from the base of the PR and between c908cc2 and 1722bcc.

📒 Files selected for processing (1)
  • .github/workflows/release.yml

Comment thread .github/workflows/release.yml
Comment thread .github/workflows/release.yml
@nicholls73
nicholls73 merged commit ca7d9a4 into main Jul 31, 2026
6 checks passed
@nicholls73
nicholls73 deleted the codex/manual-release-workflow branch July 31, 2026 03:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant