ci: the runner is docker-mode, and a guide for setting one up
`runs-on: ubuntu-latest` stays what it is everywhere else — a disposable container — and `docker-compose.ci.yml` is now what makes that true: the label maps to `catthehacker/ubuntu:act-24.04`, job containers share the runner's network so the cache server is reachable at all, and the host's docker socket is passed through (`docker_host: automount`) so the image workflow can build. The failure this is replacing is worth naming, because the symptom does not point at it: with a **host**-mode runner answering the same label, every job runs directly on the server as the runner's own user, so the workflows' `apt-get install` steps fail on permissions — and had they succeeded, CI would have been installing packages on a host. A workflow cannot tell which kind of runner it got; only the label map can say. `docs/gitea-runner.md` is the separate guide: why docker mode, the prerequisites including Gitea's two `app.ini` settings, the install, how to remove a host-mode runner (and what to check before you do, since a runner is shared), how to verify a job really is in a container, why labels cannot be changed without re-registering, and a table of the failures with their causes. Also `workflow_dispatch` on the test workflow, so a fresh runner can be proved from the UI without inventing a commit. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
6 files changed
+299
-59
No files matched your search
+58
-34
@@ -1,48 +1,72 @@
|
||||
# The Gitea Actions runner, for a single-machine Gitea.
|
||||
# The Gitea Actions runner, in Docker.
|
||||
#
|
||||
# Nothing in .gitea/workflows runs until a runner is registered, and this is the
|
||||
# whole of it. Two settings do the work:
|
||||
# This is the runner that executes everything in `.gitea/workflows`. It claims
|
||||
# the label **`ubuntu-latest`** and maps it to a container image, which is what
|
||||
# the workflows expect: GitHub's own name, GitHub's own semantics — the job runs
|
||||
# in a disposable container, not on the machine.
|
||||
#
|
||||
# * the **label map** decides what `runs-on: ubuntu-latest` means. It is pinned
|
||||
# to catthehacker/ubuntu:act-24.04 because the workflows need two things from
|
||||
# the image: a node (Gitea's javascript actions — checkout, cache,
|
||||
# upload-artifact — run *inside* the job container) and Python 3.12, which
|
||||
# the backend's `requires-python` insists on. Ubuntu 24.04 ships 3.12.
|
||||
# * the **docker socket**, mounted into job containers so the `docker` workflow
|
||||
# can build and push an image. That is a real privilege handed to CI; it is
|
||||
# also the normal arrangement when Gitea and its runner are the same box as
|
||||
# the deployment.
|
||||
# It replaced a *host*-mode runner on the same box (`ubuntu-latest:host`), where
|
||||
# every job ran directly on the server as the `act_runner` user. That is why the
|
||||
# workflows' `apt-get install` steps failed: nothing could be installed, and had
|
||||
# it succeeded it would have been installing packages on the host.
|
||||
#
|
||||
# Setting it up:
|
||||
# Setting it up, and what each piece is for, is in
|
||||
# [`docs/gitea-runner.md`](docs/gitea-runner.md). The short version:
|
||||
#
|
||||
# 1. Gitea → Settings → Actions → Runners → "Create new runner", copy the token.
|
||||
# 2. GITEA_RUNNER_REGISTRATION_TOKEN=<token> docker compose -f docker-compose.ci.yml up -d
|
||||
# 3. Repository → Settings → Actions → Secrets, add:
|
||||
# REGISTRY_USER, REGISTRY_TOKEN — a Gitea user and token with
|
||||
# package:write, for the registry
|
||||
# KADENCE_KEYSTORE_BASE64 — base64 -w0 of your keystore
|
||||
# KADENCE_KEYSTORE_PASSWORD, KADENCE_KEY_ALIAS, KADENCE_KEY_PASSWORD
|
||||
# Without the keystore secrets the APK job still runs and produces an
|
||||
# unsigned-for-release (debug-signed) artifact rather than failing.
|
||||
# mkdir -p /opt/gitea-runner && cd /opt/gitea-runner
|
||||
# # copy this file as docker-compose.yml and deploy/act-runner.yaml as config.yaml
|
||||
# printf 'GITEA_RUNNER_REGISTRATION_TOKEN=%s\n' "<token from Gitea>" > .env
|
||||
# chmod 600 .env
|
||||
# docker compose up -d
|
||||
#
|
||||
# Gitea itself needs `[actions] ENABLED = true` in app.ini, and
|
||||
# `DEFAULT_ACTIONS_URL = github` so `actions/checkout@v4` can be resolved.
|
||||
# The registration token is needed **once**: after the first start the runner has
|
||||
# its own permanent token in `./data/.runner` and the one in `.env` is dead.
|
||||
services:
|
||||
runner:
|
||||
image: gitea/act_runner:0.2.11
|
||||
image: gitea/act_runner:0.3.1
|
||||
container_name: gitea-runner
|
||||
restart: unless-stopped
|
||||
|
||||
environment:
|
||||
GITEA_INSTANCE_URL: ${GITEA_INSTANCE_URL:-https://git.timka.su}
|
||||
GITEA_RUNNER_REGISTRATION_TOKEN: ${GITEA_RUNNER_REGISTRATION_TOKEN:?set this to the token from Gitea}
|
||||
GITEA_RUNNER_NAME: ${GITEA_RUNNER_NAME:-kadence-runner}
|
||||
GITEA_RUNNER_LABELS: ubuntu-latest:docker://catthehacker/ubuntu:act-24.04
|
||||
# Mounted into every job container, which is what lets the docker workflow
|
||||
# build an image. `valid_volumes` has to allow it explicitly.
|
||||
# Only read at first registration; harmless (and ignored) afterwards.
|
||||
GITEA_RUNNER_REGISTRATION_TOKEN: ${GITEA_RUNNER_REGISTRATION_TOKEN:-}
|
||||
GITEA_RUNNER_NAME: ${GITEA_RUNNER_NAME:-dockerized}
|
||||
# The label map: what `runs-on` may ask for, and what it gets.
|
||||
#
|
||||
# `act-24.04` and not something slimmer because the jobs need two things
|
||||
# from the image: a **node**, since Gitea's javascript actions (checkout,
|
||||
# cache, upload-artifact) run *inside* the job container, and **Python
|
||||
# 3.12**, which the backend's `requires-python` insists on and Ubuntu
|
||||
# 24.04 ships. A plain `ubuntu:24.04` has neither and every job would
|
||||
# fail at the first `uses:`.
|
||||
#
|
||||
# Labels are baked into `./data/.runner` at registration — changing this
|
||||
# line later does nothing on its own. See the guide.
|
||||
GITEA_RUNNER_LABELS: >-
|
||||
ubuntu-latest:docker://catthehacker/ubuntu:act-24.04,
|
||||
ubuntu-24.04:docker://catthehacker/ubuntu:act-24.04,
|
||||
ubuntu-22.04:docker://catthehacker/ubuntu:act-22.04
|
||||
CONFIG_FILE: /config/config.yaml
|
||||
|
||||
volumes:
|
||||
- runner-data:/data
|
||||
- ./deploy/act-runner.yaml:/config/config.yaml:ro
|
||||
- ./config.yaml:/config/config.yaml:ro
|
||||
# The registration lives here. Delete `./data/.runner` and the runner
|
||||
# re-registers as a *new* one, leaving a stale entry in Gitea.
|
||||
- ./data:/data
|
||||
# The host's docker daemon, so a job can build and push an image. This is
|
||||
# a real privilege — root on the host, effectively — and the reason the
|
||||
# runner should not be registered at instance level on a box you do not
|
||||
# want CI to own. `config.yaml` passes it through to job containers.
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
|
||||
volumes:
|
||||
runner-data:
|
||||
networks:
|
||||
- runner
|
||||
|
||||
networks:
|
||||
# Job containers join this same network (`container.network` in config.yaml),
|
||||
# which is what makes the runner's built-in cache server reachable from them:
|
||||
# it advertises its own address, and on a separate network that address would
|
||||
# route nowhere. It is also why nothing here needs a published port.
|
||||
runner:
|
||||
name: gitea-runner
|
||||
Reference in new issue
Block a user