diff --git a/README.md b/README.md index 2af6413..16f8957 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Public container images for cloud work, built multi-arch and rootless with secur | Image | Description | |---|---| -| `ghcr.io/cloudsnacks/actions-runner` | Rootless GitHub Actions runner for [Actions Runner Controller](https://github.com/actions/actions-runner-controller), with docker CLI and buildx | +| `ghcr.io/cloudsnacks/actions-runner` | Rootless GitHub Actions runner for [Actions Runner Controller](https://github.com/actions/actions-runner-controller), with docker CLI, buildx and a mise-managed CLI toolchain ([`mise.toml`](images/actions-runner/mise.toml)) | | `ghcr.io/cloudsnacks/claude-code` | Headless Claude Code agent with git-repo and agent-profile bootstrap | | `ghcr.io/cloudsnacks/dev-desktop` | Arch Linux dev workstation with Hyprland streamed over [Sunshine](https://github.com/LizardByte/Sunshine)/Moonlight, cloud tooling, and AI coding agents (`linux/amd64` only, needs `/dev/dri`) | | `ghcr.io/cloudsnacks/infisical-mcp` | Infisical MCP server (secrets management over MCP) | diff --git a/images/actions-runner/Dockerfile b/images/actions-runner/Dockerfile index 50ef229..defcdca 100644 --- a/images/actions-runner/Dockerfile +++ b/images/actions-runner/Dockerfile @@ -107,6 +107,33 @@ RUN DOCKER_ARCH="$(case "${TARGETARCH}" in amd64) echo x86_64 ;; arm64) echo aar && docker --version \ && docker buildx version +# Workflow tooling that GitHub's own hosted images ship and Ubuntu does not +# usefully package — there is no gh in the archive at all, and its `yq` is the +# unrelated Python jq-wrapper with different syntax. Without them here every +# workflow that opens a PR or patches a manifest curls its own copy into +# RUNNER_TEMP, which is the per-repo drift this image exists to absorb. +# +# The list lives in mise.toml, one line per tool, so growing it costs no +# Dockerfile. Renovate's native mise manager reads that file, which is why +# those entries carry no `# renovate:` annotation. mise itself is fetched as a +# pinned release binary rather than through the unpinned mise.run installer. +# renovate: datasource=github-releases depName=jdx/mise +ARG MISE_VERSION=2026.7.17 +# Data dir stays root-owned and read-only to the runner user; the cache is the +# only path mise writes to at runtime, so it points somewhere world-writable. +ENV MISE_DATA_DIR=/opt/mise \ + MISE_CONFIG_DIR=/opt/mise \ + MISE_CACHE_DIR=/tmp/mise-cache \ + PATH=/opt/mise/shims:$PATH +COPY mise.toml /opt/mise/config.toml +RUN MISE_ARCH="$(case "${TARGETARCH}" in amd64) echo x64 ;; *) echo "${TARGETARCH}" ;; esac)" \ + && curl -fsSL -o /tmp/mise \ + "https://github.com/jdx/mise/releases/download/v${MISE_VERSION}/mise-v${MISE_VERSION}-linux-${MISE_ARCH}" \ + && install -o root -g root -m 0755 /tmp/mise /usr/bin/mise \ + && rm -f /tmp/mise \ + && mise install --yes \ + && mise ls --installed + USER runner -LABEL org.opencontainers.image.description="GitHub Actions runner for Actions Runner Controller, with docker CLI and buildx" +LABEL org.opencontainers.image.description="GitHub Actions runner for Actions Runner Controller, with docker CLI, buildx and a mise-managed CLI toolchain" diff --git a/images/actions-runner/metadata.yaml b/images/actions-runner/metadata.yaml index 6205d06..2e2b514 100644 --- a/images/actions-runner/metadata.yaml +++ b/images/actions-runner/metadata.yaml @@ -1,14 +1,17 @@ --- name: actions-runner -description: GitHub Actions runner for Actions Runner Controller, with docker CLI and buildx +description: GitHub Actions runner for Actions Runner Controller, with docker CLI, buildx and a mise-managed CLI toolchain # -. Bump the revision whenever this image's # contents change without RUNNER_VERSION moving, so scale sets pulling with the # default IfNotPresent policy get a tag they have not already cached. Renovate # tracks upstream on RUNNER_VERSION in the Dockerfile — deliberately not # annotated here, since a -N suffix is a semver pre-release and would be # "upgraded" straight back to the bare release. -version: 2.336.0-2 +version: 2.336.0-3 platforms: - linux/amd64 - linux/arm64 -test: /home/runner/bin/Runner.Listener --version && tmux -V && docker --version && docker buildx version && dpkg -s libatomic1 libnss3 libgbm1 fonts-noto-color-emoji >/dev/null && test "$LANG" = C.UTF-8 && id -nG | grep -qw docker +# The mise loop is deliberately generic over mise.toml: every tool listed there +# must resolve through the shims on PATH and run as the runner user, so adding +# a tool needs no edit here. +test: /home/runner/bin/Runner.Listener --version && tmux -V && docker --version && docker buildx version && jq --version && test "$(mise ls --installed --json | jq 'keys|length')" -eq "$(yq -p toml -oy '.tools|length' /opt/mise/config.toml)" && for t in $(mise ls --installed --json | jq -r 'keys[]'); do command -v "$t" | grep -q '^/opt/mise/shims/' && "$t" --version >/dev/null || exit 1; done && dpkg -s libatomic1 libnss3 libgbm1 fonts-noto-color-emoji >/dev/null && test "$LANG" = C.UTF-8 && id -nG | grep -qw docker diff --git a/images/actions-runner/mise.toml b/images/actions-runner/mise.toml new file mode 100644 index 0000000..ef9d340 --- /dev/null +++ b/images/actions-runner/mise.toml @@ -0,0 +1,12 @@ +# Long-tail CLI tooling for workflows: one line per tool. Renovate's native +# mise manager matches this filename by default, so entries here need no +# `# renovate:` annotation and no addition to the repo's custom manager. +# +# Only static, version-insensitive binaries belong here. Anything a workflow +# pins against (language runtimes, kubectl, helm) stays out and is left to the +# setup-* actions, which cache into RUNNER_TOOL_CACHE. +[tools] +gh = "2.96.0" +hadolint = "2.14.0" +shellcheck = "0.11.0" +yq = "4.53.3"