feat(infra): reactivate act_runner cache by sharing the runners network #82
Reference in New Issue
Block a user
Delete Branch "feat/infra/reactivate-act-runner-cache"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Closes the deferred-since-day-one cache-server gap (documented as "Cache server (deferred)" in
infra/README.mdand mentioned every time we hit a slow CI install).Root cause.
act_runner's built-in cache server binds inside the runner container and advertises an IP on the compose-definedapf-portal-act-runnersbridge — but jobs are spawned via the mounted/var/run/docker.sock, which puts them on Docker's anonymous defaultbridge. The advertised URL is unreachable from the job, every cache request burns a ~2 minETIMEDOUT(restore + save), the hit rate is zero.Fix. Tell
act_runnerto attach jobs to the same compose-defined bridge as the runners, viacontainer.networkin the sharedrunner-config.yaml. The advertised cache URL becomes a normal internal-network DNS hop, jobs reach the cache server,cache: 'pnpm'works end-to-end.Blast-radius trade-off (bounded). Every container on
apf-portal-act-runnersis one of our runner containers, plus the jobs they spawn — all of which already have full docker-socket access. Sharing a network doesn't widen what a malicious workflow can already do; it just lets jobs reach the cache server.What lands
infra/runner-config.yaml— addcontainer.network: apf-portal-act-runners. Surface thecache.enabled: truedefault explicitly so the toggle is discoverable..gitea/workflows/ci.yml— re-enablecache: 'pnpm'on everyactions/setup-nodestep (5 jobs). Drop the now-stale block comment that explained the disablement..gitea/workflows/security-scheduled.yml— same on the two setup-node steps.infra/README.md"Cache server" section rewritten — was"(deferred)", now describes the working setup, rationale, and the disable toggle.ci.yml's Trivy comment trimmed to drop the cross-reference to the deferred-cache-server section that no longer exists.Roll-out (manual, post-merge, on the runner host)
rotaterecreates the containers with the newrunner-config.yamlmount intact (rolling restart, ~15 s pause between each runner so the CI pipeline stays online).Test plan
Set up Node.jsstep shows the cache restore attempt succeed quickly (no ETIMEDOUT). TheRun pnpm install --frozen-lockfilestep on the first post-rollout run still reportsProgress: resolved N, reused 0, downloaded N(cold seed).reused N, downloaded 0(or a small downloaded delta if Renovate moved a dep meanwhile) — the cache hit is real.Complete jobstep at the end no longer showsreserveCache failed: connect ETIMEDOUTwarnings.pnpm install+ the 2× ~2 min ETIMEDOUTs we used to eat).The deferred-since-day-one cache-server gap (documented as "Cache server (deferred)" in infra/README.md, mentioned every time we hit a slow CI install). Root cause: act_runner's built-in cache server binds inside the runner container and advertises an IP on the compose-defined `apf-portal-act-runners` bridge — but jobs are spawned via the mounted /var/run/docker. sock, which puts them on Docker's anonymous default `bridge` instead. The advertised URL is unreachable from the job, every cache request burns a ~2 min ETIMEDOUT (restore + save), the hit rate is zero. Fix: tell act_runner to attach jobs to the same compose-defined bridge as the runners, via `container.network` in the shared runner-config.yaml. The advertised cache URL becomes a normal internal-network DNS hop, jobs reach the cache server, and `cache: 'pnpm'` works end-to-end. The blast-radius trade-off is bounded: every container on the apf-portal-act-runners network is one of our runner containers (plus the jobs they spawn), all of which already have full docker-socket access. Sharing a network does not widen what a malicious workflow can already do; it just lets jobs reach the cache server. Changes: - infra/runner-config.yaml: add `container.network: apf-portal- act-runners`. Surface the `cache.enabled: true` default explicitly so a future contributor knows where the toggle is. - .gitea/workflows/ci.yml: re-enable `cache: 'pnpm'` on every actions/setup-node step (5 jobs). Drop the now-stale block comment that explained the disablement. - .gitea/workflows/security-scheduled.yml: same on the two setup-node steps in this workflow. - infra/README.md "Cache server" section rewritten — was "(deferred)", now describes the working setup, with the rationale and blast-radius note. The disable toggle is documented inline. - ci.yml's Trivy comment trimmed to drop the cross-reference to the deferred-cache-server section that no longer exists. Roll-out on the runner host (manual, post-merge): cd <repo>/infra git pull ./ci-runners.sh rotate `rotate` recreates the containers with the new runner-config.yaml mount intact. The first CI job after rollout seeds the cache from cold (~30-60 s install); subsequent jobs should report `reused N` instead of `downloaded N` in the `pnpm install --frozen-lockfile` line and finish a few minutes faster overall.