Repository navigation
feat(cli): build a remote sandbox base image from a Dockerfile and save it by digest - #750
Merged
ItamarZand88 merged 26 commits intoSep 26, 2026
Conversation
`alien projects capabilities enable remote-sandbox --src <dir>` builds the Dockerfile in <dir> as the sandbox base image, pushes it to the project's private repository through the manager, and configures the capability with the pushed reference. A rerun with an unchanged build context reuses the earlier push through the release push cache, so the reference does not change.
…rror Adds SandboxImagePushFailed so the registry cause is the headline, resolves the manager before creating the project repository, marks the two pushed-reference invariants as GenericError, and drops Platform clones.
…sh cache atomically A missing --src directory is a validation error, not a retryable file failure. The push cache is written through a temp file and renamed, so an interrupted write cannot empty it and force a re-push under a new tag.
A retried create answers "already exists" to its own first attempt, and every HTTP error is retryable in the shared client, so an existing repository cost three backoff retries before it was reported as a conflict. CreateRepository now goes out once through sign_send_json_once and callers decide whether to retry.
create_repository always creates the prefixed name, so describing the logical name first cost a failed request on every lookup. The logical name stays as the fallback.
…re-pulls bases BuildSettings.rebuild builds every source resource again: the local artifact cache is not consulted and Docker builds pass --pull, so a change that only exists upstream in a FROM image is picked up. Off for every existing caller.
docker_source_input_hash covers the files under src by relative path, the Dockerfile, build args, stage and target platforms, and not the absolute path, so two checkouts of the same tree agree on it. registry::manifest_digest reads a tag's digest and reports a missing manifest as absent; registry::tag_manifest points a second tag at a pushed manifest by copying its bytes, so an image index keeps its digest.
…y digest `alien projects capabilities enable remote-sandbox --src` now hashes the build inputs and looks for remote-sandbox-src-<hash> in the project repository first. A hit skips the build and push, from any machine; a miss builds, pushes, and tags the pushed manifest with that name. The capability is configured with the manifest digest. --rebuild skips that lookup and the local artifact cache and re-pulls FROM images. --image replaces --base-image, which still parses as a hidden alias. A missing Dockerfile is refused before any request. The repository is now ensured before the build, since the lookup needs it.
…misses A pull role scoped to the repository prefix answers 403 for the logical name, which hid the in-scope 404. Also state why CreateRepository is sent once.
…or out A refused lookup or tag is IMAGE_LOOKUP_REJECTED / IMAGE_PUSH_REJECTED (not retryable); a transport error, 5xx or 429 stays retryable. The OCI error is never attached, as registry errors can carry signed URLs.
The source tag is shared by every machine with the same tree, so the input hash is recomputed after the build and a mismatch fails the run. The sandbox push skips the release push cache, so --rebuild always pushes and a cached reference the registry dropped cannot break the tag step. A failed push-cache save is logged as a warning.
…e local cache The artifact is cached under the pre-edit tree's key, so reverting the edit would have reused it and tagged it as that tree.
…sable A token endpoint failure reads as a failed token request, not a refused credential.
…tifact cache The cache key is taken before the build reads the tree. It is taken again before the cache entry is written, and on a mismatch the artifact is left uncached, so an interrupted run or a reverted edit cannot reuse it. This covers alien release as well; the sandbox CLI keeps only its own check before tagging.
…ache key A Dockerfile outside the source directory, or under a directory the source walk skips, was keyed by path only, so an edit to it reused the old artifact. A missing Dockerfile is left to the build to report. A mid-build re-key that fails counts as a change: the artifact stays uncached rather than failing a finished build.
…a failed read The wrapper covers lookup, push and tag, so it is SANDBOX_IMAGE_PUBLISH_FAILED. IMAGE_LOOKUP_REJECTED no longer claims a refusal for an unusable manifest. An empty ECR repository id looks up the shared repository, as create does.
A re-key that fails is logged with its error rather than as a source change.
…WS one The remote sandbox configure endpoint rebuilds the whole configuration from the request, so an omitted `azure` key turns Azure off. `alien projects capabilities enable remote-sandbox` always omitted it, which deleted a project's saved Azure sandbox whenever the AWS base image was set with --image or --src. Read the project's saved Azure settings right before the configure call and send them with the new base image. A project with no Azure sandbox still omits the key.
Contributor
Author
|
@greptile review |
|
…image The source input hash reused the artifact cache's file walk, which skips node_modules, target, .git and symlinks. Docker sends all of them unless .dockerignore says otherwise, so an edit there left the hash unchanged and reused a stale image. The hash now walks the context with Docker's .dockerignore rules (the Dockerfile-specific ignore file first), and covers file contents, the executable bit, symlink targets and directories. It skips the build's own output directory when that sits inside the source, since the build writes there between the hashes taken before and after it.
…ith its hash On a registry hit the command configured the tagged digest using the hash taken before the lookup, so a tree edited in between got the older image. Both paths now rehash before they use the tag and fail the same way when the source moved.
Two releases in one directory shared push-cache.json.tmp, so one could rename the other's file away and fail its write. Each write now goes through a uniquely named temp file in the cache directory.
Contributor
Author
|
@greptile review |
… across generated types
Contributor
Author
|
@greptile review |
ItamarZand88
deleted the
itamar/alien-1034-give-the-sandbox-capability-a-private-image-without-typing
branch
September 26, 2026 20:19
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.
Summary
alien projects capabilities enable remote-sandbox --src ./sandboxbuilds the sandbox base image from a Dockerfile, pushes it to the project's private repository and saves it by digest, so a private image no longer needs a hand-rundocker login/tag/push. Re-running with an unchanged directory, on any machine, reuses the image and changes nothing.When a developer runs the command with
--src:remote-sandbox-src-<hash>in the project's repository.<registry>/<repository>@sha256:…as the capability's base image.This PR changes a private sandbox image from four manual Docker commands to one CLI command.
What I did
--image(was--base-image, kept as a hidden alias) for a prebuilt image;--srcwith optional--dockerfileto build;--rebuildto build again even when the directory is unchanged, re-pullingFROM.release.rsso release and this command share them.CreateRepositoryis now sent once. It was retried on the 400 "already exists" answer for ~7s before being treated as success, which made a repeat request time out. Repository lookups try the routable name first.alien release.How I tested
FROM alpine:3.20:Unchanged …:remote-sandbox-src-<hash>in 3s, same digest, nothing pushed;--rebuild: new build with--pull;--base-imagealias with a public image still configures;--srcand--image.alien release; no new credential is created or stored.configure_refuses_an_image_outside_the_pushed_repository).