Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions runners/arc/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
# local cache instead of hitting api.github.com / objects.githubusercontent.com
# from a cold pod (setup-python was timing out fetching the version manifest).
#
# It further bakes in `jq`/`curl` and Playwright's browser OS dependencies so
# e2e/visual jobs only run `npx playwright install <browser>` (no apt/root at
# job time). This is the CI-capable runner image register-repo.sh defaults to.
#
# Build + push: runners/arc/build-and-push-runner-image.sh
# Consumed by: runners/arc/runner-scale-set-values.yaml (template.spec image)
# runners/arc/register-repo.sh (--runner-image / RUNNER_IMAGE)
Expand Down Expand Up @@ -70,4 +74,18 @@ COPY warm-python-toolcache.sh /usr/local/bin/warm-python-toolcache.sh
RUN chmod +x /usr/local/bin/warm-python-toolcache.sh; \
/usr/local/bin/warm-python-toolcache.sh 3.10 3.11

# --- Playwright browser system dependencies ----------------------------------
# e2e / visual-regression jobs run Playwright. The heavy, root-requiring part is
# the OS-level libraries the browsers need (libnss3, libatk, fonts, …); baking
# those in via Playwright's own `install-deps` resolver means consumer jobs only
# need `npx playwright install <browser>` — which downloads the browser binary
# into the (unprivileged) runner cache and needs neither apt nor root at job
# time. Uses the warmed Node from the toolcache. Pin PLAYWRIGHT_VERSION to the
# consumers' Playwright major so the dep list matches.
ARG PLAYWRIGHT_VERSION=1.49.1
RUN set -eux; \
export PATH="/opt/hostedtoolcache/node/${NODE_VERSION}/x64/bin:$PATH"; \
npx --yes "playwright@${PLAYWRIGHT_VERSION}" install-deps; \
rm -rf /var/lib/apt/lists/* /root/.npm

USER runner
21 changes: 15 additions & 6 deletions runners/arc/ONBOARD-REPO.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,21 @@ means these work out of the box on `runs-on: <SCALE_SET_NAME>` — no separate
- `docker build` / `docker buildx build --push` (GHCR image builds) ✅
- `docker run` / `docker ps` (daemon reachable via `DOCKER_HOST`) ✅

**`docker compose` needs one extra step.** The stock `ghcr.io/actions/actions-runner`
image ships the docker CLI + buildx but **not** the compose-v2 plugin, so
`docker compose -f …` fails with `unknown shorthand flag: 'f' in -f`. To enable it,
publish `runners/arc/Dockerfile` (bakes the compose plugin) and point the scale set
at it via `RUNNER_IMAGE` / the `image:` field, then re-register (below). DinD alone
does **not** add compose.
**`docker compose` works by default now.** `register-repo.sh` defaults the runner
image to the **FuzeInfra CI-capable image** (`ghcr.io/izzywdev/fuzeinfra-arc-runner`,
built from `runners/arc/Dockerfile`), which bakes in the **compose-v2 & buildx CLI
plugins**, `jq`/`curl`, a warm Python/Node toolcache, and **Playwright browser OS
deps**. So `docker compose -f …`, `docker buildx …`, and `npx playwright install
<browser>` all work on `runs-on: <SCALE_SET_NAME>` out of the box.

> **Prerequisite:** that image must be **published + PUBLIC** on GHCR (or an
> `imagePullSecret` wired into `arc-runners`) or runner pods `ImagePullBackOff`.
> Publish it once via the `build-runner-image` workflow
> (`runners/arc/workflows-to-install/build-runner-image.yml` → move into
> `.github/workflows/`) or `runners/arc/build-and-push-runner-image.sh`.

To fall back to the stock image (no compose), pass `--runner-image
ghcr.io/actions/actions-runner:latest`. DinD alone does **not** add compose.

**Re-register existing scale sets to pick up DinD.** The dind sidecar only appears
on pods created *after* the Helm values change. Any scale set registered before DinD
Expand Down
37 changes: 32 additions & 5 deletions runners/arc/register-repo.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@
# --name fuzefront \
# --secret arc-runner-github-app # existing secret in arc-runners
#
# # override the CI runner image or container mode (both have CI-capable
# # defaults — the FuzeInfra runner image + dind — so onboarding stays a
# # single invocation):
# ./runners/arc/register-repo.sh \
# --repo-url https://github.com/izzywdev/FuzeFront \
# --name fuzefront --secret arc-runner-github-app \
# --runner-image ghcr.io/izzywdev/fuzeinfra-arc-runner:2026-07-13 \
# --container-mode dind
#
# # uninstall a repo's scale set
# ./runners/arc/register-repo.sh --name fuzefront --uninstall
#
Expand All @@ -48,10 +57,24 @@ ARC_VERSION="0.14.2"
# the node; raise per-repo with --max-runners once the CI pool is scaled out.
MAX_RUNNERS=3
MIN_RUNNERS=0
# Runner image. Stock actions-runner ships the docker CLI + buildx but NOT the
# compose-v2 plugin. To get `docker compose`, publish runners/arc/Dockerfile and
# point RUNNER_IMAGE at it (e.g. ghcr.io/izzywdev/fuzeinfra-arc-runner:<tag>).
RUNNER_IMAGE="${RUNNER_IMAGE:-ghcr.io/actions/actions-runner:latest}"
# Runner image. Defaults to the FuzeInfra CI-capable image (runners/arc/Dockerfile:
# stock actions-runner + docker compose-v2 & buildx plugins + jq/curl + warm
# Python/Node toolcache + Playwright browser deps) so every scale set comes up
# CI-capable from this one provisioning change. Override with --runner-image or
# RUNNER_IMAGE (e.g. the stock ghcr.io/actions/actions-runner:latest — but that
# lacks `docker compose`, so gate-* / build-test jobs will fail on it).
#
# PREREQUISITE: the default image must be published + PUBLIC (or an imagePullSecret
# wired into arc-runners) or runner pods ImagePullBackOff. Publish it via the
# build-runner-image workflow (runners/arc/workflows-to-install/build-runner-image.yml)
# or runners/arc/build-and-push-runner-image.sh before onboarding new repos.
RUNNER_IMAGE="${RUNNER_IMAGE:-ghcr.io/izzywdev/fuzeinfra-arc-runner:latest}"

# Container mode for the runner pods. "dind" (default) injects a privileged
# docker:dind sidecar + init-dind-externals initContainer and wires DOCKER_HOST,
# giving docker / docker compose / docker buildx / docker run self-hosted. Kept
# parameterizable (--container-mode) but dind is the CI-capable default.
CONTAINER_MODE="dind"

REPO_URL=""
SCALE_SET_NAME=""
Expand All @@ -76,6 +99,8 @@ while [[ $# -gt 0 ]]; do
--app-install-id) APP_INSTALL_ID="$2"; shift 2 ;;
--app-private-key) APP_PRIVATE_KEY_FILE="$2"; shift 2 ;;
--max-runners) MAX_RUNNERS="$2"; shift 2 ;;
--runner-image) RUNNER_IMAGE="$2"; shift 2 ;;
--container-mode) CONTAINER_MODE="$2"; shift 2 ;;
--uninstall) UNINSTALL=true; shift ;;
--help|-h) usage ;;
*) echo "Unknown option: $1"; usage ;;
Expand Down Expand Up @@ -180,7 +205,7 @@ template:
# FuzeInfra arc-reinstall-scaleset.yml for the staging set) to pick this up --
# the dind sidecar only appears on pods created after this Helm values change.
containerMode:
type: dind
type: ${CONTAINER_MODE}

controllerServiceAccount:
namespace: ${CONTROLLER_NS}
Expand All @@ -200,6 +225,8 @@ EOF

# ---- Helm install/upgrade ---------------------------------------------------
echo "==> Registering scale set '$SCALE_SET_NAME' for $REPO_URL …"
echo " runner image : $RUNNER_IMAGE"
echo " containerMode: $CONTAINER_MODE"
echo "$VALUES" | helm upgrade --install "$SCALE_SET_NAME" \
"$ARC_RUNNER_CHART" \
--version "$ARC_VERSION" \
Expand Down
Loading