ci: auto-rebase open PRs on main push - #313
Conversation
Reviewer's GuideAdds a GitHub Actions workflow that automatically rebases all open PR branches targeting main whenever main is updated or the workflow is manually triggered, force-pushing clean rebases and labeling/commenting on PRs that encounter conflicts. Sequence diagram for auto-rebase of a single PR on main pushsequenceDiagram
participant GitHub
participant Workflow as auto-rebase-open-prs
participant gh as gh_CLI
participant Git as Git_local
participant API as GitHub_API
participant PR as Pull_Request
GitHub->>Workflow: Trigger on push to main
Workflow->>Git: actions/checkout with full history
Workflow->>Git: Configure bot user
Workflow->>gh: gh pr list --state open --base main
gh->>API: List open PRs base=main
API-->>gh: PR list (number, headRefName)
gh-->>Workflow: Encoded PR data
loop For each PR
Workflow->>Git: git fetch origin head
alt fetch succeeds
Workflow->>Git: git checkout -B head origin/head
Workflow->>Git: git merge-base --is-ancestor origin/main HEAD
alt Already on top of main
Git-->>Workflow: is-ancestor true
Workflow->>Workflow: Skip rebase
else Behind main
Git-->>Workflow: is-ancestor false
Workflow->>Git: git rebase origin/main
alt Rebase clean
Git-->>Workflow: Rebase success
Workflow->>Git: git push --force-with-lease origin head
alt Push succeeds
Git-->>Workflow: Push success
Workflow->>gh: gh pr edit --remove-label merge-conflict
gh->>API: Remove merge-conflict label
API-->>gh: Label updated
else Push rejected
Git-->>Workflow: Push rejected
Workflow->>Git: git rebase --abort
end
else Rebase has conflicts
Git-->>Workflow: Rebase conflict
Workflow->>Git: git rebase --abort
Workflow->>gh: gh pr edit --add-label merge-conflict
gh->>API: Add merge-conflict label
API-->>gh: Label added
Workflow->>gh: gh pr comment with recovery instructions
gh->>API: Create PR comment
API-->>gh: Comment created
end
end
else fetch fails
Git-->>Workflow: Fetch error
Workflow->>Workflow: Skip this PR
end
end
Note over PR,Workflow: PR ends either updated on main or flagged with merge-conflict
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
Warning Rate limit exceeded
To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughAdds a GitHub Actions workflow that lists open PRs targeting Changes
Sequence Diagram(s)sequenceDiagram
participant Scheduler as GitHub Actions
participant GH_API as GitHub API
participant Runner as Workflow Runner (git)
participant Remote as origin/main
Scheduler->>GH_API: List open PRs (base=main)
loop per PR
GH_API->>Runner: Fetch PR head branch
Runner->>Remote: fetch origin/main
Runner->>Runner: git merge-base --is-ancestor?
alt up-to-date
Runner->>GH_API: no-op / skip
else needs rebase
Runner->>Runner: git rebase origin/main
alt rebase success
Runner->>Remote: git push --force-with-lease
alt push success
Runner->>GH_API: remove merge-conflict label (if present)
else push failed
Runner->>Runner: git rebase --abort
Runner->>GH_API: leave PR for future retry
end
else rebase conflict
Runner->>Runner: git rebase --abort
Runner->>GH_API: add merge-conflict label
Runner->>GH_API: post comment with manual rebase commands
end
end
end
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ 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. Review rate limit: 0/1 reviews remaining, refill in 56 minutes and 48 seconds.Comment |
There was a problem hiding this comment.
Hey - I've found 1 issue, and left some high level feedback:
- Consider explicitly skipping PRs from forks (e.g., by querying
headRepositoryOwnerand comparing to the main repo) so the workflow doesn’t repeatedly log fetch failures for branches that aren’t available on theoriginremote. - To avoid noisy duplicate comments on long-lived conflicted PRs, you might gate the
merge-conflictcomment on whether the label was just added or whether a previous bot comment already exists. - It may be worth adding a
concurrencygroup to this workflow so that only the latest run formainis active, preventing overlapping jobs from fighting over rebases and force-pushes.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Consider explicitly skipping PRs from forks (e.g., by querying `headRepositoryOwner` and comparing to the main repo) so the workflow doesn’t repeatedly log fetch failures for branches that aren’t available on the `origin` remote.
- To avoid noisy duplicate comments on long-lived conflicted PRs, you might gate the `merge-conflict` comment on whether the label was just added or whether a previous bot comment already exists.
- It may be worth adding a `concurrency` group to this workflow so that only the latest run for `main` is active, preventing overlapping jobs from fighting over rebases and force-pushes.
## Individual Comments
### Comment 1
<location path=".github/workflows/auto-rebase-open-prs.yml" line_range="39-40" />
<code_context>
+ run: |
+ set -e
+ # JSON: [{number, headRefName, baseRefName}]
+ prs=$(gh pr list --state open --base main \
+ --json number,headRefName,baseRefName \
+ --jq '.[] | @base64')
+
</code_context>
<issue_to_address>
**question (bug_risk):** This will silently skip PRs from forks, which may or may not match the intended behavior.
`git fetch origin "$head"` will always fail for fork-based PRs, so they’ll always take the "fetch failed, skip" path and never be auto-rebased, even though `gh pr list` includes them. If you only want same-repo PRs, filter them explicitly in the `gh pr list` JSON (e.g., via `headRepositoryOwner`/`headRepository`). If you do want to support forks, you’ll need a different approach than force-pushing to `origin/$head`.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
|
[claim:review:Setr:2026-04-29T16:24:08Z] |
|
Review: discretion grep on the diff catches one banned phrase in
Or just drop the sentence — the file purpose is already explained in the lines above. Otherwise the workflow logic looks correct (rebase, force-with-lease, conflict-flag with recovery one-liner). Sourcery + pattern-scan + history-scan + pytest all green. Holding merge until the line is reworded. Will pick this back up once it lands. |
|
[release:review:Setr:2026-04-29T16:25:07Z] |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/auto-rebase-open-prs.yml:
- Line 23: Replace the floating tag actions/checkout@v4 with a pinned commit SHA
by changing actions/checkout@v4 to actions/checkout@<COMMIT_SHA> (use the full
40-char commit from the actions/checkout repo for the v4 release) and keep the
human-readable tag in a trailing comment, e.g. actions/checkout@<COMMIT_SHA> #
v4, so the workflow is pinned while still showing the version.
- Around line 39-41: The PR listing command stored in the prs variable uses gh
pr list which defaults to 30 results; update the gh pr list invocation (the
command assigned to prs) to explicitly request all PRs by adding the --limit 0
flag (e.g., change "gh pr list --state open --base main --json ..." to "gh pr
list --limit 0 --state open --base main --json ...") so the workflow processes
every open PR rather than the default paginated 30.
- Around line 69-75: Replace the double-quoted inline body passed to gh pr
comment (the block that contains the escaped backticks and $head) with a heredoc
to avoid YAML/quote escaping, and make the branch checkout safe by quoting the
variable (use git checkout "$head" or compute safe_head="$(printf '%q' "$head")"
and use that). Specifically, change the gh pr comment invocation to use a
here-doc (gh pr comment "$num" --body <<EOF ... EOF) containing the
triple-backtick fenced block and use git checkout "$head" (or "$safe_head")
inside it so branch names with spaces/special chars are handled correctly.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 2bedaba2-afac-4140-a352-37b5fa972af9
📒 Files selected for processing (1)
.github/workflows/auto-rebase-open-prs.yml
|
Reworded line 6 — |
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (3)
.github/workflows/auto-rebase-open-prs.yml (3)
23-23:⚠️ Potential issue | 🟠 Major | ⚡ Quick winPin
actions/checkoutto an immutable SHA.Line 23 is still using a floating tag (
@v4), which violates the workflow supply-chain pinning rule.Suggested fix
- - uses: actions/checkout@v4 + - uses: actions/checkout@<FULL_40_CHAR_SHA> # v4.x.xAs per coding guidelines, "Third-party actions must be pinned to a commit SHA, with the version tag in a trailing comment. Flag any unpinned
@v*ref."🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/auto-rebase-open-prs.yml at line 23, Replace the floating actions/checkout@v4 reference with a pinned commit SHA: update the uses entry that currently reads "uses: actions/checkout@v4" to use the specific immutable SHA for the desired v4 release (e.g., "uses: actions/checkout@<COMMIT_SHA>") and include the original tag as a trailing comment (e.g., "# v4") so the tag is recorded but the workflow is pinned; ensure this change is applied where "uses: actions/checkout@v4" appears.
69-75:⚠️ Potential issue | 🔴 Critical | ⚡ Quick winFix invalid YAML in conflict comment body (workflow currently won’t parse).
Lines 69-75 use escaped triple backticks inside a double-quoted YAML string, which is invalid YAML syntax and breaks the workflow.
Suggested fix
- gh pr comment "$num" --body \ -"Auto-rebase onto main failed: conflicts. Resolve locally: -\`\`\` -git fetch origin && git checkout $head && git rebase origin/main -# resolve, then -git push --force-with-lease -\`\`\`" 2>/dev/null || true + gh pr comment "$num" --body-file - <<EOF 2>/dev/null || true +Auto-rebase onto main failed: conflicts. Resolve locally: +``` +git fetch origin && git checkout "$head" && git rebase origin/main +# resolve, then +git push --force-with-lease +``` +EOF🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/auto-rebase-open-prs.yml around lines 69 - 75, The workflow comment currently embeds escaped triple backticks inside a double-quoted YAML string causing invalid YAML; update the gh pr comment invocation (the command that calls gh pr comment "$num" --body) to use a YAML-safe multiline string (here-doc / EOF or block scalar) for the --body so the backtick fence is not escaped, include the branch variable quoted (use "$head") inside the here-doc, end the here-doc after the final backtick fence, and ensure the entire gh pr comment command redirects errors as before (2>/dev/null || true) so the job parses and preserves the intended message with a proper git fetch/checkout/rebase sequence and the fenced code block.
39-41:⚠️ Potential issue | 🟠 Major | ⚡ Quick winProcess all open PRs explicitly (avoid default
ghpagination).Line 39 uses
gh pr listwithout--limit; default pagination can skip PRs beyond the first page, so rebases become incomplete.Suggested fix
- prs=$(gh pr list --state open --base main \ + prs=$(gh pr list --state open --base main --limit 1000 \ --json number,headRefName,baseRefName \ --jq '.[] | `@base64`')🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/auto-rebase-open-prs.yml around lines 39 - 41, The gh pr list invocation stored in the prs variable can miss PRs due to default pagination; update the command used to build prs (the prs=$(gh pr list --state open --base main --json number,headRefName,baseRefName --jq '.[] | `@base64`')) to include an explicit limit flag (e.g., add --limit 1000) so all open PRs are returned and processed rather than only the first page.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/auto-rebase-open-prs.yml:
- Around line 39-50: The current loop that iterates over prs uses git fetch
origin "$head" and git checkout -B "$head" "origin/$head" which silently fails
for fork-based PRs; change the fetch/checkout to use GitHub's PR head ref
(refs/pull/<num>/head) for every PR number (num) so both fork and same-repo PRs
are fetched and checked out reliably; update the fetch invocation that uses
"$head" and the checkout invocation that references "origin/$head" to instead
fetch refs/pull/$num/head and create/checkout the local branch from that fetched
ref.
---
Duplicate comments:
In @.github/workflows/auto-rebase-open-prs.yml:
- Line 23: Replace the floating actions/checkout@v4 reference with a pinned
commit SHA: update the uses entry that currently reads "uses:
actions/checkout@v4" to use the specific immutable SHA for the desired v4
release (e.g., "uses: actions/checkout@<COMMIT_SHA>") and include the original
tag as a trailing comment (e.g., "# v4") so the tag is recorded but the workflow
is pinned; ensure this change is applied where "uses: actions/checkout@v4"
appears.
- Around line 69-75: The workflow comment currently embeds escaped triple
backticks inside a double-quoted YAML string causing invalid YAML; update the gh
pr comment invocation (the command that calls gh pr comment "$num" --body) to
use a YAML-safe multiline string (here-doc / EOF or block scalar) for the --body
so the backtick fence is not escaped, include the branch variable quoted (use
"$head") inside the here-doc, end the here-doc after the final backtick fence,
and ensure the entire gh pr comment command redirects errors as before
(2>/dev/null || true) so the job parses and preserves the intended message with
a proper git fetch/checkout/rebase sequence and the fenced code block.
- Around line 39-41: The gh pr list invocation stored in the prs variable can
miss PRs due to default pagination; update the command used to build prs (the
prs=$(gh pr list --state open --base main --json number,headRefName,baseRefName
--jq '.[] | `@base64`')) to include an explicit limit flag (e.g., add --limit
1000) so all open PRs are returned and processed rather than only the first
page.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 8311fd42-a3aa-423b-a90a-4619848e479a
📒 Files selected for processing (1)
.github/workflows/auto-rebase-open-prs.yml
Cuts cross-session rebase churn. Every push to main fetches each open PR branch, attempts rebase onto origin/main, and force-pushes if clean. Conflicts get a merge-conflict label + recovery comment so the author sees them in the next aelf-scan section 3.
3ca9ffc to
9e864b6
Compare
- Pin actions/checkout to commit SHA (v4.3.1) per supply-chain rule. - Add concurrency group so overlapping main pushes don't fight on rebase/force-push. - gh pr list --limit 1000 to disable default 30-PR pagination. - Skip fork PRs explicitly (isCrossRepository) — GITHUB_TOKEN can't force-push to forks. - Replace invalid double-quoted YAML body (escaped backticks) with mktemp + echo file, then --body-file. - Gate conflict explainer comment on absence of merge-conflict label so long-lived conflicted PRs aren't spammed on every main push.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/auto-rebase-open-prs.yml:
- Around line 68-75: The current workflow always posts the conflict comment
regardless of prior state; change the logic so you only post the comment when a
PR transitions into conflicted state by checking labels first. Use gh pr view
"$num" --json labels (or inspect the output of gh pr edit "$num" --add-label
merge-conflict) to determine whether the merge-conflict label already exists for
"$num", and only run gh pr comment "$num" --body ... when the label was not
previously present (i.e., when you successfully added the merge-conflict label
or detected it as newly added); keep the existing label-add step (gh pr edit
"$num" --add-label merge-conflict) but gate the gh pr comment invocation on the
label being newly applied.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 6824d05c-2d9d-474d-94a9-0b6feb174c47
📒 Files selected for processing (1)
.github/workflows/auto-rebase-open-prs.yml
|
[claim:review:Gylf:2026-04-30T09:14:26Z] |
|
Concern before merge: force-pushes performed with Effect: after this workflow rebases and force-pushes, the PR's required status checks ( Two fixes:
Option 1 is cleaner. Worth confirming locally — land a no-op rebase and check whether Otherwise the workflow looks correct: pinned action SHA, |
|
[release:review:Gylf:2026-04-30T09:15:12Z] |
|
[claim:review:Setr:2026-04-30T09:16:26Z] |
|
Resolved CodeRabbit's fork-fetch thread: the workflow already skips fork PRs explicitly ( |
Summary
.github/workflows/auto-rebase-open-prs.ymlfires on push tomainand onworkflow_dispatch.base=main, fetches the head branch, attemptsgit rebase origin/main, force-pushes if clean.merge-conflictlabel and a comment with the local-recovery one-liner.Why
Three concurrent sessions opening PRs against main means every merge invalidates ~2 in-flight PRs. Reviewer hits "BLOCKED — needs rebase" and bounces. This eliminates the manual rebase step for the common (clean) case and makes real conflicts surface as a flag.
Resolves
Refs #256 review thrash (5+ claim/release cycles before merge).
Test plan
merge-conflictlabel + comment.Summary by Sourcery
CI:
Summary by CodeRabbit