Skip to content

Commit f8a8747

Browse files
committed
ci: add custom ARC runner image with build+push pipeline
In this commit, we add a darepo-specific GitHub Actions runner image plus the workflow that builds and publishes it to GHCR. The image is based on summerwind/actions-runner-dind so the runner pod gets a working Docker daemon, and layers on the build deps that darepo's Makefile-driven CI needs (build-essential, make, postgresql-client, sqlite3) along with a preinstalled Go matching the GO_VERSION pinned in main.yml. The first head-to-head run against the new ARC self-hosted pool exposed two image-level blockers on the upstream summerwind image: "make: command not found" on every Makefile-driven step, and EACCES on /opt/hostedtoolcache when actions/setup-go tried to drop the Go toolchain. Patching every job with apt-installs and chowns is the wrong level to fix this. Baking a single darepo-runner image keeps the workflows clean and gives every job a fast-start runner with the toolchain already in the cache. The runner-image.yml workflow stays on ubuntu-latest (GitHub-hosted) because we can't use ARC to build the ARC image while the cluster is still on the stock summerwind image. PRs validate the Dockerfile by building but skip the push; main pushes :latest plus :sha-<short>. Once this is merged and the first :latest tag is published, the RunnerDeployment in lightning-infra needs to point its image at ghcr.io/lightninglabs/darepo-runner:latest and set dockerdWithinRunnerContainer: true. Without that pairing the runs-on: [self-hosted] jobs will keep failing the same way.
1 parent 7f09189 commit f8a8747

3 files changed

Lines changed: 181 additions & 0 deletions

File tree

.github/runner-image/Dockerfile

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Custom GitHub Actions runner image for darepo CI on the ARC self-hosted
2+
# pool. Based on summerwind/actions-runner-dind which gives us a working
3+
# Docker daemon inside the runner container; we layer on the build toolchain,
4+
# system deps, and a preinstalled Go that darepo's Makefile-driven CI needs.
5+
#
6+
# Built and pushed to ghcr.io/lightninglabs/darepo-runner via the
7+
# .github/workflows/runner-image.yml workflow. The lightning-infra
8+
# RunnerDeployment must reference this image and enable dockerd inside the
9+
# runner pod.
10+
11+
ARG BASE_IMAGE=summerwind/actions-runner-dind:latest
12+
FROM ${BASE_IMAGE}
13+
14+
# Pinned Go version. Keep in sync with GO_VERSION in the project Makefile and
15+
# .github/workflows/main.yml so actions/setup-go finds the preinstalled
16+
# toolchain in the cache instead of re-downloading on every job.
17+
ARG GO_VERSION=1.25.5
18+
19+
USER root
20+
21+
# Build toolchain and runtime deps for darepo's Makefile and test harness.
22+
# build-essential covers gcc/g++/libc-dev for any cgo paths; postgresql-client
23+
# is used by systest with the postgres backend; sqlite3 for the sqlite
24+
# backend.
25+
RUN apt-get update \
26+
&& apt-get install -y --no-install-recommends \
27+
build-essential \
28+
ca-certificates \
29+
curl \
30+
git \
31+
make \
32+
pkg-config \
33+
postgresql-client \
34+
sqlite3 \
35+
&& apt-get clean \
36+
&& rm -rf /var/lib/apt/lists/*
37+
38+
# Preinstall Go into the same path actions/setup-go writes to, so the action
39+
# treats it as a cache hit and skips downloading. Layout per setup-go on
40+
# Linux: /opt/hostedtoolcache/go/<version>/<arch>, with a sibling
41+
# <arch>.complete marker file. Cache arch is x64 for amd64 hosts and arm64
42+
# for arm64.
43+
RUN set -eux; \
44+
ARCH="$(dpkg --print-architecture)"; \
45+
case "${ARCH}" in \
46+
amd64) GO_ARCH=amd64; CACHE_ARCH=x64 ;; \
47+
arm64) GO_ARCH=arm64; CACHE_ARCH=arm64 ;; \
48+
*) echo "unsupported arch ${ARCH}" >&2; exit 1 ;; \
49+
esac; \
50+
curl -fsSL "https://go.dev/dl/go${GO_VERSION}.linux-${GO_ARCH}.tar.gz" -o /tmp/go.tgz; \
51+
mkdir -p "/opt/hostedtoolcache/go/${GO_VERSION}/${CACHE_ARCH}"; \
52+
tar -C "/opt/hostedtoolcache/go/${GO_VERSION}/${CACHE_ARCH}" --strip-components=1 -xzf /tmp/go.tgz; \
53+
touch "/opt/hostedtoolcache/go/${GO_VERSION}/${CACHE_ARCH}.complete"; \
54+
rm -f /tmp/go.tgz; \
55+
chown -R runner:runner /opt/hostedtoolcache
56+
57+
USER runner

.github/runner-image/README.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# darepo CI runner image
2+
3+
Custom GitHub Actions runner image for the ARC self-hosted pool that runs
4+
darepo CI. Based on `summerwind/actions-runner-dind` and layered with the
5+
build toolchain (`make`, `build-essential`), database clients
6+
(`postgresql-client`, `sqlite3`), and a preinstalled Go matching the version
7+
pinned in [`main.yml`](../workflows/main.yml).
8+
9+
## Why this exists
10+
11+
The upstream `summerwind/actions-runner` image is intentionally lean: no
12+
`make`, no compilers, and `/opt/hostedtoolcache` is owned by root so
13+
`actions/setup-go` fails with `EACCES` when it tries to drop the toolchain.
14+
Patching every workflow job with apt-installs and chowns is the wrong level
15+
to fix this; baking a darepo-specific image keeps the workflows clean and
16+
gives every job a fast-start runner.
17+
18+
## Build and publish
19+
20+
[`.github/workflows/runner-image.yml`](../workflows/runner-image.yml) builds
21+
and pushes to `ghcr.io/lightninglabs/darepo-runner` on every change to this
22+
directory or the workflow itself. Tags:
23+
24+
- `ghcr.io/lightninglabs/darepo-runner:latest` on `main`
25+
- `ghcr.io/lightninglabs/darepo-runner:sha-<short>` on every build
26+
27+
Pull requests build the image to validate the Dockerfile but do not push.
28+
29+
## Wiring it into the cluster
30+
31+
The `RunnerDeployment` in
32+
[`lightning-infra/charts/actions-runner-controller/runners-staging.yaml`](https://github.com/lightninglabs/lightning-infra/blob/main/charts/actions-runner-controller/runners-staging.yaml)
33+
needs to point at this image and enable dockerd inside the runner pod:
34+
35+
```yaml
36+
spec:
37+
replicas: 1
38+
template:
39+
spec:
40+
organization: lightninglabs
41+
image: ghcr.io/lightninglabs/darepo-runner:latest
42+
dockerdWithinRunnerContainer: true
43+
```
44+
45+
If the `darepo-runner` package on GHCR is private, the namespace also needs
46+
a pull secret referenced via `imagePullSecrets`.

.github/workflows/runner-image.yml

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
name: Runner image
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
paths:
8+
- '.github/runner-image/**'
9+
- '.github/workflows/runner-image.yml'
10+
pull_request:
11+
paths:
12+
- '.github/runner-image/**'
13+
- '.github/workflows/runner-image.yml'
14+
workflow_dispatch:
15+
16+
permissions:
17+
contents: read
18+
packages: write
19+
20+
defaults:
21+
run:
22+
shell: bash
23+
24+
env:
25+
IMAGE: ghcr.io/lightninglabs/darepo-runner
26+
27+
jobs:
28+
build:
29+
name: Build and push runner image
30+
runs-on: ubuntu-latest
31+
steps:
32+
- name: Set up QEMU
33+
uses: lightninglabs/gh-actions/setup-qemu-action@2021.01.25.00
34+
35+
- name: Set up Docker Buildx
36+
uses: lightninglabs/gh-actions/setup-buildx-action@2021.01.25.00
37+
38+
- name: Git checkout
39+
uses: actions/checkout@v5
40+
with:
41+
fetch-depth: 0
42+
43+
- name: Log in to GHCR
44+
if: github.event_name != 'pull_request'
45+
uses: lightninglabs/gh-actions/login-action@2021.01.25.00
46+
with:
47+
registry: ghcr.io
48+
username: ${{ github.actor }}
49+
password: ${{ secrets.GITHUB_TOKEN }}
50+
51+
- name: Compute image tags
52+
id: tags
53+
run: |
54+
set -euo pipefail
55+
SHORT_SHA="$(git rev-parse --short=7 HEAD)"
56+
TAGS="${IMAGE}:sha-${SHORT_SHA}"
57+
if [[ "${GITHUB_REF}" == "refs/heads/main" ]]; then
58+
TAGS="${TAGS}
59+
${IMAGE}:latest"
60+
fi
61+
{
62+
echo "tags<<EOF"
63+
echo "${TAGS}"
64+
echo "EOF"
65+
} >> "${GITHUB_OUTPUT}"
66+
67+
- name: Build and push runner image
68+
id: build
69+
uses: lightninglabs/gh-actions/build-push-action@2021.01.25.00
70+
with:
71+
context: .github/runner-image
72+
# PRs validate the build but don't push to ghcr.
73+
push: ${{ github.event_name != 'pull_request' }}
74+
tags: ${{ steps.tags.outputs.tags }}
75+
76+
- name: Image digest
77+
if: github.event_name != 'pull_request'
78+
run: echo "darepo-runner: ${{ steps.build.outputs.digest }}"

0 commit comments

Comments
 (0)