From 266e8cdd86dc3419a4d04cf5937ed86b3b80470c Mon Sep 17 00:00:00 2001 From: Orkuncakilkaya Date: Sat, 5 Sep 2026 02:57:09 +0300 Subject: [PATCH] docs(ci): document the runner network a self-hosted CI needs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every workflow's first step clones ${{ github.server_url }}, which on a self-hosted Forgejo instance is an internal address like http://forgejo:3000. The runner's default is to put each job on a freshly created per-job network that the Forgejo container is not attached to, so the clone dies with fatal: unable to access 'http://forgejo:3000/…': Could not resolve host Nothing in the repo said so, and the failure is intermittent: Docker forwards names it cannot resolve to the host's resolver, which answered for the container name often enough that CI passed for weeks before stopping. Documents the fix (pin job containers to a network Forgejo is also on, using a dedicated one rather than the general application network so a CI job cannot reach unrelated services) and how to verify it without running a workflow. Co-Authored-By: Claude Opus 5 --- CONTRIBUTING.md | 33 +++++++++++++++++++++++++++++++++ changes/ci-runner-dns.md | 8 ++++++++ 2 files changed, 41 insertions(+) create mode 100644 changes/ci-runner-dns.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ecdcc391..6d51cfb1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -176,6 +176,39 @@ non-destructive version of "tidy the history" without touching a single commit. - Fill in the PR template checklist. Reference the issue you close with `Closes #NN` in the description or a commit message. +## CI (self-hosted runners) + +Every workflow starts by cloning `${{ github.server_url }}/${{ github.repository }}`. +On a self-hosted Forgejo runner that URL is usually the instance's *internal* +address (e.g. `http://forgejo:3000`), so **the job container must be able to +resolve it**. The runner puts each job on a fresh per-job network by default, +which the Forgejo container is not attached to — so the clone fails with: + +``` +fatal: unable to access 'http://forgejo:3000/…': Could not resolve host: forgejo +``` + +Give the runner a config that pins job containers to a network Forgejo is also +on. A dedicated network is better than the general application network, so a CI +job cannot reach unrelated services: + +```yaml +# the runner's config.yml, passed with: forgejo-runner daemon --config … +container: + network: forgejo-ci +``` + +with `forgejo-ci` attached to the Forgejo container as well. Verify it without +running a workflow: + +```bash +docker run --rm --network forgejo-ci alpine:3 getent hosts forgejo +``` + +This failure mode is intermittent if left unfixed: Docker forwards names it +cannot resolve to the host's resolver, which may answer for the container name +often enough that CI looks healthy for a while. + ## Reporting issues Use the templates under [`.forgejo/issue_template/`](.forgejo/issue_template): diff --git a/changes/ci-runner-dns.md b/changes/ci-runner-dns.md new file mode 100644 index 00000000..c6067d37 --- /dev/null +++ b/changes/ci-runner-dns.md @@ -0,0 +1,8 @@ +bump: patch +type: docs +CONTRIBUTING documents what a self-hosted Forgejo runner needs for CI to work at +all: every workflow clones `${{ github.server_url }}`, which on a self-hosted +instance is an internal address, so job containers must be able to resolve it. +The runner's default is a fresh per-job network the Forgejo container is not on, +which fails the clone — intermittently, because Docker forwards unresolved names +to the host resolver, so CI can look healthy for a while before it stops.