anvilsign in

collin/anvil

1#!/usr/bin/env bash
2# Build the shared anvil runner image(s) — what BOTH CI jobs and agent sessions
3# execute in.
4#
5# Two tags from one Dockerfile on one base, differing only in whether the Rust
6# toolchain is installed:
7#
8# anvil-runner:latest ubuntu:26.04 general purpose, the default
9# anvil-runner:rust ubuntu:26.04 + rustup carries the Rust toolchain
10#
11# There is deliberately no registry push: anvil resolves its default image from
12# the LOCAL image store and treats a failed pull as non-fatal when the image is
13# already present. So this must run on whichever host owns the Docker daemon
14# anvil talks to — the VPS in production, your machine in dev.
15#
16# ./docker/runner/build.sh # both tags
17# ./docker/runner/build.sh latest # just the slim one
18# ./docker/runner/build.sh rust # just the toolchain one
19set -euo pipefail
20
21cd "$(dirname "$0")"
22
23NAME="${ANVIL_RUNNER_IMAGE:-anvil-runner}"
24CHANNEL="${CLAUDE_CHANNEL:-stable}"
25
26# Toolchain baked into the `rust` tag, read from the repo's rust-toolchain.toml
27# so the image compiles with the same rustc this checkout does. Not duplicated
28# here on purpose: that file is the one place the version is set.
29RUST_VERSION="${RUST_VERSION:-$(
30 sed -n 's/^[[:space:]]*channel[[:space:]]*=[[:space:]]*"\(.*\)".*/\1/p' \
31 ../../rust-toolchain.toml
32)}"
33if [ -z "$RUST_VERSION" ]; then
34 echo "could not read [toolchain] channel from rust-toolchain.toml" >&2
35 exit 1
36fi
37
38build() {
39 local tag="$1" rust="$2"
40 echo "==> building ${NAME}:${tag} (rust ${rust:-none}, claude channel ${CHANNEL})"
41 docker build \
42 --build-arg "RUST_VERSION=${rust}" \
43 --build-arg "CLAUDE_CHANNEL=${CHANNEL}" \
44 -t "${NAME}:${tag}" \
45 .
46}
47
48case "${1:-all}" in
49 latest) build latest "" ;;
50 rust) build rust "${RUST_VERSION}" ;;
51 all)
52 build latest ""
53 build rust "${RUST_VERSION}"
54 ;;
55 *)
56 echo "usage: $0 [latest|rust|all]" >&2
57 exit 64
58 ;;
59esac
60
61echo
62echo "==> done"
63docker images "${NAME}" --format ' {{.Repository}}:{{.Tag}} {{.Size}}'
64echo
65echo "Point anvil at it in anvil.toml if you use a non-default name:"
66echo " [ci]"
67echo " default_image = \"${NAME}:latest\""
68echo " [agent]"
69echo " image = \"${NAME}:latest\""