ci(merge-thrash): pr-size-soft-cap advisory workflow (#602) - #603
Conversation
Reviewer's GuideAdds a new GitHub Actions workflow that posts an advisory sticky comment on oversized PRs based on LOC and file-count thresholds, with opt-out via label and automatic cleanup when PRs shrink, plus a corresponding CHANGELOG entry. Sequence diagram for pr-size-soft-cap advisory workflow on PR eventssequenceDiagram
actor Author
participant GitHub
participant Workflow as pr-size-soft-cap_workflow
participant Script as size_check_script
participant GHAPI as GitHub_API
Author->>GitHub: Open / update / relabel PR
GitHub-->>Workflow: pull_request event (opened / synchronize / reopened / labeled / unlabeled)
alt PR is draft
Workflow-->>GitHub: Workflow skipped (if draft == true)
else PR is ready for review
Workflow->>Script: Run size-check job with PR payload env
Script->>Script: Check PR_LABELS for size:override
alt size:override present
Script-->>GitHub: Exit without comment
else no override label
Script->>Script: Compute loc = additions + deletions
Script->>Script: Read files = changed_files
Script->>GHAPI: List PR comments (issues/{PR_NUMBER}/comments)
GHAPI-->>Script: Existing comments
Script->>Script: Find existing sticky by MARKER and github-actions[bot]
alt loc <= LOC_LIMIT and files <= FILES_LIMIT
alt existing sticky found
Script->>GHAPI: DELETE issues/comments/{existing_id}
GHAPI-->>Script: Comment deleted
else no sticky comment
Script-->>GitHub: Exit (under threshold)
end
else over threshold
Script->>Script: Render comment markdown with MARKER and metrics
Script->>Script: Build JSON payload
alt existing sticky found
Script->>GHAPI: PATCH issues/comments/{existing_id}
GHAPI-->>Script: Comment updated
else no sticky comment
Script->>GHAPI: POST issues/{PR_NUMBER}/comments
GHAPI-->>Script: Comment created
end
end
end
end
Script-->>GitHub: Job complete
Flow diagram for PR size check and sticky comment managementflowchart TD
A[Start size-check job] --> B{PR is draft?}
B -->|Yes| C[Exit workflow]
B -->|No| D{PR has size:override label?}
D -->|Yes| E[Log override and exit]
D -->|No| F[Compute loc = additions + deletions]
F --> G[Set files = changed_files]
G --> H[Fetch existing comments via GitHub API]
H --> I[Locate existing sticky comment by MARKER and author]
I --> J{loc > LOC_LIMIT or files > FILES_LIMIT?}
J -->|No| K{Existing sticky comment?}
K -->|Yes| L[Delete existing sticky comment]
K -->|No| M[Log under-threshold and exit]
L --> N[Exit]
J -->|Yes| O[Render sticky comment markdown with metrics]
O --> P[Build JSON payload]
P --> Q{Existing sticky comment?}
Q -->|Yes| R[PATCH existing comment]
Q -->|No| S[POST new comment]
R --> T[Exit]
S --> U[Exit]
File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
📝 WalkthroughWalkthroughThis PR adds a new GitHub Actions workflow that enforces a "soft cap" advisory on pull request size. The workflow monitors LOC changes and file count, posting sticky comments when thresholds are exceeded and cleaning them up when the PR returns below limits. A ChangesPR Size Advisory Workflow
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Possibly related issues
🚥 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. Comment |
|
[claim:review:Einstein:2026-05-10T17:18:28Z] |
Found one blocker, one nitBlocker — heredoc preserves 10-space indentation
Verified locally: Two consequences:
Fix is one line — make the heredoc tab-stripping ( sed 's/^ \{10\}//' > /tmp/comment.md <<EOF
${MARKER}
### PR-size soft cap
...
EOF— or just Nit —
|
|
[release:review:Einstein:2026-05-10T17:21:30Z] |
|
This PR is now behind Auto-rebase was removed because the bot has no signing key; rebasing as the bot strips author signatures and the |
|
[claim:review:godel:2026-05-10T21:44:52Z] |
Posts a sticky marker comment on PRs whose additions+deletions > 200 or changed_files > 3, suggesting a split. Quiet under both thresholds and self-heals (removes the comment if a flagged PR shrinks back below the line). `size:override` label opts out for legitimate large diffs (refactors, module removals, generated code). Addresses the conflict-probability axis of #602's merge-thrash diagnosis — bigger PRs collide with more open branches and produce the rebase loops observed on PR #591 (3 force-pushes / 9 label-flips in 30 min) and #540 (4 force-pushes / 8 label-flips in 9 min). The serialization axis (label-driven merge-train) ships separately.
c27ac86 to
8179bbb
Compare
|
Rebased onto current |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
.github/workflows/pr-size-soft-cap.yml (1)
12-12: ⚡ Quick winAdd
ready_for_reviewto trigger on draft→ready transitions.The workflow currently only runs on
opened,synchronize,reopened,labeled, andunlabeledevents. Addingready_for_reviewensures the workflow also executes when a PR transitions from draft to ready status.Suggested change
- types: [opened, synchronize, reopened, labeled, unlabeled] + types: [opened, synchronize, reopened, labeled, unlabeled, ready_for_review]🤖 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/pr-size-soft-cap.yml at line 12, The workflow's event types array (the line containing types: [opened, synchronize, reopened, labeled, unlabeled]) is missing the ready_for_review event; update that array to include ready_for_review so the job also triggers when a PR transitions from draft to ready (e.g., add ready_for_review to the list alongside the other event names).
🤖 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/pr-size-soft-cap.yml:
- Around line 51-67: The early exit when the "size:override" label is present
skips removing any prior sticky advisory comment; change the opt-out branch so
it still looks up and removes an existing sticky comment before exiting: keep
the label check for PR_LABELS, but if present run the same lookup that assigns
existing_id (using MARKER and the gh api query that filters github-actions[bot]
comments), and if existing_id is non-empty call gh api to delete
"repos/${REPO}/issues/${PR_NUMBER}/comments/${existing_id}" (or the equivalent
gh api delete command) and only then echo the opt-out message and exit;
reference the PR_LABELS check, existing_id variable, MARKER and the gh api
comments lookup/delete logic to implement this.
---
Nitpick comments:
In @.github/workflows/pr-size-soft-cap.yml:
- Line 12: The workflow's event types array (the line containing types: [opened,
synchronize, reopened, labeled, unlabeled]) is missing the ready_for_review
event; update that array to include ready_for_review so the job also triggers
when a PR transitions from draft to ready (e.g., add ready_for_review to the
list alongside the other event names).
🪄 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: af01e15a-5882-43b9-8ef5-24d4fb4851c2
⛔ Files ignored due to path filters (1)
CHANGELOG.mdis excluded by!**/CHANGELOG.md
📒 Files selected for processing (1)
.github/workflows/pr-size-soft-cap.yml
| # Opt-out via label. | ||
| if printf '%s' ",${PR_LABELS}," | grep -q ',size:override,'; then | ||
| echo "size:override label present; nothing to do." | ||
| exit 0 | ||
| fi | ||
|
|
||
| loc=$((PR_ADDITIONS + PR_DELETIONS)) | ||
| files="${PR_CHANGED_FILES}" | ||
| over=0 | ||
| if [ "$loc" -gt "$LOC_LIMIT" ]; then over=1; fi | ||
| if [ "$files" -gt "$FILES_LIMIT" ]; then over=1; fi | ||
|
|
||
| # Find any prior sticky comment authored by github-actions[bot]. | ||
| existing_id="$(gh api \ | ||
| "repos/${REPO}/issues/${PR_NUMBER}/comments" --paginate \ | ||
| --jq "[.[] | select(.user.login == \"github-actions[bot]\" and (.body | startswith(\"${MARKER}\")))] | .[0].id // empty")" | ||
|
|
There was a problem hiding this comment.
size:override exits before stale sticky cleanup.
At Line 52, the script exits before resolving/deleting any existing sticky comment, so previously posted advisories can remain visible after opt-out (and contradict the message at Line 92).
💡 Suggested fix
- # Opt-out via label.
- if printf '%s' ",${PR_LABELS}," | grep -q ',size:override,'; then
- echo "size:override label present; nothing to do."
- exit 0
- fi
-
loc=$((PR_ADDITIONS + PR_DELETIONS))
files="${PR_CHANGED_FILES}"
over=0
if [ "$loc" -gt "$LOC_LIMIT" ]; then over=1; fi
if [ "$files" -gt "$FILES_LIMIT" ]; then over=1; fi
# Find any prior sticky comment authored by github-actions[bot].
existing_id="$(gh api \
"repos/${REPO}/issues/${PR_NUMBER}/comments" --paginate \
--jq "[.[] | select(.user.login == \"github-actions[bot]\" and (.body | startswith(\"${MARKER}\")))] | .[0].id // empty")"
+
+ # Opt-out via label.
+ if printf '%s' ",${PR_LABELS}," | grep -q ',size:override,'; then
+ if [ -n "$existing_id" ]; then
+ echo "size:override label present; deleting sticky comment ${existing_id}."
+ gh api -X DELETE "repos/${REPO}/issues/comments/${existing_id}" >/dev/null
+ else
+ echo "size:override label present; nothing to do."
+ fi
+ exit 0
+ fi🤖 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/pr-size-soft-cap.yml around lines 51 - 67, The early exit
when the "size:override" label is present skips removing any prior sticky
advisory comment; change the opt-out branch so it still looks up and removes an
existing sticky comment before exiting: keep the label check for PR_LABELS, but
if present run the same lookup that assigns existing_id (using MARKER and the gh
api query that filters github-actions[bot] comments), and if existing_id is
non-empty call gh api to delete
"repos/${REPO}/issues/${PR_NUMBER}/comments/${existing_id}" (or the equivalent
gh api delete command) and only then echo the opt-out message and exit;
reference the PR_LABELS check, existing_id variable, MARKER and the gh api
comments lookup/delete logic to implement this.
|
[release:review:godel:2026-05-10T22:59:47Z] |
Closes part of #602 (the conflict-probability axis).
What lands
A new advisory GitHub Actions workflow that comments on oversize PRs without blocking them.
.github/workflows/pr-size-soft-cap.yml— runs on PRopened/synchronize/reopened/labeled/unlabeled. Skips drafts.loc = additions + deletionsandfiles = changed_filesfrom the PR event payload (no extra API calls for the metrics themselves).<!-- pr-size-soft-cap-v1 -->comment.size:overridelabel suppresses the comment entirely (legitimate large refactors, module removals, generated code).concurrency.cancel-in-progress: trueon a per-PR group so rapid pushes don't race the comment edit.Thresholds: 200 LOC, 3 files. Both editable in the workflow
env:block; living constants, not vendored.Why advisory not enforcing
The atomic-commits norm already pushes toward small units at the commit level. The merge-thrash data in #602 shows the PR-level aggregate is what determines blast radius — but a hard size block would prevent things like PR #540 (1,747-line module removal) from existing at all. Soft advisory + opt-out label keeps the door open for those while creating useful pressure on the 200–500-line "would-be-fine-as-two-PRs" cohort.
Verification
python3 -c "import yaml; yaml.safe_load(open('.github/workflows/pr-size-soft-cap.yml'))"→ loads cleanly.harden-runner@8d3c67de…v2.19.0).egress-policy: auditmatches the house style.pull-requests: write+contents: read.MARKERconstant in the workflow doubles as the comment-search key.gh api .../commentsfiltered togithub-actions[bot]author +body | startswith(MARKER)finds the existing comment for in-place PATCH or DELETE.Out of scope (follow-ups)
Discretion
Workflow YAML reviewed for any private terminology — clean. The CHANGELOG entry references #602 by number; nothing about session names or any private context. PR body, ditto.
Summary by Sourcery
Add an advisory GitHub Actions workflow that comments on oversized pull requests to encourage splitting them without blocking merges.
New Features:
CI:
Documentation:
Summary by CodeRabbit
Chores