sha256:2aa2a7cebf9b7b2d74f059bc1486f9a7a6ce06718e89f0d77b2dd0c029be404b
Last pushed
9 days by cdupuis
Type
Sandbox Kit
Manifest digest
sha256:2aa2a7cebf9b7b2d74f059bc1486f9a7a6ce06718e89f0d77b2dd0c029be404b
schemaVersion: "3"
displayName: GitHub Clone
description: Clones a GitHub repository into the sandbox at create time, using the gh CLI with a proxy-managed GH_TOKEN sentinel. Auto-installs gh if the base image doesn't have it.
version: 1.0.0
kind: mixin
capabilities:
- type: com.docker.sandbox/network-policy@1
config:
install:
allow:
- api.github.com
- github.com
- codeload.github.com
- raw.githubusercontent.com
- cli.github.com
- archive.ubuntu.com
- security.ubuntu.com
- ports.ubuntu.com
- download.docker.com
runtime:
allow:
- api.github.com
- github.com
- codeload.github.com
- raw.githubusercontent.com
- type: com.docker.sandbox/lifecycle@1
config:
install:
- command: |
set -euo pipefail
NEED=""
command -v gh >/dev/null 2>&1 || NEED="$NEED gh"
command -v git >/dev/null 2>&1 || NEED="$NEED git"
if [ -z "$NEED" ]; then
exit 0
fi
if ! command -v apt-get >/dev/null 2>&1; then
echo "github-clone: missing:$NEED and apt-get is not available — this kit only knows how to auto-install on Debian/Ubuntu bases. Layer a mixin that installs the missing tools, or pick a base agent that ships them." >&2
exit 1
fi
export DEBIAN_FRONTEND=noninteractive
# Add GitHub's official apt source only when gh is what's missing.
# Recipe follows https://github.com/cli/cli/blob/trunk/docs/install_linux.md.
case " $NEED " in
*' gh '*)
install -m 0755 -d /etc/apt/keyrings
if command -v curl >/dev/null 2>&1; then
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \
-o /etc/apt/keyrings/githubcli-archive-keyring.gpg
elif command -v wget >/dev/null 2>&1; then
wget -qO /etc/apt/keyrings/githubcli-archive-keyring.gpg \
https://cli.github.com/packages/githubcli-archive-keyring.gpg
else
# Fall back to installing curl first via apt so we can fetch
# the keyring; the base at least has ca-certificates for the
# https handshake (every *-docker base does).
apt-get update -qq
apt-get install -y -qq --no-install-recommends curl ca-certificates
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \
-o /etc/apt/keyrings/githubcli-archive-keyring.gpg
fi
chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" \
> /etc/apt/sources.list.d/github-cli.list
;;
esac
apt-get update -qq
# `$NEED` is intentionally unquoted — it's a space-separated list
# of package names constructed from the two `command -v` checks
# above, not user input.
apt-get install -y -qq --no-install-recommends $NEED
rm -rf /var/lib/apt/lists/*
description: Install gh (and git) via apt if the base image doesn't already ship them
user: "0"
- command: |
set -euo pipefail
REPO='${{ kit.args.repo }}'
REF='${{ kit.args.ref }}'
DIR='${{ kit.args.dir }}'
# Idempotent re-run: if the target already has content, leave it
# alone rather than fail or clobber user changes.
if [ -d "$DIR" ] && [ -n "$(ls -A "$DIR" 2>/dev/null || true)" ]; then
echo "github-clone: '$DIR' already exists and is non-empty; skipping clone." >&2
exit 0
fi
mkdir -p "$(dirname "$DIR")"
# The whole clone runs as root — the agent user (uid 1000) can't
# create a top-level directory like /project because / is
# root-owned 755. `chown -R agent:agent` at the end hands the
# resulting tree over. This matches the pattern every other kit
# in this repo uses (e.g. github-ssh, claude-sbx-statusline).
#
# gh reads GH_TOKEN itself, so no extra plumbing is needed for
# the clone. Extra flags after `--` are passed straight to
# `git clone`.
if [ -n "$REF" ]; then
# Fast path: shallow-clone a branch or tag directly. Fallback:
# if REF is a commit SHA (not a branch/tag), --branch fails, so
# do a full clone and check the SHA out.
if ! gh repo clone "$REPO" "$DIR" -- --depth 1 --branch "$REF" 2>/dev/null; then
rm -rf "$DIR"
gh repo clone "$REPO" "$DIR"
git -C "$DIR" checkout "$REF"
fi
else
gh repo clone "$REPO" "$DIR" -- --depth 1
fi
chown -R agent:agent "$DIR"
# Route git HTTPS auth for github.com through gh's credential
# helper so any later `git push` / `git pull` from within the
# sandbox picks up the same proxy-managed GH_TOKEN sentinel.
# Written to /etc/gitconfig with `--system` so any user in the
# container inherits it — equivalent to running `gh auth
# setup-git` per-user, but keeps this hook root-scoped and works
# even when no GitHub credential is bound on the host (the empty
# first helper resets whatever the base image may have set; the
# two-line pattern is what gh's own setup-git writes).
git config --system --unset-all credential."https://github.com".helper 2>/dev/null || true
git config --system --add credential."https://github.com".helper ''
git config --system --add credential."https://github.com".helper '!gh auth git-credential'
description: Clone ${{ kit.args.repo }} into ${{ kit.args.dir }} via gh
env:
- GH_TOKEN
user: "0"
- type: com.docker.sandbox/agent-context@1
config:
content: |
## github-clone
A GitHub repository (`${{ kit.args.repo }}`) has been cloned into
`${{ kit.args.dir }}` at sandbox-create time. Treat that directory as
the working copy for this task rather than `~/workspace`.
Authentication is proxy-mediated: `GH_TOKEN` in the container is a
sentinel — the sandbox proxy swaps in the real token bound on the host
(via `sbx secret set -g github`) when talking to `api.github.com` and
`github.com`. `gh` and `git` HTTPS operations both use this path, so
`gh api …`, `gh pr create`, `git push`, and friends work without any
extra setup.
Public repos work with no host-side credential bound; only writes and
private-repo access need one.
args:
dir:
default: /project
description: |
Absolute directory inside the sandbox to clone into. If the directory
already exists and is non-empty, the clone is skipped (the mixin
re-runs cleanly on `sbx create` retries).
pattern: ^/[A-Za-z0-9._/-]+$
ref:
default: ""
description: |
Optional git ref (branch, tag, or 7–40 hex commit SHA) to check out.
Empty (the default) clones the repo's default branch.
pattern: ^[A-Za-z0-9._/-]*$
repo:
required: true
description: |
GitHub repository to clone. Accepts the `owner/name` shorthand, a full
`https://github.com/owner/name[.git]` URL, or an
`[email protected]:owner/name[.git]` SSH URL. Any other form is rejected
before the clone shells out.
pattern: ^(?:[A-Za-z0-9._-]+/[A-Za-z0-9._-]+(?:\.git)?|https://github\.com/[A-Za-z0-9._-]+/[A-Za-z0-9._-]+(?:\.git)?|git@github\.com:[A-Za-z0-9._-]+/[A-Za-z0-9._-]+(?:\.git)?)$