From 95364dcb48a8f26748e255b36976734568621c12 Mon Sep 17 00:00:00 2001 From: Erich Blume Date: Wed, 11 Feb 2026 17:24:20 -0800 Subject: [PATCH] Simplify runner image (Dagger Phase 3) (#162) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary With Phases 1 and 2 complete, the runner image no longer needs most of its bundled tools. This PR strips it down and adds what was missing. **Removed** (now inside Dagger containers): - Node.js 24.x - Docker CLI + buildx plugin - skopeo - gnupg, lsb-release, xz-utils **Added:** - `tzdata` — fixes the TZ env var (#159, #160, #161) so `TZ=America/Los_Angeles` actually works - `flyctl` — was being installed from scratch every release **Workflow changes:** - Remove "Ensure Dagger CLI" bootstrap steps from both workflows (Dagger is in the image) - Remove "Install flyctl" step from build-blumeops (flyctl is in the image) - Remove job-level `TZ` from build-blumeops (moved to runner configmap `runner.envs`) - Set `TZ: America/Los_Angeles` in runner configmap so all job containers inherit it ## Deployment After merge: 1. Build and release the new runner image: `mise run container-release forgejo-runner v2.0.0` 2. Sync the runner: `argocd app sync forgejo-runner` 3. Verify: `kubectl -n forgejo-runner exec deploy/forgejo-runner -c runner -- date` (but the real test is running a docs release and checking the changelog date) Reviewed-on: https://forge.ops.eblu.me/eblume/blumeops/pulls/162 --- .forgejo/workflows/build-blumeops.yaml | 18 ------------ .forgejo/workflows/build-container.yaml | 12 -------- .../manifests/forgejo-runner/configmap.yaml | 3 +- containers/forgejo-runner/Dockerfile | 28 ++++++------------- .../dagger-phase3-runner.feature.md | 1 + docs/how-to/plans/adopt-dagger-ci.md | 3 +- 6 files changed, 13 insertions(+), 52 deletions(-) create mode 100644 docs/changelog.d/dagger-phase3-runner.feature.md diff --git a/.forgejo/workflows/build-blumeops.yaml b/.forgejo/workflows/build-blumeops.yaml index 7bfa577..754f52a 100644 --- a/.forgejo/workflows/build-blumeops.yaml +++ b/.forgejo/workflows/build-blumeops.yaml @@ -37,8 +37,6 @@ on: jobs: build: runs-on: k8s - env: - TZ: America/Los_Angeles steps: - name: Resolve version id: version @@ -110,17 +108,6 @@ jobs: with: fetch-depth: 0 - - name: Ensure Dagger CLI - run: | - # Bootstrap: install dagger if not already in the runner image. - # Remove once all runners include dagger (Phase 3). - if ! command -v dagger &>/dev/null; then - echo "Dagger not found, installing..." - curl -fsSL https://dl.dagger.io/dagger/install.sh | DAGGER_VERSION=0.19.11 sh - mv ./bin/dagger /usr/local/bin/dagger && rmdir ./bin - fi - dagger version - - name: Build docs run: | VERSION="${{ steps.version.outputs.version }}" @@ -306,11 +293,6 @@ jobs: echo "Docs app synced successfully!" - - name: Install flyctl - run: | - curl -L https://fly.io/install.sh | sh - echo "/root/.fly/bin" >> "$GITHUB_PATH" - - name: Purge Fly.io proxy cache env: FLY_API_TOKEN: ${{ secrets.FLY_DEPLOY_TOKEN }} diff --git a/.forgejo/workflows/build-container.yaml b/.forgejo/workflows/build-container.yaml index 8973c9f..98231cf 100644 --- a/.forgejo/workflows/build-container.yaml +++ b/.forgejo/workflows/build-container.yaml @@ -68,18 +68,6 @@ jobs: echo "" echo "Skipping build." - - name: Ensure Dagger CLI - if: steps.check.outputs.exists == 'true' - run: | - # Bootstrap: install dagger if not already in the runner image. - # Remove once all runners include dagger (Phase 3). - if ! command -v dagger &>/dev/null; then - echo "Dagger not found, installing..." - curl -fsSL https://dl.dagger.io/dagger/install.sh | DAGGER_VERSION=0.19.11 sh - mv ./bin/dagger /usr/local/bin/dagger && rmdir ./bin - fi - dagger version - - name: Publish if: steps.check.outputs.exists == 'true' run: | diff --git a/argocd/manifests/forgejo-runner/configmap.yaml b/argocd/manifests/forgejo-runner/configmap.yaml index dd3c3ef..9ca43bf 100644 --- a/argocd/manifests/forgejo-runner/configmap.yaml +++ b/argocd/manifests/forgejo-runner/configmap.yaml @@ -12,9 +12,10 @@ data: file: /data/.runner capacity: 2 timeout: 3h - # Set DOCKER_HOST in job containers so they can run docker commands + # Env vars injected into all job containers envs: DOCKER_HOST: tcp://127.0.0.1:2375 + TZ: America/Los_Angeles container: # Use our custom job execution image with Node.js + Docker CLI diff --git a/containers/forgejo-runner/Dockerfile b/containers/forgejo-runner/Dockerfile index 2694dec..be569ed 100644 --- a/containers/forgejo-runner/Dockerfile +++ b/containers/forgejo-runner/Dockerfile @@ -3,7 +3,8 @@ # This image is used as the job execution environment for Forgejo Actions. # The host runner daemon creates containers from this image to run workflow steps. # -# Includes: Node.js (for GitHub Actions), Docker CLI, git, and common CI tools. +# Build logic (container images, docs site) runs inside Dagger containers, +# so this image only needs: git, Dagger CLI, ArgoCD CLI, uv, and basic tools. # # Usage: Configure runner with label like: # docker:docker://registry.ops.eblu.me/blumeops/forgejo-runner:latest @@ -18,24 +19,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ curl \ git \ jq \ - gnupg \ - lsb-release \ - xz-utils \ - && rm -rf /var/lib/apt/lists/* - -# Install Node.js 24.x LTS (required for actions/checkout@v4 and Quartz builds) -RUN curl -fsSL https://deb.nodesource.com/setup_24.x | bash - \ - && apt-get install -y --no-install-recommends nodejs \ - && rm -rf /var/lib/apt/lists/* - -# Install Docker CLI (for container builds - daemon accessed via socket mount) -# and skopeo (for pushing images to zot registry - Docker 27 manifest compat issues) -RUN install -m 0755 -d /etc/apt/keyrings \ - && curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc \ - && chmod a+r /etc/apt/keyrings/docker.asc \ - && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian $(lsb_release -cs) stable" > /etc/apt/sources.list.d/docker.list \ - && apt-get update \ - && apt-get install -y --no-install-recommends docker-ce-cli docker-buildx-plugin skopeo \ + tzdata \ && rm -rf /var/lib/apt/lists/* # Install uv (Python package runner for towncrier) @@ -44,7 +28,6 @@ RUN curl -LsSf https://astral.sh/uv/install.sh | sh \ && mv /root/.local/bin/uvx /usr/local/bin/uvx # Install argocd CLI (for syncing apps from workflows) -# Use dpkg --print-architecture as fallback since TARGETARCH may be empty in single-platform builds RUN ARCH="${TARGETARCH:-$(dpkg --print-architecture)}" \ && curl -fsSL -o /usr/local/bin/argocd \ "https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-${ARCH}" \ @@ -60,5 +43,10 @@ RUN ARCH="${TARGETARCH:-$(dpkg --print-architecture)}" \ && rm /tmp/dagger.tar.gz \ && dagger version +# Install flyctl (for Fly.io cache purge after docs deploy) +RUN curl -L https://fly.io/install.sh | sh \ + && mv /root/.fly/bin/flyctl /usr/local/bin/fly \ + && rm -rf /root/.fly + # Default to bash CMD ["/bin/bash"] diff --git a/docs/changelog.d/dagger-phase3-runner.feature.md b/docs/changelog.d/dagger-phase3-runner.feature.md new file mode 100644 index 0000000..d145b7b --- /dev/null +++ b/docs/changelog.d/dagger-phase3-runner.feature.md @@ -0,0 +1 @@ +Simplify Forgejo runner image (Dagger Phase 3): remove Node.js, Docker CLI, buildx, skopeo, gnupg, lsb-release, and xz-utils. Add tzdata and flyctl. All build tools now live inside Dagger containers. diff --git a/docs/how-to/plans/adopt-dagger-ci.md b/docs/how-to/plans/adopt-dagger-ci.md index 2b3b617..ef4db55 100644 --- a/docs/how-to/plans/adopt-dagger-ci.md +++ b/docs/how-to/plans/adopt-dagger-ci.md @@ -10,7 +10,7 @@ tags: # Plan: Adopt Dagger as CI/CD Build Engine -> **Status:** Phase 2 implemented +> **Status:** Phase 3 implemented ## Background @@ -509,6 +509,7 @@ BuildKit caches aggressively, making repeated builds fast. Since the Forgejo run - [ ] Simplified runner image builds and runs - [ ] Dagger engine starts inside the runner's DinD environment - [ ] All existing workflows pass with the simplified runner +- [ ] TZ=America/Los_Angeles works in job containers (tzdata installed) ## How-To Articles to Write