Skip to content

feat(sandbox): official Kit sandbox image + GHCR workflow#78

Merged
ezynda3 merged 3 commits into
masterfrom
feat/sandbox-image
Jun 26, 2026
Merged

feat(sandbox): official Kit sandbox image + GHCR workflow#78
ezynda3 merged 3 commits into
masterfrom
feat/sandbox-image

Conversation

@ezynda3

@ezynda3 ezynda3 commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

What

Adds an official, pre-baked Linux image for running the Kit coding agent inside a workdir.dev sandbox, plus a CI workflow that builds it and publishes to GHCR.

Today the dev-sandbox integration installs the whole toolchain (apt-get, npm/go install, /etc/hosts patch, symlinks) on every sandbox boot. This image bakes all of that in once, so sandboxes created from it are ready immediately.

Contents

  • deploy/sandbox/Dockerfileubuntu:24.04 mirroring workdir's curated base apt layer, plus:
    • Go (/usr/local/go) and kit (go install github.com/mark3labs/kit/cmd/kit@<ver>, version ldflag injected)
    • the three git-forge CLIs: gh (GitHub), glab (GitLab), tea (Gitea)
    • git + openssh-client for SSH clones
    • the 127.0.0.1 localhost /etc/hosts entry Kit's OAuth listener needs
    • /workspace
    • It deliberately does not ship workdir's sandbox-guest-agent / sandbox-init — workdir's custom-image builder injects the static-musl guest agent + init when it converts this OCI image to an ext4 rootfs.
  • .github/workflows/sandbox-image.yml — buildx → GHCR (ghcr.io/mark3labs/kit-sandbox) on master pushes touching deploy/sandbox/**, on published releases (rebuilt against the released kit tag), and on workflow_dispatch. Tags: latest, sha-<short>, branch, vX.Y.Z/vX.Y.
  • deploy/sandbox/README.md — build, publish, and workdir POST /v1/images (source.type=oci) registration instructions.

Versions

Pinned, overridable via build args: go 1.26.4 (matches go.mod), gh 2.95.0, glab 1.105.0, tea 0.14.1.

How it's used

Once published, register the OCI image with workdir:

```bash
curl -X POST https://api.workdir.dev/v1/images
-H "Authorization: Bearer $WORKDIR_API_KEY"
-d '{"source":{"type":"oci","image_ref":"ghcr.io/mark3labs/kit-sandbox:latest"},"name":"custom/mark3labs/kit-sandbox"}'
```

then create sandboxes with {"image":"custom/mark3labs/kit-sandbox", ...}.

Testing

Built locally on linux/amd64; the final layer smoke-checks every CLI:

```
go version go1.26.4 linux/amd64
kit version v0.82.1
gh version 2.95.0
glab 1.105.0
Version: 0.14.1
```

Summary by CodeRabbit

  • New Features

    • Added a new sandbox container image for faster, prebuilt development environments.
    • The image now includes common tools like Go, GitHub/GitLab/Gitea CLIs, SSH utilities, and build essentials.
    • Added automated publishing of the sandbox image to a container registry on release, main-branch changes, or manual runs.
  • Documentation

    • Added setup and usage instructions for building, publishing, and using the sandbox image.

Pre-baked Linux image for running the Kit coding agent inside a workdir.dev
sandbox, so the dev-sandbox integration no longer installs the toolchain on
every boot.

- deploy/sandbox/Dockerfile: ubuntu:24.04 mirroring workdir's curated base apt
  layer, plus Go (go install github.com/mark3labs/kit/cmd/kit), the gh/glab/tea
  git-forge CLIs, git+openssh-client, the 127.0.0.1 localhost /etc/hosts entry
  Kit's OAuth listener needs, and /workspace. Deliberately omits workdir's
  guest-agent/init (the custom-image builder injects those).
- .github/workflows/sandbox-image.yml: buildx -> GHCR (ghcr.io/mark3labs/
  kit-sandbox) on master pushes touching deploy/sandbox/**, releases, and
  workflow_dispatch; tags latest/sha/semver.
- deploy/sandbox/README.md: build, publish, and workdir POST /v1/images
  (source.type=oci) registration instructions.

Versions pinned (overridable via build args): go 1.26.4, gh 2.95.0,
glab 1.105.0, tea 0.14.1. Builds verified locally on linux/amd64.
@mark-iii-labs-huly

Copy link
Copy Markdown

Connected to Huly®: KIT-79

@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@ezynda3, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 40 minutes and 45 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5c29b0ed-8ebe-46f9-8aec-2982a86c8d0c

📥 Commits

Reviewing files that changed from the base of the PR and between bc055b2 and 05c9413.

📒 Files selected for processing (3)
  • .github/workflows/sandbox-image.yml
  • deploy/sandbox/Dockerfile
  • deploy/sandbox/README.md
📝 Walkthrough

Walkthrough

This PR adds a sandbox image build-and-publish workflow, a Dockerfile for the image, and README instructions for building, publishing, and registering the image with workdir.

Changes

Sandbox image build, packaging, and docs

Layer / File(s) Summary
Workflow triggers and version selection
\.github/workflows/sandbox-image.yml
The workflow runs on sandbox file changes, release publication, or manual dispatch, serializes runs per ref, and resolves kit_version from the event context.
GHCR auth and image push
\.github/workflows/sandbox-image.yml
The job sets up Buildx, logs in to GHCR, generates image tags and labels, and builds and pushes deploy/sandbox/Dockerfile for linux/amd64 with KIT_VERSION and gha cache enabled.
Base image and toolchain
deploy/sandbox/Dockerfile
The Dockerfile starts from Ubuntu 24.04, installs sandbox utilities, downloads Go, builds kit, and installs gh, glab, and tea.
Runtime setup and validation
deploy/sandbox/Dockerfile
The image adds a localhost hosts entry, creates /workspace, checks go, kit, gh, glab, and tea during build, and defaults to /bin/bash.
Usage and registration docs
deploy/sandbox/README.md
The README describes the sandbox image, local build args, GHCR publishing triggers and tags, workdir image registration, and sandbox creation using image_version.

Sequence Diagram(s)

sequenceDiagram
  participant GitHubActions as GitHub Actions
  participant SandboxWorkflow as sandbox-image workflow
  participant BuildJob as build job
  participant LoginAction as docker/login-action
  participant MetadataAction as docker/metadata-action
  participant BuildPushAction as docker/build-push-action
  participant GHCR

  GitHubActions->>SandboxWorkflow: trigger on master push, release publication, or workflow_dispatch
  SandboxWorkflow->>BuildJob: start build job
  BuildJob->>BuildJob: resolve KIT_VERSION from release tag, input, or latest
  BuildJob->>LoginAction: log in with GITHUB_TOKEN
  LoginAction->>GHCR: authenticate registry session
  BuildJob->>MetadataAction: generate tags and labels
  MetadataAction-->>BuildJob: tags and labels
  BuildJob->>BuildPushAction: build deploy/sandbox/Dockerfile and push image
  BuildPushAction->>GHCR: publish tagged image
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 I hopped to GHCR with a Docker shell,
kit and its friends now build quite well.
In the sandbox burrow, warm and bright,
the image lands and boots up right.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding an official sandbox image and a GHCR publishing workflow.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/sandbox-image

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 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/sandbox-image.yml:
- Line 45: Pin the workflow’s action dependencies to immutable commit SHAs
instead of mutable version tags in the sandbox image publishing job. Update each
`uses` reference in the workflow, including `actions/checkout`,
`docker/setup-buildx-action`, `docker/login-action`, `docker/metadata-action`,
and `docker/build-push-action`, so they point to specific content SHAs and can’t
be retagged upstream.
- Around line 47-56: The “Resolve kit version” step is interpolating release and
input values directly inside the shell script, which can let untrusted content
reach the shell. Update the workflow step to pass github.event.release.tag_name
and inputs.kit_version through env variables instead of `${{ ... }}` in the
script, then in the run block read those env vars, validate the chosen version
string, and only then write it to GITHUB_OUTPUT.
- Around line 76-77: The sandbox image release tags generated by
docker/metadata-action are missing the required leading v prefix, so the current
semver patterns in the workflow produce 1.x.x tags instead of v1.x.x. Update the
tag generation entries in the sandbox-image workflow to preserve the contract,
either by using a v-prefixed pattern or by adding prefix=v for the semver tag
rules, and keep the existing release-tag behavior aligned with the documented
vX.Y.Z / vX.Y format.

In `@deploy/sandbox/Dockerfile`:
- Around line 58-61: The `kit` smoke check is being masked by `|| true`, so a
broken binary can still pass the image build; update the `RUN` step that
installs `kit` and invokes `kit --version` to fail the build on any non-zero
exit, and apply the same change to the other `kit` validation block referenced
in the review so both checks actually enforce runtime validity.
- Around line 47-81: The Dockerfile’s tool install steps for Go, gh, glab, and
tea download release artifacts and install them without verification. Add
integrity checks in the RUN blocks that fetch these assets, using the relevant
upstream checksum, signature, or digest verification flow before extracting or
copying them. Update the install sections for the Go bootstrap, gh, glab, and
tea steps so each artifact is validated before being placed on PATH.

In `@deploy/sandbox/README.md`:
- Around line 57-69: The OCI image registration example uses the mutable latest
tag, which makes the workdir definition non-reproducible. Update the example in
the README to use one of the immutable tags already produced by the workflow,
such as a semver tag or a sha-* tag, and keep the image_ref in the registration
snippet aligned with that stable tag.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6a282e89-aae3-43dc-ab1d-0bd4b075d8cc

📥 Commits

Reviewing files that changed from the base of the PR and between d99b76c and bc055b2.

📒 Files selected for processing (3)
  • .github/workflows/sandbox-image.yml
  • deploy/sandbox/Dockerfile
  • deploy/sandbox/README.md

Comment thread .github/workflows/sandbox-image.yml Outdated
Comment thread .github/workflows/sandbox-image.yml
Comment thread .github/workflows/sandbox-image.yml Outdated
Comment thread deploy/sandbox/Dockerfile Outdated
Comment thread deploy/sandbox/Dockerfile Outdated
Comment thread deploy/sandbox/README.md
- Pin all workflow actions to immutable commit SHAs + persist-credentials: false
  on checkout (prevents upstream retag / credential persistence on a job with
  packages: write).
- Resolve-kit-version step: move github context values into env: and validate
  the version before writing GITHUB_OUTPUT (avoids template-injection into a
  shell step with publish credentials).
- metadata-action: add prefix=v to the semver tag patterns so release image
  tags are vX.Y.Z / vX.Y as documented (the action strips the v otherwise).
- Dockerfile: verify Go, gh, glab, tea downloads against pinned SHA256
  checksums; pin the image to linux/amd64 (checksums are arch-specific and
  workdir runs x86_64 Firecracker).
- Dockerfile: drop '|| true' on the kit smoke checks so a broken kit binary
  fails the build instead of publishing green.

Rebuilt locally: all checksums verify OK, kit version injects, smoke check passes.
@ezynda3

ezynda3 commented Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai all five findings addressed in e0ce63b:

  1. Unpinned actions (workflow:45) — every uses is now pinned to an immutable commit SHA (# vN comment kept for readability), and actions/checkout sets persist-credentials: false.
  2. Template injection (workflow:56)github.event.release.tag_name and inputs.kit_version moved into env:; the resolved version is validated (rejects newlines/whitespace/shell metacharacters) before being written to GITHUB_OUTPUT.
  3. Release tag format (workflow:77) — added prefix=v to both type=semver patterns so published tags are vX.Y.Z / vX.Y, matching the README.
  4. Unverified downloads (Dockerfile:81) — Go, gh, glab, and tea are now verified against pinned *_SHA256 build args via sha256sum -c. The image is pinned to linux/amd64 (checksums are arch-specific; workdir runs x86_64 Firecracker).
  5. Masked smoke check (Dockerfile:61) — removed || true from both kit --version checks so a broken kit binary fails the build.

Verified locally: all four checksums report OK, kit version v0.82.1 injects correctly, the strict smoke check passes, and actionlint is clean.

@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

@ezynda3 Thanks for the thorough follow-up — those updates address the concerns I raised, and the local verification notes are helpful too.


If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

Use ghcr.io/mark3labs/kit-sandbox:v0.82.1 (an immutable release tag) instead of
:latest in the POST /v1/images example, with a note to prefer vX.Y.Z or
sha-<short> over latest, so the workdir image definition is reproducible.
@ezynda3

ezynda3 commented Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai addressed the README reproducibility finding in 05c9413 — the POST /v1/images example now pins an immutable tag (ghcr.io/mark3labs/kit-sandbox:v0.82.1) instead of :latest, with a note to prefer a vX.Y.Z or sha-<short> tag for a reproducible workdir image definition.

@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

@ezynda3 Thanks — that resolves the reproducibility concern. Pinning the README example to an immutable image tag and calling out vX.Y.Z/sha-<short> as the preferred options makes the workdir image definition much safer and more repeatable.

@ezynda3 ezynda3 merged commit 81e8ce3 into master Jun 26, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant