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# ./deploy/runner/build.sh # both tags
17# ./deploy/runner/build.sh latest # just the slim one
18# ./deploy/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. Keep in step with the workspace
27# `rust-version` in Cargo.toml.
28RUST_VERSION="${RUST_VERSION:-1.98.0}"
29
30build() {
31 local tag="$1" rust="$2"
32 echo "==> building ${NAME}:${tag} (rust ${rust:-none}, claude channel ${CHANNEL})"
33 docker build \
34 --build-arg "RUST_VERSION=${rust}" \
35 --build-arg "CLAUDE_CHANNEL=${CHANNEL}" \
36 -t "${NAME}:${tag}" \
37 .
38}
39
40case "${1:-all}" in
41 latest) build latest "" ;;
42 rust) build rust "${RUST_VERSION}" ;;
43 all)
44 build latest ""
45 build rust "${RUST_VERSION}"
46 ;;
47 *)
48 echo "usage: $0 [latest|rust|all]" >&2
49 exit 64
50 ;;
51esac
52
53echo
54echo "==> done"
55docker images "${NAME}" --format ' {{.Repository}}:{{.Tag}} {{.Size}}'
56echo
57echo "Point anvil at it in anvil.toml if you use a non-default name:"
58echo " [ci]"
59echo " default_image = \"${NAME}:latest\""
60echo " [agent]"
61echo " image = \"${NAME}:latest\""