hive-ci-register.service now runs unconditionally on every boot (not just when .runner is absent). Before fetching a registration token it validates existing .runner credentials via the forge admin API: - 200: runner still registered, write dummy token and exit - 404: runner deleted from forge, purge .runner and re-register - 000: forge unreachable, keep credentials (runner surfaces the error) - other non-200 or malformed .runner: purge and re-register Removes ConditionPathExists so stale credentials from a wiped forge no longer block the runner indefinitely. Updates docs/ci.md to match.
3.2 KiB
3.2 KiB
hive-ci: Forgejo Actions Runner
The hive-ci module runs a Forgejo Actions runner in a hive-ci nixos-container, executing CI jobs from .forgejo/workflows/ci.yml (e.g., nix flake check on every PR).
Operator bootstrap
Set services.hyperhive.ci.enable = true in the host NixOS config. That's it — no manual token provisioning.
Requirements:
services.hyperhive.forge.enable = truemust also be set (the runner registers against hive-forge).- Optional: tune
services.hyperhive.ci.name(runner name in forge admin panel),concurrency(parallel job capacity),labels(workflow targeting).
Container design
- Shared host netns: container reaches hive-forge at
http://127.0.0.1:<httpPort>(same as hive-gateway). - Non-ephemeral: runner credentials persist across restarts (written to container's stateDir on first registration, reused thereafter).
- Sandbox fallback: nspawn containers can't create user-namespaces, so nix's sandboxing would always fail. Module sets
nix.settings.sandbox-fallback = truein the container — nix builds run unsandboxed (safe because the container is already isolated). Seedocs/gotchas.md.
Auto-registration flow
hive-ci-register.service is a oneshot that runs on every boot before gitea-runner-hive.service. It handles both first-run registration and stale-credential detection.
Every boot
- Read the core admin token from
/run/hive-ci/core-token(bind-mounted from/var/lib/hyperhive/forge-core-token). - If
.runnerexists: validate the runner ID againstGET /api/v1/admin/runners/{id}using the core token:- 200: runner still registered — write dummy
TOKEN=placeholderand exit; runner reuses.runnercredentials. - 404: runner was deleted from forge (e.g. after a wipe) — delete
.runner, proceed to re-registration below. - 000 (forge unreachable): keep existing
.runner; the runner itself will surface the connectivity error. - other non-200: treat as stale, delete
.runnerand re-register. - malformed
.runner(noidfield): delete and re-register.
- 200: runner still registered — write dummy
- If
.runneris absent (first boot or purged above): fetch a fresh registration token fromGET /api/v1/admin/runners/registration-token. Retries for 30s in case forge is still starting. WritesTOKEN=<real>to/run/hive-ci/runner-token. gitea-actions-runnerreads the token, registers itself, and persists credentials to.runner. On subsequent boots step 2 validates these credentials and fast-paths past registration.
CI workflow
The single CI job is defined in .forgejo/workflows/ci.yml:
name: CI
on:
pull_request:
branches: ["**"]
jobs:
check:
name: nix flake check
runs-on: [hive-ci]
steps:
- uses: actions/checkout@v3
- name: check
run: nix flake check
This runs on every PR, executing all flake checks (treefmt, rustfmt, cargo test, cargo clippy, module evaluation). No --no-build: the checks' derivations are the canonical source of truth.
References
nix/modules/hive-ci.nix: runner configuration, auto-registration script, container setup..forgejo/workflows/ci.yml: workflow definition.docs/gotchas.md: nix sandboxing limitations in containers.