Skip to content

fix(ci): make auto-rollover dedup fail-closed and add merged-PR guard#2193

Merged
Aureliolo merged 4 commits into
mainfrom
ci/auto-rollover-dedup-guard
Jun 1, 2026
Merged

fix(ci): make auto-rollover dedup fail-closed and add merged-PR guard#2193
Aureliolo merged 4 commits into
mainfrom
ci/auto-rollover-dedup-guard

Conversation

@Aureliolo
Copy link
Copy Markdown
Owner

Summary

The Auto Rollover workflow opened a duplicate rollover PR (#2190, now closed) for v0.9.0 even though the rollover for that version had already merged (#2177) and release-please PR #2178 already targets 0.9.0.

Root cause

The workflow re-runs on every push to main and decides "rollover needed" from last-stable-patch >= 9, which stays true for the whole window between the rollover merge and the 0.9.0 release (0.9.0 is not tagged yet, so last stable is still v0.8.9). The only guard preventing a repeat rollover PR in that window was:

if git log "${LAST_STABLE}..HEAD" --format=%B | grep -qE '^Release-As:'; then ... skip

This fails open. On the 01 Jun 10:26 run, that run's checkout did not materialise the v0.8.9<->HEAD connection, so the range came up empty, grep matched nothing, the if was false, and the workflow fell through to needed=true. Every other run since #2177 merged correctly detected the trailer and skipped; only this one slipped through. The two other safety nets did not cover the window: the release-please-body guard matches a Release-As: trailer (the release PR body is a changelog, no trailer), and the create-step open-PR guard was moot because #2177 was already merged/closed.

Fix

  • New primary guard (history-independent). Query GitHub directly for an already-merged-or-open rollover PR on chore/auto-rollover-v<NEXT>; skip if one exists. This holds regardless of local git-history completeness, which is what failed before. The branch name carries the version, so a merged v0.(X+1).0 rollover never suppresses the next version's rollover; a CLOSED-not-merged PR (manual cancel) is intentionally not a skip.
  • Git-log guard now fails closed. Capture git log into a variable and skip the run if it errors, instead of an inline git log | grep that conflated a git log failure with a genuine no-match under set -o pipefail. A missed rollover self-heals on the next push to main; a spurious PR does not.
  • Kept the release-please-body guard; removed the now-duplicate NEXT_VERSION computation.
  • Updated docs/reference/claude-reference.md (was "three skip guards"; now four + fail-closed note) and tightened the new workflow comments to present-tense rationale.

Test plan

  • actionlint, zizmor, yamllint: clean on the workflow.
  • vale + lychee: clean on the doc.
  • Verified locally that chore: auto-rollover to v0.9.0 #2177's Release-As: 0.9.0 trailer is an ancestor of the head that opened chore: auto-rollover to v0.9.0 #2190 and that the range-grep matches with full history present, confirming the bug is the checkout-history edge plus the fail-open guard, not a logic error in the trailer match.
  • Walked all five auto-rollover runs since chore: auto-rollover to v0.9.0 #2177 merged: four skipped correctly, only the 10:26 run fell through.

Review coverage

Pre-reviewed by 3 agents (infra-reviewer, docs-consistency, comment-quality-rot). All valid findings addressed: comment hygiene (dropped incident/migration framing and a stale issue ref), and the "three skip guards" doc drift. The infra reviewer confirmed the shell idioms (if ! VAR=$(...), printf '%s'), the gh pr list jq filter, the least-privilege token/permissions, and the NEXT_VERSION move are correct, and that the gh pr list call fails closed (a GitHub API outage aborts the step into the existing failure tracker rather than risking a duplicate).

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 1, 2026

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 1, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: dac8e3c4-a6f3-4d88-a928-5a916609f052

📥 Commits

Reviewing files that changed from the base of the PR and between 4cac60a and feb736d.

📒 Files selected for processing (1)
  • docs/reference/claude-reference.md
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Build Web Assets (melange)
  • GitHub Check: Lighthouse Site
  • GitHub Check: Analyze (go)
  • GitHub Check: Build Preview
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (actions)
  • GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (1)
{README,CLAUDE,*.md,docs/**/*.md}

📄 CodeRabbit inference engine (CLAUDE.md)

Numerics in README and public docs must be sourced from data/runtime_stats.yaml via markers

Files:

  • docs/reference/claude-reference.md
🧠 Learnings (4)
📚 Learning: 2026-05-16T18:36:31.446Z
Learnt from: Aureliolo
Repo: Aureliolo/synthorg PR: 1944
File: docs/reference/conventions.md:787-789
Timestamp: 2026-05-16T18:36:31.446Z
Learning: In Aureliolo/synthorg, do not require adding `<!--RS:...-->` “Doc Numeric Claims (MANDATORY)” numeric macros for Python version numbers mentioned in documentation prose (e.g., “Python 3.14”, “Python 3.15”). The `scripts/check_doc_numeric_macros.py` gate only applies to `README.md`, `docs/index.md`, `docs/roadmap/index.md`, `docs/architecture/decisions.md`, and `docs/reference/convention-gates.md`, and it only flags digits adjacent to specific stat nouns (tests/providers/agents/stars/releases), not language version mentions like “Python 3.14”.

Applied to files:

  • docs/reference/claude-reference.md
📚 Learning: 2026-05-16T18:36:35.250Z
Learnt from: Aureliolo
Repo: Aureliolo/synthorg PR: 1944
File: docs/getting_started.md:109-109
Timestamp: 2026-05-16T18:36:35.250Z
Learning: When reviewing Markdown in the synthorg repo, account for the CI gate `check_doc_numeric_macros.py`: it skips fenced code blocks entirely, and it only flags digits that are adjacent to these stat nouns: `tests`, `providers`, `agents`, `stars`, `releases`. Therefore, numeric examples such as CLI flag values (e.g., `--num-workers=4` in fenced bash blocks) and prose version numbers (e.g., `3.14`/`3.15`) are not expected to trigger this check; prioritize changes only when digits appear next to one of the listed nouns (e.g., “5 tests”, “10 stars”, etc.).

Applied to files:

  • docs/reference/claude-reference.md
📚 Learning: 2026-05-16T18:36:35.250Z
Learnt from: Aureliolo
Repo: Aureliolo/synthorg PR: 1944
File: docs/getting_started.md:109-109
Timestamp: 2026-05-16T18:36:35.250Z
Learning: When reviewing markdown files for the "Doc Numeric Claims (MANDATORY)" RS-marker rule, only require/flag missing RS markers in the files that are actually in-scope for the rule. The scope is enforced via an identical _SCOPED_FILES allowlist in scripts/check_doc_numeric_macros.py and scripts/inject_runtime_stats.py, and currently includes: README.md; docs/index.md; docs/roadmap/index.md; docs/architecture/decisions.md; docs/reference/convention-gates.md. For any other markdown files (e.g., docs/getting_started.md, docs/guides/*), missing RS markers for numeric claims are no-ops and should NOT be flagged.

Applied to files:

  • docs/reference/claude-reference.md
📚 Learning: 2026-05-16T18:36:35.250Z
Learnt from: Aureliolo
Repo: Aureliolo/synthorg PR: 1944
File: docs/getting_started.md:109-109
Timestamp: 2026-05-16T18:36:35.250Z
Learning: When reviewing Markdown in the synthorg repo against the `check_doc_numeric_macros.py` gate, account for its documented behavior: it skips fenced code blocks entirely, and it only flags digits that are adjacent to specific stat nouns (`tests`, `providers`, `agents`, `stars`, `releases`). As a result, CLI-style numbers (e.g., `--num-workers=4`) inside fenced bash code blocks should never be treated as violations of this gate; only non-fenced text needs checking, and only around those specific nouns.

Applied to files:

  • docs/reference/claude-reference.md
🪛 LanguageTool
docs/reference/claude-reference.md

[uncategorized] ~99-~99: The official name of this software platform is spelled with a capital “H”.
Context: ...ynthorg_rollover_at_patchthreshold in.github/release-please-config.json` (default 9)...

(GITHUB)

🔇 Additional comments (1)
docs/reference/claude-reference.md (1)

99-99: LGTM!


Walkthrough

The auto-rollover workflow's decision logic is refactored to strengthen deduplication and safety. The next rollover version and version-specific branch name are now precomputed early, followed by a GitHub PR query to skip the rollover if a merged or open PR already exists for that branch. The Release-As trailer detection is reworked to explicitly handle git log failures rather than treating failure the same as no match. The later NEXT_VERSION reassignment is removed since the value is precomputed earlier. Reference documentation is updated to reflect the new skip condition.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix(ci): make auto-rollover dedup fail-closed and add merged-PR guard' accurately and concisely summarizes the main changes: fixing a CI bug by adding fail-closed deduplication and a merged-PR guard to the auto-rollover workflow.
Description check ✅ Passed The description is comprehensively related to the changeset, providing detailed root cause analysis, the specific fix implemented, test plan, and review coverage for the auto-rollover workflow and documentation changes.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a bug in the Auto Rollover workflow where duplicate release PRs were occasionally generated due to incomplete git history during workflow execution. By introducing a history-independent check against the GitHub API and hardening existing git-log logic to fail closed, the workflow is now more resilient against environment-specific checkout issues.

Highlights

  • New History-Independent Guard: Added a check using 'gh pr list' to verify if a rollover PR for the target version already exists (merged or open), preventing duplicate PR creation regardless of local git history state.
  • Fail-Closed Git-Log Guard: Updated the git-log range check to fail closed; if the command fails (e.g., due to incomplete fetch), the workflow now skips rather than potentially triggering a duplicate rollover.
  • Documentation Update: Updated 'docs/reference/claude-reference.md' to reflect the transition from three to four skip guards and added notes on the new fail-closed logic.
Ignored Files
  • Ignored by pattern: .github/workflows/** (1)
    • .github/workflows/auto-rollover.yml
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request updates the documentation in docs/reference/claude-reference.md to accurately reflect the behavior of the auto-rollover.yml workflow, expanding the description of its skip guards from three to four. The updated documentation details new history-independent checks using gh pr list and fail-closed evaluations of the Release-As: trailer range. There are no review comments, and I have no feedback to provide.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

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 `@docs/reference/claude-reference.md`:
- Line 99: The doc incorrectly states that auto-rollover appends the Release-As:
trailer to an empty commit and PATCHes refs/heads/main; update the wording in
the auto-rollover section (mentioning auto-rollover.yml and
__synthorg_rollover_at_patch) to reflect the actual merge path: the workflow
creates/updates a rollover branch ref (not directly PATCHing refs/heads/main),
places the Release-As: trailer in the PR body, and relies on a squash-merge to
land the trailer on main, and also remove or correct the claim about POST
/git/commits + PATCH /git/refs/heads/main so it matches the branch-ref + PR
flow.
🪄 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: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 27a74b66-a15c-4327-801a-f6ff07aea085

📥 Commits

Reviewing files that changed from the base of the PR and between b4ac770 and 4cac60a.

📒 Files selected for processing (2)
  • .github/workflows/auto-rollover.yml
  • docs/reference/claude-reference.md
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Lighthouse Site
  • GitHub Check: Build Web Assets (melange)
  • GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (1)
{README,CLAUDE,*.md,docs/**/*.md}

📄 CodeRabbit inference engine (CLAUDE.md)

Numerics in README and public docs must be sourced from data/runtime_stats.yaml via markers

Files:

  • docs/reference/claude-reference.md
🧠 Learnings (4)
📚 Learning: 2026-05-16T18:36:31.446Z
Learnt from: Aureliolo
Repo: Aureliolo/synthorg PR: 1944
File: docs/reference/conventions.md:787-789
Timestamp: 2026-05-16T18:36:31.446Z
Learning: In Aureliolo/synthorg, do not require adding `<!--RS:...-->` “Doc Numeric Claims (MANDATORY)” numeric macros for Python version numbers mentioned in documentation prose (e.g., “Python 3.14”, “Python 3.15”). The `scripts/check_doc_numeric_macros.py` gate only applies to `README.md`, `docs/index.md`, `docs/roadmap/index.md`, `docs/architecture/decisions.md`, and `docs/reference/convention-gates.md`, and it only flags digits adjacent to specific stat nouns (tests/providers/agents/stars/releases), not language version mentions like “Python 3.14”.

Applied to files:

  • docs/reference/claude-reference.md
📚 Learning: 2026-05-16T18:36:35.250Z
Learnt from: Aureliolo
Repo: Aureliolo/synthorg PR: 1944
File: docs/getting_started.md:109-109
Timestamp: 2026-05-16T18:36:35.250Z
Learning: When reviewing Markdown in the synthorg repo, account for the CI gate `check_doc_numeric_macros.py`: it skips fenced code blocks entirely, and it only flags digits that are adjacent to these stat nouns: `tests`, `providers`, `agents`, `stars`, `releases`. Therefore, numeric examples such as CLI flag values (e.g., `--num-workers=4` in fenced bash blocks) and prose version numbers (e.g., `3.14`/`3.15`) are not expected to trigger this check; prioritize changes only when digits appear next to one of the listed nouns (e.g., “5 tests”, “10 stars”, etc.).

Applied to files:

  • docs/reference/claude-reference.md
📚 Learning: 2026-05-16T18:36:35.250Z
Learnt from: Aureliolo
Repo: Aureliolo/synthorg PR: 1944
File: docs/getting_started.md:109-109
Timestamp: 2026-05-16T18:36:35.250Z
Learning: When reviewing markdown files for the "Doc Numeric Claims (MANDATORY)" RS-marker rule, only require/flag missing RS markers in the files that are actually in-scope for the rule. The scope is enforced via an identical _SCOPED_FILES allowlist in scripts/check_doc_numeric_macros.py and scripts/inject_runtime_stats.py, and currently includes: README.md; docs/index.md; docs/roadmap/index.md; docs/architecture/decisions.md; docs/reference/convention-gates.md. For any other markdown files (e.g., docs/getting_started.md, docs/guides/*), missing RS markers for numeric claims are no-ops and should NOT be flagged.

Applied to files:

  • docs/reference/claude-reference.md
📚 Learning: 2026-05-16T18:36:35.250Z
Learnt from: Aureliolo
Repo: Aureliolo/synthorg PR: 1944
File: docs/getting_started.md:109-109
Timestamp: 2026-05-16T18:36:35.250Z
Learning: When reviewing Markdown in the synthorg repo against the `check_doc_numeric_macros.py` gate, account for its documented behavior: it skips fenced code blocks entirely, and it only flags digits that are adjacent to specific stat nouns (`tests`, `providers`, `agents`, `stars`, `releases`). As a result, CLI-style numbers (e.g., `--num-workers=4`) inside fenced bash code blocks should never be treated as violations of this gate; only non-fenced text needs checking, and only around those specific nouns.

Applied to files:

  • docs/reference/claude-reference.md
🪛 LanguageTool
docs/reference/claude-reference.md

[uncategorized] ~99-~99: The official name of this software platform is spelled with a capital “H”.
Context: ...ynthorg_rollover_at_patchthreshold in.github/release-please-config.json` (default 9)...

(GITHUB)

🔇 Additional comments (1)
.github/workflows/auto-rollover.yml (1)

79-79: LGTM!

Also applies to: 122-160

Comment thread docs/reference/claude-reference.md Outdated
@Aureliolo Aureliolo merged commit 1536bd3 into main Jun 1, 2026
82 checks passed
@Aureliolo Aureliolo deleted the ci/auto-rollover-dedup-guard branch June 1, 2026 21:42
@Aureliolo Aureliolo temporarily deployed to cloudflare-preview June 1, 2026 21:42 — with GitHub Actions Inactive
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