feat(cut-release): add --promote for ring-to-ring channel moves (#501) - #992
Conversation
cut-release.sh --channel always tries to CREATE the immutable <agent>/vX.Y.Z release tag, so promoting an already-cut version to the next ring aborts on the "immutable tags are never overwritten" check (hit on every ring0→ring1→stable advance during the #870 soak — worked around with raw git/refs PATCH calls). Add --promote: move <agent>/<channel> to the EXISTING release commit without recreating the tag. Requires --channel, errors if the release tag is absent (can't promote what wasn't cut), ignores --ref (the release's own commit is authoritative). Works for both cross-repo (.github via gh api) and this-repo (local git) agents; respects --dry-run / --push. New helper gh_release_commit() dereferences the annotated release tag to its commit. Tests: +4 (requires --channel, errors when absent, moves channel without recreating the tag, dry-run no-op). 50 cut-release bats pass, shellcheck clean. This is the channel-move primitive the #501 auto-promoter needs; until it lands the soak loop moved channels via raw API. Refs #501, #870.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
@donpetry-bot please review |
|
Warning Review limit reached
Next review available in: 33 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the 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 configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
|
@don-petry I'm on it — starting a fresh review now. Results will appear in a few minutes. |
Dev-Lead — review-changes (no-changes)No changes were needed for this PR. |
There was a problem hiding this comment.
Code Review
This pull request introduces a new --promote flag to the cut-release.sh script, enabling ring-to-ring channel promotions to an existing release tag without cutting a new release. This includes a new gh_release_commit helper function to resolve the commit SHA of a release tag via the GitHub API, along with corresponding integration tests. The review feedback suggests optimizing gh_release_commit to reduce network overhead by combining multiple API calls into a single request, and recommends guarding the gh_release_commit call in the promotion logic to prevent silent failures under set -e.
Dev-Lead — fix-reviews (applied)Changes committed and pushed. |
|
|
CI checks on this PR are still running. Once they complete, re-mention Posted by the donpetry-bot PR-review cascade. |
|
@donpetry-bot I'm on it — starting a fresh review now. Results will appear in a few minutes. |
Dev-Lead — waiting on PR blockers (intent: review-changes)PR: #992 |
|
Note @don-petry I reviewed this PR and no code changes were needed, but it still has blocking checks or reviews (failing or cancelled checks, or changes-requested reviews), so I cannot mark it done yet. I'll re-check automatically. |
donpetry-bot
left a comment
There was a problem hiding this comment.
Automated review — APPROVED ✓
Risk: MEDIUM
Reviewed commit: 91908a67952fb43014847bb98548c54ef0823a5c
Cascade: triage → deep (triage: haiku 4.5 → deep: opus 4.8 + duck: o4-mini → audit: fable 5)
Summary
Adds a --promote (ring-to-ring channel-move) mode to scripts/cut-release.sh plus 4 bats tests; no auth/secret/migration surface. The triage escalation signal — gemini's HIGH that gh_release_commit()'s second gh api call could silently exit under set -e — is resolved at head SHA 91908a6: the caller invokes the helper inside an if ! condition (suppressing set -e in the function body) and guards both a non-zero return and empty output, and the this-repo path uses guarded git rev-parse. All CI checks are green (shellcheck, bats, CodeQL, SonarCloud, gitleaks); the remaining BLOCKED/REVIEW_REQUIRED state is the org-leads human review gate, not an automated failure. No downstream consumers impacted (DOWNSTREAM_IMPACT: none).
Findings
- info: Triage's HIGH signal addressed: gh_release_commit() is called as
if ! pcommit="$(gh_release_commit ...)" || [ -z "$pcommit" ]. Because the function runs in an if-condition, set -e is suppressed inside it, so a failing secondgh apireturns non-zero rather than silently exiting; the caller then handles both non-zero and empty results. No silent-exit path remains. - minor: gemini also suggested collapsing the two sequential
gh api .../git/ref/tags/$2lookups (sha + type) into one request. Non-blocking efficiency nit; current two-call form is correct and now properly guarded. - info: The bats stub returns a bare sha (no
type) forgit/ref/tags/, so tests exercise the lightweight-ref (else) branch but not the annotated-tag deref branch (type=="tag", secondgit/tags/$objcall). Real release tags are annotated, so the deref path is untested by the stub — acceptable fidelity gap, not a code defect. - info: run_secret_scanning MCP tool not available in this environment; relied on gitleaks CI check (SUCCESS) plus manual diff inspection. Diff is pure shell control-flow — no credentials, tokens, or .env content.
Reviewed by the PR-review cascade (triage: haiku 4.5 → deep: opus 4.8 + duck: o4-mini → audit: fable 5). Reply if you need a human review.
|
Advisory bots were rate-limited; auto-approval is withheld until they recover. pr-review-sweep will re-review this PR after 2026-06-30T21:24:40Z. |
#992) * feat(cut-release): add --promote for ring-to-ring channel moves (#501) cut-release.sh --channel always tries to CREATE the immutable <agent>/vX.Y.Z release tag, so promoting an already-cut version to the next ring aborts on the "immutable tags are never overwritten" check (hit on every ring0→ring1→stable advance during the #870 soak — worked around with raw git/refs PATCH calls). Add --promote: move <agent>/<channel> to the EXISTING release commit without recreating the tag. Requires --channel, errors if the release tag is absent (can't promote what wasn't cut), ignores --ref (the release's own commit is authoritative). Works for both cross-repo (.github via gh api) and this-repo (local git) agents; respects --dry-run / --push. New helper gh_release_commit() dereferences the annotated release tag to its commit. Tests: +4 (requires --channel, errors when absent, moves channel without recreating the tag, dry-run no-op). 50 cut-release bats pass, shellcheck clean. This is the channel-move primitive the #501 auto-promoter needs; until it lands the soak loop moved channels via raw API. Refs #501, #870. * fix(reviews): address review comments [skip ci-relay] --------- Co-authored-by: Claude Code Bot <bot@petry-projects> Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
#992) * feat(cut-release): add --promote for ring-to-ring channel moves (#501) cut-release.sh --channel always tries to CREATE the immutable <agent>/vX.Y.Z release tag, so promoting an already-cut version to the next ring aborts on the "immutable tags are never overwritten" check (hit on every ring0→ring1→stable advance during the #870 soak — worked around with raw git/refs PATCH calls). Add --promote: move <agent>/<channel> to the EXISTING release commit without recreating the tag. Requires --channel, errors if the release tag is absent (can't promote what wasn't cut), ignores --ref (the release's own commit is authoritative). Works for both cross-repo (.github via gh api) and this-repo (local git) agents; respects --dry-run / --push. New helper gh_release_commit() dereferences the annotated release tag to its commit. Tests: +4 (requires --channel, errors when absent, moves channel without recreating the tag, dry-run no-op). 50 cut-release bats pass, shellcheck clean. This is the channel-move primitive the #501 auto-promoter needs; until it lands the soak loop moved channels via raw API. Refs #501, #870. * fix(reviews): address review comments [skip ci-relay] --------- Co-authored-by: Claude Code Bot <bot@petry-projects> Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
#992) * feat(cut-release): add --promote for ring-to-ring channel moves (#501) cut-release.sh --channel always tries to CREATE the immutable <agent>/vX.Y.Z release tag, so promoting an already-cut version to the next ring aborts on the "immutable tags are never overwritten" check (hit on every ring0→ring1→stable advance during the #870 soak — worked around with raw git/refs PATCH calls). Add --promote: move <agent>/<channel> to the EXISTING release commit without recreating the tag. Requires --channel, errors if the release tag is absent (can't promote what wasn't cut), ignores --ref (the release's own commit is authoritative). Works for both cross-repo (.github via gh api) and this-repo (local git) agents; respects --dry-run / --push. New helper gh_release_commit() dereferences the annotated release tag to its commit. Tests: +4 (requires --channel, errors when absent, moves channel without recreating the tag, dry-run no-op). 50 cut-release bats pass, shellcheck clean. This is the channel-move primitive the #501 auto-promoter needs; until it lands the soak loop moved channels via raw API. Refs #501, #870. * fix(reviews): address review comments [skip ci-relay] --------- Co-authored-by: Claude Code Bot <bot@petry-projects> Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
#992) * feat(cut-release): add --promote for ring-to-ring channel moves (#501) cut-release.sh --channel always tries to CREATE the immutable <agent>/vX.Y.Z release tag, so promoting an already-cut version to the next ring aborts on the "immutable tags are never overwritten" check (hit on every ring0→ring1→stable advance during the #870 soak — worked around with raw git/refs PATCH calls). Add --promote: move <agent>/<channel> to the EXISTING release commit without recreating the tag. Requires --channel, errors if the release tag is absent (can't promote what wasn't cut), ignores --ref (the release's own commit is authoritative). Works for both cross-repo (.github via gh api) and this-repo (local git) agents; respects --dry-run / --push. New helper gh_release_commit() dereferences the annotated release tag to its commit. Tests: +4 (requires --channel, errors when absent, moves channel without recreating the tag, dry-run no-op). 50 cut-release bats pass, shellcheck clean. This is the channel-move primitive the #501 auto-promoter needs; until it lands the soak loop moved channels via raw API. Refs #501, #870. * fix(reviews): address review comments [skip ci-relay] --------- Co-authored-by: Claude Code Bot <bot@petry-projects> Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
#992) * feat(cut-release): add --promote for ring-to-ring channel moves (#501) cut-release.sh --channel always tries to CREATE the immutable <agent>/vX.Y.Z release tag, so promoting an already-cut version to the next ring aborts on the "immutable tags are never overwritten" check (hit on every ring0→ring1→stable advance during the #870 soak — worked around with raw git/refs PATCH calls). Add --promote: move <agent>/<channel> to the EXISTING release commit without recreating the tag. Requires --channel, errors if the release tag is absent (can't promote what wasn't cut), ignores --ref (the release's own commit is authoritative). Works for both cross-repo (.github via gh api) and this-repo (local git) agents; respects --dry-run / --push. New helper gh_release_commit() dereferences the annotated release tag to its commit. Tests: +4 (requires --channel, errors when absent, moves channel without recreating the tag, dry-run no-op). 50 cut-release bats pass, shellcheck clean. This is the channel-move primitive the #501 auto-promoter needs; until it lands the soak loop moved channels via raw API. Refs #501, #870. * fix(reviews): address review comments [skip ci-relay] --------- Co-authored-by: Claude Code Bot <bot@petry-projects> Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
#992) * feat(cut-release): add --promote for ring-to-ring channel moves (#501) cut-release.sh --channel always tries to CREATE the immutable <agent>/vX.Y.Z release tag, so promoting an already-cut version to the next ring aborts on the "immutable tags are never overwritten" check (hit on every ring0→ring1→stable advance during the #870 soak — worked around with raw git/refs PATCH calls). Add --promote: move <agent>/<channel> to the EXISTING release commit without recreating the tag. Requires --channel, errors if the release tag is absent (can't promote what wasn't cut), ignores --ref (the release's own commit is authoritative). Works for both cross-repo (.github via gh api) and this-repo (local git) agents; respects --dry-run / --push. New helper gh_release_commit() dereferences the annotated release tag to its commit. Tests: +4 (requires --channel, errors when absent, moves channel without recreating the tag, dry-run no-op). 50 cut-release bats pass, shellcheck clean. This is the channel-move primitive the #501 auto-promoter needs; until it lands the soak loop moved channels via raw API. Refs #501, #870. * fix(reviews): address review comments [skip ci-relay] --------- Co-authored-by: Claude Code Bot <bot@petry-projects> Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
#992) * feat(cut-release): add --promote for ring-to-ring channel moves (#501) cut-release.sh --channel always tries to CREATE the immutable <agent>/vX.Y.Z release tag, so promoting an already-cut version to the next ring aborts on the "immutable tags are never overwritten" check (hit on every ring0→ring1→stable advance during the #870 soak — worked around with raw git/refs PATCH calls). Add --promote: move <agent>/<channel> to the EXISTING release commit without recreating the tag. Requires --channel, errors if the release tag is absent (can't promote what wasn't cut), ignores --ref (the release's own commit is authoritative). Works for both cross-repo (.github via gh api) and this-repo (local git) agents; respects --dry-run / --push. New helper gh_release_commit() dereferences the annotated release tag to its commit. Tests: +4 (requires --channel, errors when absent, moves channel without recreating the tag, dry-run no-op). 50 cut-release bats pass, shellcheck clean. This is the channel-move primitive the #501 auto-promoter needs; until it lands the soak loop moved channels via raw API. Refs #501, #870. * fix(reviews): address review comments [skip ci-relay] --------- Co-authored-by: Claude Code Bot <bot@petry-projects> Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
#992) * feat(cut-release): add --promote for ring-to-ring channel moves (#501) cut-release.sh --channel always tries to CREATE the immutable <agent>/vX.Y.Z release tag, so promoting an already-cut version to the next ring aborts on the "immutable tags are never overwritten" check (hit on every ring0→ring1→stable advance during the #870 soak — worked around with raw git/refs PATCH calls). Add --promote: move <agent>/<channel> to the EXISTING release commit without recreating the tag. Requires --channel, errors if the release tag is absent (can't promote what wasn't cut), ignores --ref (the release's own commit is authoritative). Works for both cross-repo (.github via gh api) and this-repo (local git) agents; respects --dry-run / --push. New helper gh_release_commit() dereferences the annotated release tag to its commit. Tests: +4 (requires --channel, errors when absent, moves channel without recreating the tag, dry-run no-op). 50 cut-release bats pass, shellcheck clean. This is the channel-move primitive the #501 auto-promoter needs; until it lands the soak loop moved channels via raw API. Refs #501, #870. * fix(reviews): address review comments [skip ci-relay] --------- Co-authored-by: Claude Code Bot <bot@petry-projects> Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
#992) * feat(cut-release): add --promote for ring-to-ring channel moves (#501) cut-release.sh --channel always tries to CREATE the immutable <agent>/vX.Y.Z release tag, so promoting an already-cut version to the next ring aborts on the "immutable tags are never overwritten" check (hit on every ring0→ring1→stable advance during the #870 soak — worked around with raw git/refs PATCH calls). Add --promote: move <agent>/<channel> to the EXISTING release commit without recreating the tag. Requires --channel, errors if the release tag is absent (can't promote what wasn't cut), ignores --ref (the release's own commit is authoritative). Works for both cross-repo (.github via gh api) and this-repo (local git) agents; respects --dry-run / --push. New helper gh_release_commit() dereferences the annotated release tag to its commit. Tests: +4 (requires --channel, errors when absent, moves channel without recreating the tag, dry-run no-op). 50 cut-release bats pass, shellcheck clean. This is the channel-move primitive the #501 auto-promoter needs; until it lands the soak loop moved channels via raw API. Refs #501, #870. * fix(reviews): address review comments [skip ci-relay] --------- Co-authored-by: Claude Code Bot <bot@petry-projects> Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
#992) * feat(cut-release): add --promote for ring-to-ring channel moves (#501) cut-release.sh --channel always tries to CREATE the immutable <agent>/vX.Y.Z release tag, so promoting an already-cut version to the next ring aborts on the "immutable tags are never overwritten" check (hit on every ring0→ring1→stable advance during the #870 soak — worked around with raw git/refs PATCH calls). Add --promote: move <agent>/<channel> to the EXISTING release commit without recreating the tag. Requires --channel, errors if the release tag is absent (can't promote what wasn't cut), ignores --ref (the release's own commit is authoritative). Works for both cross-repo (.github via gh api) and this-repo (local git) agents; respects --dry-run / --push. New helper gh_release_commit() dereferences the annotated release tag to its commit. Tests: +4 (requires --channel, errors when absent, moves channel without recreating the tag, dry-run no-op). 50 cut-release bats pass, shellcheck clean. This is the channel-move primitive the #501 auto-promoter needs; until it lands the soak loop moved channels via raw API. Refs #501, #870. * fix(reviews): address review comments [skip ci-relay] --------- Co-authored-by: Claude Code Bot <bot@petry-projects> Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
#992) * feat(cut-release): add --promote for ring-to-ring channel moves (#501) cut-release.sh --channel always tries to CREATE the immutable <agent>/vX.Y.Z release tag, so promoting an already-cut version to the next ring aborts on the "immutable tags are never overwritten" check (hit on every ring0→ring1→stable advance during the #870 soak — worked around with raw git/refs PATCH calls). Add --promote: move <agent>/<channel> to the EXISTING release commit without recreating the tag. Requires --channel, errors if the release tag is absent (can't promote what wasn't cut), ignores --ref (the release's own commit is authoritative). Works for both cross-repo (.github via gh api) and this-repo (local git) agents; respects --dry-run / --push. New helper gh_release_commit() dereferences the annotated release tag to its commit. Tests: +4 (requires --channel, errors when absent, moves channel without recreating the tag, dry-run no-op). 50 cut-release bats pass, shellcheck clean. This is the channel-move primitive the #501 auto-promoter needs; until it lands the soak loop moved channels via raw API. Refs #501, #870. * fix(reviews): address review comments [skip ci-relay] --------- Co-authored-by: Claude Code Bot <bot@petry-projects> Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
#992) * feat(cut-release): add --promote for ring-to-ring channel moves (#501) cut-release.sh --channel always tries to CREATE the immutable <agent>/vX.Y.Z release tag, so promoting an already-cut version to the next ring aborts on the "immutable tags are never overwritten" check (hit on every ring0→ring1→stable advance during the #870 soak — worked around with raw git/refs PATCH calls). Add --promote: move <agent>/<channel> to the EXISTING release commit without recreating the tag. Requires --channel, errors if the release tag is absent (can't promote what wasn't cut), ignores --ref (the release's own commit is authoritative). Works for both cross-repo (.github via gh api) and this-repo (local git) agents; respects --dry-run / --push. New helper gh_release_commit() dereferences the annotated release tag to its commit. Tests: +4 (requires --channel, errors when absent, moves channel without recreating the tag, dry-run no-op). 50 cut-release bats pass, shellcheck clean. This is the channel-move primitive the #501 auto-promoter needs; until it lands the soak loop moved channels via raw API. Refs #501, #870. * fix(reviews): address review comments [skip ci-relay] --------- Co-authored-by: Claude Code Bot <bot@petry-projects> Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
#992) * feat(cut-release): add --promote for ring-to-ring channel moves (#501) cut-release.sh --channel always tries to CREATE the immutable <agent>/vX.Y.Z release tag, so promoting an already-cut version to the next ring aborts on the "immutable tags are never overwritten" check (hit on every ring0→ring1→stable advance during the #870 soak — worked around with raw git/refs PATCH calls). Add --promote: move <agent>/<channel> to the EXISTING release commit without recreating the tag. Requires --channel, errors if the release tag is absent (can't promote what wasn't cut), ignores --ref (the release's own commit is authoritative). Works for both cross-repo (.github via gh api) and this-repo (local git) agents; respects --dry-run / --push. New helper gh_release_commit() dereferences the annotated release tag to its commit. Tests: +4 (requires --channel, errors when absent, moves channel without recreating the tag, dry-run no-op). 50 cut-release bats pass, shellcheck clean. This is the channel-move primitive the #501 auto-promoter needs; until it lands the soak loop moved channels via raw API. Refs #501, #870. * fix(reviews): address review comments [skip ci-relay] --------- Co-authored-by: Claude Code Bot <bot@petry-projects> Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
#992) * feat(cut-release): add --promote for ring-to-ring channel moves (#501) cut-release.sh --channel always tries to CREATE the immutable <agent>/vX.Y.Z release tag, so promoting an already-cut version to the next ring aborts on the "immutable tags are never overwritten" check (hit on every ring0→ring1→stable advance during the #870 soak — worked around with raw git/refs PATCH calls). Add --promote: move <agent>/<channel> to the EXISTING release commit without recreating the tag. Requires --channel, errors if the release tag is absent (can't promote what wasn't cut), ignores --ref (the release's own commit is authoritative). Works for both cross-repo (.github via gh api) and this-repo (local git) agents; respects --dry-run / --push. New helper gh_release_commit() dereferences the annotated release tag to its commit. Tests: +4 (requires --channel, errors when absent, moves channel without recreating the tag, dry-run no-op). 50 cut-release bats pass, shellcheck clean. This is the channel-move primitive the #501 auto-promoter needs; until it lands the soak loop moved channels via raw API. Refs #501, #870. * fix(reviews): address review comments [skip ci-relay] --------- Co-authored-by: Claude Code Bot <bot@petry-projects> Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
#992) * feat(cut-release): add --promote for ring-to-ring channel moves (#501) cut-release.sh --channel always tries to CREATE the immutable <agent>/vX.Y.Z release tag, so promoting an already-cut version to the next ring aborts on the "immutable tags are never overwritten" check (hit on every ring0→ring1→stable advance during the #870 soak — worked around with raw git/refs PATCH calls). Add --promote: move <agent>/<channel> to the EXISTING release commit without recreating the tag. Requires --channel, errors if the release tag is absent (can't promote what wasn't cut), ignores --ref (the release's own commit is authoritative). Works for both cross-repo (.github via gh api) and this-repo (local git) agents; respects --dry-run / --push. New helper gh_release_commit() dereferences the annotated release tag to its commit. Tests: +4 (requires --channel, errors when absent, moves channel without recreating the tag, dry-run no-op). 50 cut-release bats pass, shellcheck clean. This is the channel-move primitive the #501 auto-promoter needs; until it lands the soak loop moved channels via raw API. Refs #501, #870. * fix(reviews): address review comments [skip ci-relay] --------- Co-authored-by: Claude Code Bot <bot@petry-projects> Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
#992) * feat(cut-release): add --promote for ring-to-ring channel moves (#501) cut-release.sh --channel always tries to CREATE the immutable <agent>/vX.Y.Z release tag, so promoting an already-cut version to the next ring aborts on the "immutable tags are never overwritten" check (hit on every ring0→ring1→stable advance during the #870 soak — worked around with raw git/refs PATCH calls). Add --promote: move <agent>/<channel> to the EXISTING release commit without recreating the tag. Requires --channel, errors if the release tag is absent (can't promote what wasn't cut), ignores --ref (the release's own commit is authoritative). Works for both cross-repo (.github via gh api) and this-repo (local git) agents; respects --dry-run / --push. New helper gh_release_commit() dereferences the annotated release tag to its commit. Tests: +4 (requires --channel, errors when absent, moves channel without recreating the tag, dry-run no-op). 50 cut-release bats pass, shellcheck clean. This is the channel-move primitive the #501 auto-promoter needs; until it lands the soak loop moved channels via raw API. Refs #501, #870. * fix(reviews): address review comments [skip ci-relay] --------- Co-authored-by: Claude Code Bot <bot@petry-projects> Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
#992) * feat(cut-release): add --promote for ring-to-ring channel moves (#501) cut-release.sh --channel always tries to CREATE the immutable <agent>/vX.Y.Z release tag, so promoting an already-cut version to the next ring aborts on the "immutable tags are never overwritten" check (hit on every ring0→ring1→stable advance during the #870 soak — worked around with raw git/refs PATCH calls). Add --promote: move <agent>/<channel> to the EXISTING release commit without recreating the tag. Requires --channel, errors if the release tag is absent (can't promote what wasn't cut), ignores --ref (the release's own commit is authoritative). Works for both cross-repo (.github via gh api) and this-repo (local git) agents; respects --dry-run / --push. New helper gh_release_commit() dereferences the annotated release tag to its commit. Tests: +4 (requires --channel, errors when absent, moves channel without recreating the tag, dry-run no-op). 50 cut-release bats pass, shellcheck clean. This is the channel-move primitive the #501 auto-promoter needs; until it lands the soak loop moved channels via raw API. Refs #501, #870. * fix(reviews): address review comments [skip ci-relay] --------- Co-authored-by: Claude Code Bot <bot@petry-projects> Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
… promotion text Addresses CodeAnt review findings on #1956: - AGENTS.md: an existing release tag does not prove `next` moved, because autocut creates the release before moving the channel. Tell readers to compare `<agent>/v<M>-next` with the release's commit and to use `--promote` (not a new cut) if it lags. - AGENTS.md channel-skew step 2: show `cut-release.sh --promote --channel` for moving to an existing release. Without `--promote` it always cuts a new tag and fails when the version exists. - docs/release/runbook.md: add a "current state" note pointing at the Release Manager automation and at the AGENTS.md section. Replace the "Phase-1 human-driven" promotion rule, the stale "no channel-only-move mode / use git tag -f + push --force" gap (superseded by --promote #992; a force-push of a protected channel is rejected with GH013), the stale cross-repo "refuses a live cut" note (#872 wired), and the "#501 is future work" bullets. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015fdDZDb4mhT65MU1izeA4R
…tes release tags (#1956) * docs(agents): document Release Manager automation that cuts and promotes release tags AGENTS.md told contributors that a merge stays inert until someone runs `cut-release.sh`, and called the health-gated promotion workflow "forthcoming". In practice the Release Manager (the `Canary Rollout` workflow in petry-projects/.github, acting as the petry-projects-release-manager[bot] App) already auto-cuts `<agent>/vX.Y.Z` and moves `<agent>/v<MAJOR>-next` every 4h sweep, and promotes through the rings when armed. That left sessions hand-cutting after merges and colliding with tags the bot had already created. - Reframe "Merging to main does not activate agent code": still inert on merge, but `next` catches up on the next autocut sweep and later rings move by gated promotion. The rule is now to state when a change reaches each channel. - New "Release automation — who cuts and moves tags" subsection: autocut / promote-all / sync-issues, their arm variables (CANARY_AUTO_CUT, CANARY_AUTO_PROMOTE), bump detection, watched paths, require_confirmation (today only dev-lead ring1->stable), when to hand-cut, rollback paths, and that a human go/no-go must be configured in canary-rings.json before the candidate reaches the ring. - Replace the stale "(forthcoming) promotion workflow" bullet and update the channel-skew sequencing step accordingly. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015fdDZDb4mhT65MU1izeA4R * docs(release): fix tag-check race, --promote usage, and stale runbook promotion text Addresses CodeAnt review findings on #1956: - AGENTS.md: an existing release tag does not prove `next` moved, because autocut creates the release before moving the channel. Tell readers to compare `<agent>/v<M>-next` with the release's commit and to use `--promote` (not a new cut) if it lags. - AGENTS.md channel-skew step 2: show `cut-release.sh --promote --channel` for moving to an existing release. Without `--promote` it always cuts a new tag and fails when the version exists. - docs/release/runbook.md: add a "current state" note pointing at the Release Manager automation and at the AGENTS.md section. Replace the "Phase-1 human-driven" promotion rule, the stale "no channel-only-move mode / use git tag -f + push --force" gap (superseded by --promote #992; a force-push of a protected channel is rejected with GH013), the stale cross-repo "refuses a live cut" note (#872 wired), and the "#501 is future work" bullets. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015fdDZDb4mhT65MU1izeA4R --------- Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>



Summary
cut-release.sh --channelalways tries to create the immutable<agent>/vX.Y.Zrelease tag, so promoting an already-cut version to the next ring aborts on the immutability check. This blocked everyring0→ring1→stableadvance during the #870 soak (worked around with rawgit/refsPATCH calls).--promoteadds the missing channel-move-only primitive:<agent>/<channel>to the existing release commit; never recreates the tag.--channel; errors if the release tag is absent (can't promote what wasn't cut); ignores--ref..githubviagh api) and this-repo (local git) agents; honors--dry-run/--push.Tests
New
gh_release_commit()helper (dereferences the annotated tag → commit). +4 bats (requires--channel; errors when release absent; moves channel without recreating the tag; dry-run no-op). 50 cut-release bats pass,shellcheck --severity=warningclean. Verified live in--dry-runagainst the in-flightagent-shield/v2.1.0.This is the advance primitive the #501 auto-promoter consumes.
Refs #501, #870.
🤖 Generated with Claude Code