Skip to content

chore(ci): run CI and auto-publish on release/* maintenance branches - #430

Merged
pbean merged 2 commits into
mainfrom
chore/ci-release-branch-triggers
Aug 2, 2026
Merged

chore(ci): run CI and auto-publish on release/* maintenance branches#430
pbean merged 2 commits into
mainfrom
chore/ci-release-branch-triggers

Conversation

@pbean

@pbean pbean commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator

What

Add release/* to the push branch filter in both .github/workflows/ci.yml
and .github/workflows/release.yml, and correct release.yml's header comment,
which described the trigger as a version bump landing on main only.

Nothing else changes.

Why

Both workflows fire only on push: branches: [main]. A maintenance branch
therefore gets no checks at all on its merge commits, and a version bump
landing there never publishes — release.py publish simply has no trigger
outside trunk.

The 0.9.1 hotfix hit exactly that. It was cut from v0.9.0 onto
release/0.9.x (main carries next-major work that must not ship in a patch),
merged as #406 with zero checks, and had no path to a v0.9.1 tag short of a
hand-created one.

Effect

Any release/* branch will now auto-publish on a version bump, the same
way main does: pushing a merge commit that bumps the canonical version fires
the publish job, which creates the vX.Y.Z tag and GitHub release from the
matching ## [X.Y.Z] CHANGELOG section, targeting that branch's head. Those
branches also get full CI on their merge commits for the first time.

release.py publish is idempotent — it no-ops when the tag already exists — so
the two triggers cannot fight: whichever branch carries a given version first
wins the tag, and the other side's run does nothing. That is what keeps a
forward-port of already-released content from re-tagging it.

The same change was shipped to release/0.9.x as #429 so v0.9.1 could publish;
this PR carries it to trunk.

Refs #405.

Summary by CodeRabbit

  • Chores
    • Continuous integration now runs for updates to both the main branch and release branches.
    • Releases can be initiated from either the main branch or a release branch.
    • Updated release workflow documentation to reflect the supported branch options.

Both workflows fire only on `push: branches: [main]`, so a maintenance branch
gets no checks on its merge commits and its version bumps never publish. The
0.9.1 hotfix hit exactly that: it merged into `release/0.9.x` with zero checks
and no path to a `v0.9.1` tag.

Add `release/*` to the push branch filter in both workflows so any release
branch gets the same treatment as trunk. `release.py publish` is already
idempotent (no-op when the tag exists), so whichever branch carries a version
first wins the tag and the other side's run does nothing.

@greptile-apps greptile-apps 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.

pbean has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@pbean, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 45 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 09dd81ce-f5f1-4742-b4a5-c0dfbc39b285

📥 Commits

Reviewing files that changed from the base of the PR and between 5f6fb22 and 9a1dfb8.

📒 Files selected for processing (3)
  • .github/workflows/release.yml
  • scripts/release.py
  • tests/test_release.py

Walkthrough

CI and release workflows now trigger on pushes to main and release/*. Release documentation states that either branch can publish the first version tag.

Changes

Workflow trigger updates

Layer / File(s) Summary
Branch push trigger configuration
.github/workflows/ci.yml, .github/workflows/release.yml
Pushes to release/* now trigger CI and release workflows. Release documentation reflects the added branch. Existing idempotent tag publishing remains unchanged.

Estimated code review effort: 1 (Trivial) | ~5 minutes

Poem

A rabbit checks the branch list twice,
main and release/* now hop in nice.
CI runs when the push bells ring,
Release tags keep their steady spring.
One small change, clean and bright.

🚥 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 summarizes the CI and automatic publishing changes for release/* maintenance branches.
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 chore/ci-release-branch-triggers

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

🤖 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 8-10: Update the release workflow’s concurrency and publishing
behavior so main and release/* runs targeting the same version cannot race: use
a shared version/release-based concurrency group instead of only github.ref, or
make command_publish handle gh release create conflicts by treating an
already-existing tag or release as successful.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 92cca359-f110-45df-ab43-2fe7a171a312

📥 Commits

Reviewing files that changed from the base of the PR and between a6424ad and 5f6fb22.

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

Comment thread .github/workflows/release.yml
@pbean

pbean commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator Author

@coderabbitai Verified the race and it is real, but it is out of scope for this PR — filed
as #431 instead.

Confirming the mechanism rather than taking it at face value: tag_exists is
git rev-parse -q --verify refs/tags/<tag> against the local clone, and nothing
fetches between actions/checkout and the check. So the guard reflects tag state at
checkout time, not the live remote — two runs that both check out before either creates the
tag both pass it, both call gh release create, and the loser exits non-zero under
check=True. And group: release-${{ github.ref }} does not serialize them, since two
branches are two refs. Your read was correct on both halves.

Not fixing it here for two reasons:

  1. This PR is deliberately the trigger change and nothing else. Its sibling chore(ci): run CI and auto-publish on release/* maintenance branches #429 already
    merged into release/0.9.x and published v0.9.1; letting the two diverge would muddy the
    forward-port.
  2. The blast radius is a spuriously red workflow run on the losing branch — the release that
    wins is still correct. It is not a correctness bug in the published artifact.

One note on the suggested fix: a shared concurrency group alone does not close the window,
because the second job's checkout can still predate the first job's tag push. #431 records
that, and lands on the gh release create conflict-tolerance half as the one that actually
closes it.

@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

@pbean Confirmed. #431 tracks the correct fix scope.

A shared concurrency group alone does not close the stale local-tag window. The gh release create conflict-tolerance path handles the duplicate-release case after the remote state changes.

I will treat this PR as the intended trigger-only change.

🐇


✏️ Learnings added
Learnt from: pbean
URL: https://github.com/bmad-code-org/bmad-loop/pull/430

Timestamp: 2026-08-02T18:51:22.549Z
Learning: In the GitHub Actions release workflow, `tag_exists` uses `git rev-parse -q --verify refs/tags/<tag>` against the local checkout. Because no fetch occurs between `actions/checkout` and this check, concurrent runs on different branch refs can both observe a missing tag and both call `gh release create`. The losing `gh release create` process exits non-zero under `check=True`. A shared concurrency group alone does not close this race if the second checkout predates the first tag push; `gh release create` conflict tolerance is required.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

You are interacting with an AI system.

Adding the `release/*` trigger lets two branches publish, which turns
`cmd_publish`'s idempotency guard into a TOCTOU. `tag_exists` is `git rev-parse`
against the *checkout's* refs and nothing re-fetches before `gh release create`,
so it answers for tag state at checkout time. Two runs carrying the same version
could both pass it, both create, and the loser died on `check=True` — a red job
for an outcome that was already correct, since the winner made this exact tag
from this exact CHANGELOG section.

Close it from both ends. The concurrency group drops `github.ref` so all publish
runs serialize repo-wide and the second one checks out after the first pushed its
tag, short-circuiting cleanly on the probe. And `gh release create` no longer runs
under `check=True`: a stderr naming a duplicate tag returns 0, anything else
prints the stderr and dies as before.

Matching the phrase rather than the HTTP status keeps a 422 raised for some other
validation failure — a malformed target, bad notes — on the loud path.

@greptile-apps greptile-apps 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.

pbean has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@pbean
pbean merged commit b5e5b7a into main Aug 2, 2026
10 checks passed
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