# GitHub CI

GitHub Actions can run `s0` non-interactively for common Sandbox0 automation flows such as image build/push, template updates, and sandbox orchestration.

This page covers the recommended integration shape:

- use the official `setup-s0` GitHub Action or the official reusable workflow
- authenticate with a Sandbox0 API key through GitHub Secrets
- build images with Docker on the runner
- push team-scoped images with short-lived registry credentials issued by Sandbox0

## Required secrets

Store the following in GitHub repository, organization, or environment secrets:

| Secret | Purpose |
|------|-------------|
| `SANDBOX0_BASE_URL` | Optional Sandbox0 API entrypoint override. Sandbox0 Cloud defaults to `https://api.sandbox0.ai`; most workflows can omit it. |
| `SANDBOX0_TOKEN` | Sandbox0 service API key used by the workflow |

For Sandbox0 SaaS, `s0` defaults to `https://api.sandbox0.ai`, so most workflows only need `SANDBOX0_TOKEN`.

For image build and push workflows, create a dedicated service API key with the smallest role that satisfies the workflow.

For registry push only, prefer the `builder` role. It is intended for CI automation that needs Sandbox0 registry access without broader sandbox write permissions.

## Runner requirements

Sandbox0 does not build container images remotely.

`s0 template image build` uses the local Docker daemon on the GitHub Actions runner, and `s0 template image push` uses Docker again after fetching short-lived registry credentials from Sandbox0.

That means your workflow should run on a runner with Docker available. GitHub-hosted Ubuntu runners are the easiest default.

## Official reusable workflow

The official reusable workflow handles image build and push:

```yaml
name: sandbox0-image

on:
    workflow_dispatch:
    push:
        branches: [main]

jobs:
    build-and-push:
        uses: sandbox0-ai/s0/.github/workflows/template-image.yml@v0.10.3
        with:
            image-tag: my-app:${{ github.sha }}
            context: .
            dockerfile: Dockerfile
            s0-version: v0.10.3
        secrets:
            sandbox0_token: ${{ secrets.SANDBOX0_TOKEN }}
```

To explicitly override the API endpoint, pass `api-url: ${{ vars.SANDBOX0_BASE_URL }}`.

The reusable workflow installs `s0`, verifies Docker, builds the image locally
on the runner, and pushes it with short-lived Sandbox0 registry credentials.
In the reviewed `v0.10.3` workflow, its `template-image` output reconstructs a
path from `PullRegistry` and the requested tag. That output is incorrect for
providers that return a rewritten complete `PullImage`, including the Aliyun
mapping. For those providers, use the setup-action flow below and consume the
CLI's printed complete reference.

## Official setup action

Use the setup action for custom logic and provider-correct image outputs:

```yaml
name: sandbox0-image

on:
    workflow_dispatch:
    push:
        branches: [main]

jobs:
    build-and-push:
        runs-on: ubuntu-latest
        outputs:
            template-image: ${{ steps.push.outputs.template_image }}
        steps:
            - uses: actions/checkout@v6

            - uses: sandbox0-ai/s0/.github/actions/setup-s0@v0.10.3
              with:
                  version: v0.10.3
                  token: ${{ secrets.SANDBOX0_TOKEN }}

            - name: Build image
              run: s0 template image build . -t my-app:${GITHUB_SHA}

            - name: Push image to Sandbox0 registry
              id: push
              shell: bash
              run: |
                  set -euo pipefail
                  s0 template image push "my-app:${GITHUB_SHA}" -t "my-app:${GITHUB_SHA}" \
                      | tee "${RUNNER_TEMP}/sandbox0-image-push.log"
                  image="$(sed -n 's/^Template image reference: //p' "${RUNNER_TEMP}/sandbox0-image-push.log" | tail -n 1)"
                  test -n "$image"
                  echo "template_image=$image" >> "$GITHUB_OUTPUT"
```

These examples pin a reviewed release. The action/workflow ref and the installed
CLI version are separate: use action `version` or reusable-workflow `s0-version`
to pin the binary as well. The reusable workflow still fetches its installer
from `main`; pinning that wrapper alone does not pin every downloaded script.

The push step obtains temporary registry credentials from Sandbox0 automatically. You do not need to manage a long-lived `docker login` secret for the Sandbox0 registry.

## Recommended setup

1. Create a dedicated Sandbox0 service API key for GitHub Actions.
2. Grant the key the narrowest role the workflow needs. For registry push only, prefer `builder`.
3. Add `SANDBOX0_TOKEN` to GitHub repository or environment secrets.
4. Add `SANDBOX0_BASE_URL` only if you need an explicit API endpoint override.
5. Pin the action or reusable workflow to a published `s0` release tag.
6. Use the CLI's complete `Template image reference`, then resolve its manifest digest for your template definition.

## How image push works

`s0 template image push` performs these steps:

1. Authenticates to Sandbox0 with `SANDBOX0_TOKEN`
2. Calls the registry credentials endpoint for a short-lived push credential
3. Tags the local image with the complete team-scoped `pushImage` reference returned by Sandbox0
4. Pushes the image with Docker
5. Prints the provider-specific `pullImage` reference that Sandbox0 should use at runtime

This keeps registry credentials short-lived while leaving the build itself on the CI runner.

## Using the pushed image in a template

After a successful push, treat the printed `Template image reference` repository and pull hostname as authoritative. Resolve the pushed manifest digest with Docker or another registry client, then replace the tag with the registry-reported `@sha256:<digest>`. Providers such as Aliyun ACR may use a VPC-only runtime hostname, so do not reconstruct the pull path from the push path.

```yaml
spec:
    mainContainer:
        image: registry.example.com/t-<team-key>/my-app@sha256:<64-hex-digest>
        resources:
            memory: 8Gi
```

Render the actual pull reference and digest into the file before submitting it;
`s0 template create/update --spec-file` does not expand shell variables in YAML.
Build for the Linux platform required by your region (`platform` in the reusable
workflow or `--platform` in the CLI). Template creation or update does not wait
for durable image import to become ready; see [Custom Images](/docs/sandbox/template/images).

If your workflow also creates or updates templates, it needs an `admin` key;
`builder` and `developer` can read templates but cannot write them.

## Security guidance

- Prefer a dedicated service API key for GitHub Actions rather than a human access token.
- Prefer GitHub environment secrets when deployments should require approvals or branch restrictions.
- Use the narrowest Sandbox0 role that can complete the workflow.
- Rotate service API keys on a schedule that matches your organization policy.

---

## Next Steps

<CardGroup>
  <Card title="Deployment Options" href="/docs/sandbox/deployment" cta="Continue">
    Check Sandbox0 Cloud availability and the planned BYOC option.
  </Card>

  <Card title="Get Started" href="/docs/sandbox/get-started" cta="Continue">
    Connect your application to Sandbox0 Cloud.
  </Card>
</CardGroup>
