Repository navigation
ci: read CLA policy snapshots through git to spare the GITHUB_TOKEN budget - #16225
lawrencecchen wants to merge 1 commit into
Conversation
The CLA policy guard runs on every pull_request_target event, including review-bot description edits (494 runs from 12:00 to 13:00 PDT on 2026-09-30), and fetched twelve policy files per run through the REST contents API: 14 GITHUB_TOKEN requests a run, the largest share of the repository's shared budget once ci-fail-fast.yml was gone. Fetch each revision's tree into a blob-less bare repository and its policy blobs by object id instead. Git transfers are not charged to that budget, and the bytes are identical (checked for base, fork head and test-merge revisions). A run now makes 2 REST requests. When the budget is spent anyway, wait for the reset GET /rate_limit reports (it is not charged) if it is at most five minutes away, and otherwise fail with the reset time instead of a bare 403. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Bugbot is paused — on-demand spend limit reachedBugbot uses usage-based billing for this team and has hit its on-demand spend limit. A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue. |
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 28 minutes. View limit detailsLimit details: You’ve used all 10 included reviews currently available. Review configuration: ⚙️ Run configurationConfiguration used: Repository: manaflow-ai/cmux/.coderabbit.yaml Review profile: ASSERTIVE Plan: Advanced Run ID: 📒 Files selected for processing (1)
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 |
|
All contributors have signed the CLA ✍️ ✅ |
|
Independent confirmation of the problem, plus one finding on the fix. Confirming the impact from the other side. I hit this while attributing 151 of 288 runs failed in those forty minutes, across 51 distinct head branches. Finding: the new rate-limit diagnostic cannot reach the annotation. fail!("the repository's GITHUB_TOKEN rate limit is exhausted until #{reset_at}; re-run this check after that (#{endpoint})")but the script ends with rescue PolicyError
warn "::error::CLA policy validation rejected the proposed policy"So after the single wait-and-retry, a still-exhausted budget is annotated as a The classification you want already exists one line below: rescue StandardError
warn "::error::CLA policy validation could not complete"Suggested fix, small and contained: add an error class for infrastructure class InfrastructureError < StandardError; end
def infra_fail!(message)
raise InfrastructureError, message
endthen Not a blocker on the approach, which I think is right. |
Summary
CLA policy guard runs on every
pull_request_targetevent, includingedited. Between 12:00 and 13:00 PDT on 2026-09-30 it ran 494 times for 264 head SHAs. 175 of those runs came from review bots editing PR descriptions (cubic-dev-ai 134, coderabbitai 29, blacksmith 12). Each run fetched twelve policy files through the REST contents API, for 14 GITHUB_TOKEN requests a run. That is about 6,900 requests an hour, out of a 15,000-an-hour budget that every workflow in the repository shares. Afterci-fail-fast.ymlwas removed (#16160), this guard was the largest remaining consumer. When the budget ran out, the guard failed on every PR with a bare 403.fetch_snapshotnow reads each revision through git. It fetches the commit's trees into a blob-less bare repository, with--depth=1 --filter=blob:noneand one promisor remote per repository. It then fetches only the policy blobs, by object id. Git transfers are not charged to the REST budget. Objects are addressed by SHA, so the bytes are the ones the contents API returned. I checked this for a main base, a fork head (#16198 from wanjinhao1/cmux) and a test-merge commit. The public repositories are fetched anonymously, and no credential is written. A missing path is stillnil. A directory or symlink is still "not a regular file". The size limit is checked before the blob is read. One difference: a revision that cannot be fetched now fails the check. Before, every file silently read as missing.If the budget is exhausted anyway,
api_jsonasksGET /rate_limitfor the reset time (that endpoint is not charged). If the reset is at most five minutes away, it waits and retries once. Otherwise it fails with the reset time rather than a bare 403.This changes the guard script, so the guard running from main requires a trusted reviewer's approval of this exact head (@austinywang or @azooz2003-bit). The check stays red until one of them approves.
EXPECTED_GUARD_SCRIPT_DIGESTis updated to the new self-digest.Companion: #16224 cuts the merge-group watcher's polling.
Testing
ghshim against live PRs (fix: recover interrupted Cloud vm run creates #16221, same-repo; Fix #16193: refuse case-only duplicate label names in the labels manifest #16198, fork): 14 before, 2 after (repos/{repo}andpulls/{n}). Wall time is about 4 s. The full validator, with all its regression matrices, passes on Ruby 2.6 and 4.0.fetch_snapshotand the new git one gave identical results for the 7 policy paths, including missing paths, at 4 revisions.ghwhose first call returns "API rate limit exceeded", the validator waits for the reported reset and then succeeds. With the wait cap set to 0, it fails with "exhausted until HH:MM UTC".Changelog
none
🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.Summary by cubic
Reduces the CLA policy guard's GITHUB_TOKEN usage by reading policy snapshots through git instead of the REST contents API, dropping a run from 14 to 2 REST requests.
Written for commit fdcf940. Summary will update on new commits.