Repository navigation
ci: share the slow tier's computer images through a mirror registry rather than per-shard caches - #580
Open
andrewpark-scaleai wants to merge 4 commits into
Open
ci: share the slow tier's computer images through a mirror registry rather than per-shard caches#580andrewpark-scaleai wants to merge 4 commits into
andrewpark-scaleai wants to merge 4 commits into
Conversation
andrewpark-scaleai
force-pushed
the
andrew-park/ci-shared-computer-images
branch
from
November 10, 2026 00:19
3f301be to
d2329d8
Compare
andrewpark-scaleai
force-pushed
the
andrew-park/ci-shared-computer-images
branch
from
November 10, 2026 00:50
d2329d8 to
2c89b45
Compare
This was referenced Nov 10, 2026
…ather than per-shard caches The slow tier saved each runner's whole registry to the Actions cache, keyed by shard and week. The same image landed on up to three shards, so the entries (1.6 to 6.3GB each) overflowed the repository's 10GB, evicted each other, and most shards built every image from scratch. - The composer copies an image of a key the env's image store lacks from AGENT_ENV_COMPUTER_IMAGE_MIRROR, read anonymously, before it would build it; a mirror it can't read leaves the image to be built. - registry_api.copy_image copies an image between registries by its digest, sending only the blobs the target lacks and each manifest byte for byte. - After its tests pass on main, each slow shard shares the images it built or copied to ghcr.io/scaleapi/agentenv-ci-computers under their keys and <key>-seen-<date>. - computer-image-mirror.yml deletes, daily, the versions no run has used for 7 days, keeping a kept index's platform manifests. - The test packages folder keeps its own per-shard weekly cache, saved only on main and named by its locks. prune_registry.py, which trimmed the registry cache, goes with that cache. Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
…fore its credentials go Co-Authored-By: Claude <noreply@anthropic.com>
andrewpark-scaleai
force-pushed
the
andrew-park/ci-shared-computer-images
branch
from
November 10, 2026 23:09
5d957be to
c7f3ced
Compare
andrewpark-scaleai
enabled auto-merge (squash)
November 11, 2026 01:01
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The goal is a shorter Local backends run on the same 12 slow-tier runners. The run finishes when the slowest slow shard does, and that shard is usually rebuilding computer images another shard already built.
computers-<shard>-<week>-<tags>.What changes
The composer copies an image it would build from a mirror.
_storedlooks for a key's image in the env's image store, as before.AGENT_ENV_COMPUTER_IMAGE_MIRRORis set and the store lacks the image, the composer reads the image anonymously from the mirror and copies it into the store. It then reuses the image as if it had been built earlier.<composer digest>-<key>. The composer digest iscomposition(), which already covers the composer, the builder, the computers' build files and the protocol's computer package. So a change to the code that builds images misses the mirror and builds them again, and the build path stays tested.registry_api.copy_imagecopies an image between registries by its digest.Content-Length. They are never held in memory.The slow tier shares images through
ghcr.io/scaleapi/agentenv-ci-computers.<tag>-seen-<YYYYMMDD>.share_computer_images.pydoes this asGITHUB_TOKEN. An image already in the mirror is only tagged again. If anonymous reads fail, it warns that the package needs to be public.actions/cacherestore, the "keep only the computer images" step, and the save of the registry are gone.prune_registry.pyand its test, which only trimmed the registry cache, are removed.A daily prune deletes images unused for a week.
computer-image-mirror.ymlrunsprune_computer_images.pydaily at 06:17 UTC, or on demand with a dry run.seen-tag, or its upload date when it has none, falls within 7 days. It also keeps the platform manifests a kept index lists, because GHCR lists those as versions of their own. Every other version is deleted.Before merge
agentenv-ci-computers, and it's already readable without credentials.GITHUB_TOKEN, which needs the repository to hold admin access to the package. A package admin has been asked to grant it.Measured on this PR
Run 42716509774 was measured twice. Attempt 1 started with an empty mirror and built everything. Attempt 2 found every image in the mirror.
Main's slowest slow shard has a median of 940s over its last 46 runs (800s to 1198s). Those runs mixed cache hits and misses from shard to shard. With the mirror, every shard reuses every image whose sources are unchanged, so a run stops depending on which cache entries survived. Shard 8 is still the slowest at 865s of pytest, against the 596s the durations table plans for it. Refreshing the table from a run with every image in the mirror is the next step.
Verification
copy_imagesends only missing blobs and keeps each manifest's bytes.copy_imageresend blobs the target has;copy_imagecopied the published 2-platformagentenv-db-webindex from GHCR into a localregistry:2with the same digest, in 10.6s. A second copy, with the blobs already there, took 0.6s.share_computer_images.pybetween two local registries pushed the key and itsseen-tag, and skippedindex-*tags.

Confidence Score: 5/5
The PR appears safe to merge, with no new blocking issues found.Summary
The slow test runners now share computer images through GHCR instead of caching each runner’s registry.
Diagram
%%{init: {'theme': 'neutral'}}%% flowchart TD A[Composer needs an image] --> B{Local store has it?} B -->|Yes| F[Reuse and probe] B -->|No| C{Mirror provides it?} C -->|Yes| D[Copy into local store] D --> F C -->|No or copy fails| E[Build image] E --> F F --> G{Main tests pass?} G -->|Yes| H[Share image and add dated tag] H --> I[GHCR mirror] J[Daily prune] --> K[Keep recent images and their platform manifests] K --> IReviews (9) · Last reviewed commit: "fix(registry): refuse an upload a regist..." · Reviewed by Greptile