Repository navigation
ci: prune expired R2 cache archives, never one a latest pointer names - #14089
Conversation
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. Note Currently processing new changes in this PR. This may take a few minutes, please wait... ⚙️ Run configurationConfiguration used: Repository: manaflow-ai/cmux/.coderabbit.yaml Review profile: ASSERTIVE Plan: Advanced Run ID: 📒 Files selected for processing (7)
✨ Finishing Touches📝 Generate docstrings
🧪 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 |
|
All contributors have signed the CLA ✍️ ✅ |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Merged current main (c172961). The conflict in tests/test-execution.toml was a positional collision, and both entries are kept. Main now keeps the R2 write credentials in the — Lemur g1 🖇️ |
2d758e7 to
82c1c22
Compare
|
Rebased onto |
|
Correction to my comment above: at 06:56Z another push rebased this branch to 82c1c22, which replaced c172961 and 2d758e7. I have not pushed over it. The current head still lacks the writer environment, so The fix is one line on the environment: ${{ github.ref == 'refs/heads/main' && 'ci-cache-writer' || '' }}Without it, main's run of the job would also get empty R2 credentials, because they live in that environment now. — Lemur g1 🖇️ |
The guard from #14147 requires every job holding the R2 write credentials to declare it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both families try the pull request's exact base first, then the newest by prefix. On 2026-09-24, 92 of the 100 most recently updated open pull requests had a base under a day old, and each day of retention costs about 35 GiB. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
scripts/ci/r2-cache.shsaves archives to the CI cache bucket and nothing ever deletes them. On 2026-09-24 the bucket held 143.4 GiB after about five days of the R2 backend, and 141.4 GiB of that was 138xcode-compilation-*archives, so it grows by roughly 35 GiB a day. Per-commit DerivedData snapshots (#14081) would add about 2 GiB per build-changing main commit.r2-cache-prune.ymlruns daily on main and deletesv1/*/objects/archives older than their family's retention. It never deletes an archive that anylatest/pointer names, whatever its age, because prefix restores read those. It re-reads every pointer immediately before deleting, becauser2-cache.shre-pointslatest/at an existing key without re-uploading it. Retention is chosen by key prefix:admission-derived-data-xcode-compilation-Package.resolved, toolchain), so an old key stays exact for a PR on an older baseIt is a dry run by default. Deletes need a dispatch with
deletechecked, or the repository variableCI_R2_CACHE_PRUNE_DELETE=1. An incomplete listing or an unreadable pointer deletes nothing, pointers and keys outsidev1/*/objects/are never candidates, and one run deletes at most 2,000 archives, oldest first. Listing and signing reuser2_cache_census.py.Why one day: on 2026-09-24, 92 of the 100 most recently updated open pull requests had a base under a day old, and each extra day of retention holds about 35 GiB.
Dry run against the real bucket
Run from a throwaway branch with the same credentials, with no
--deletepath: 35943338712, then with the census modelling other windows.xcode-compilation-Nothing is eligible yet, because no archive is older than five days. For the same bucket, the census reports that an age rule over all archives would reclaim 22.5 GiB at 3 days, 64.6 GiB at 2 days and 106.4 GiB at 1 day.
Validation
tests/test_r2_cache_prune.py, 8 tests, fake bucket: per-family retention; pointer targets kept in both archive formats; a pointer moved mid-run protects its new target; an incomplete listing and a bad pointer delete nothing; the per-run bound; the workflow runs only on main, on Linux, withpermissions: {}at the top level and deletes only on opt-in.ci-guards.ymlcommand sweep passes locally, except two failures that also fail on a cleanorigin/mainexport (a missingvendor/bonsplitsubmodule, and a bun test path that expects itsworking-directory). actionlint is clean.To enable deletes after reviewing a scheduled dry run:
gh variable set CI_R2_CACHE_PRUNE_DELETE --repo manaflow-ai/cmux --body 1.— Marmot g1 🎒
Run: run_cmux_ci_incremental_deriveddata_for_compile_admission_20260924_0d1859dd
🤖 Generated with Claude Code
Summary by cubic
Prunes the CI R2 cache bucket, which grows about 35 GiB a day and was never cleaned. Adds
r2_cache_prune.pyand a daily workflow on main that deletesv1/*/objects/archives older than their family's retention.Migration
admission-derived-data-andxcode-compilation-archives, 30 days for everything else.latest/pointer are always kept; pointers are re-read right before deleting because a save can publish a new prefix's first pointer between listing and delete.deletechecked or setting repository variableCI_R2_CACHE_PRUNE_DELETE=1.ci-cache-writerenvironment, and uses the Ubuntu runner outsidemanaflow-ai.Written for commit 7180091. Summary will update on new commits.
Summary by CodeRabbit