feat(gitea-actions): build the CI job images in Gitea CI

The runner's job images were built by ansible into localhost/ only, so the
nightly CI prune deleted them and every idle stretch ended with CI failing in
under a second on `docker pull localhost/gitea-ci:latest` until someone re-ran
the role and waited out a rebuild. The previous commit moved them to the Gitea
registry; this moves the *build* off the deploy path entirely.

- .gitea/workflows/ci-images.yml builds files/Containerfile.* and pushes to
  git.debyl.io/gitbot/. Per-image change detection, so an ESP-IDF pin bump does
  not rebuild the other two; weekly schedule for base-image updates; a
  workflow_dispatch selector. PRs build under a throwaway :pr-<n> tag and drop
  it -- the build lands in the live runner's store, and act_runner will not
  re-pull a tag it already has, so a PR using the real tag would hand every
  later job on this host an unmerged image.
- The Containerfiles stop being ansible templates: their version vars are now
  --build-arg, read by the workflow out of the same defaults/main.yml the role
  interpolates, so CI and ansible build the same bytes from one set of pins.
- LABEL io.debyl.ci-base moves into each Containerfile so neither builder can
  forget the prune exemption; the workflow re-checks it before pushing.
- roles/gitea-actions pulls instead of building. gitea_ci_build_local=true
  restores the local build+push for seeding a cold registry or when CI is
  down -- the workflow that builds gitea-ci runs in gitea-ci.
- Lint .gitea/ alongside ansible/, and document the flow in the role README.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Bastian de Byl
2026-09-21 11:10:43 -04:00
co-authored by Claude Opus 5
parent a52209ff6a
commit d0e76bd6cf
11 changed files with 475 additions and 63 deletions
+13
View File
@@ -45,6 +45,7 @@ ansible/
│ ├── ssl/ # Legacy SSL management (deprecated - Caddy handles certificates automatically)
│ ├── github-actions/# CI/CD runner setup
│ ├── labelprint/ # 4x6 label print proxy (Raspberry Pi, CUPS/TSPL)
│ ├── gitea-actions/ # Gitea Actions runners + CI job images (see its README)
│ └── pihole/ # DNS filtering
└── vars/
└── vault.yml # Encrypted secrets
@@ -90,6 +91,7 @@ Tasks are tagged by service/component for selective deployment:
- `ddns` - Dynamic DNS tasks
- ~~`drone` - CI/CD tasks (decommissioned)~~
- `hass` - Home Assistant tasks
- `gitea-actions` - Gitea Actions runners and their CI job images
- Common infrastructure tags like `common`, `ssl`
## Configuration Files
@@ -122,6 +124,17 @@ Tasks are tagged by service/component for selective deployment:
- Falls back to its own rescue Wi-Fi AP at 192.168.4.1 when the home SSID is
unreachable
### Gitea Actions CI images
The runner's job images (`gitea-ci`, `gitea-ci-espidf`, `gitea-ci-platformio`)
are built by `.gitea/workflows/ci-images.yml` and published to the Gitea
container registry under `git.debyl.io/gitbot/`. The `gitea-actions` role only
pulls them - do NOT add build steps back to it. To change an image, edit
`ansible/roles/gitea-actions/files/Containerfile.*` (or a version pin in that
role's `defaults/main.yml`) and push to master; CI rebuilds only what changed.
See `ansible/roles/gitea-actions/README.md` for the registry rationale, the
prune-exemption label, and the bootstrap path when CI itself cannot build.
### Remote SSH Commands for Service Users
The `podman` user (and other service users) have `/bin/nologin` as their shell. To run commands as these users via SSH: