boma/docs/decisions/010-forgejo-ci.md

100 lines
3.8 KiB
Markdown
Raw Permalink Normal View History

# ADR-010 — Forgejo integration and CI
## Status
Accepted (2026-05-30)
## Context
boma's git host, container registry, and (planned) CI all run on a self-hosted
Forgejo instance at `forgejo.nyumbani.baobab.band` (SSH on 7577, HTTPS on 443). Both
humans and AI/automation interact with it. This ADR sets the principles so the
instance does not become undocumented click-ops drift, and so its credentials are
held to the same standard as the rest of the repo's secrets.
---
## What Forgejo provides here
- **Git hosting** — `origin` (push/pull over SSH; key-based, not token).
- **Container registry** — hosts the Molecule test image
(`forgejo.nyumbani.baobab.band/sjat/molecule-debian13`); see ADR-008.
- **Actions CI** — planned, not yet enabled (`has_actions: false`); trunk-based
pipeline per ADR-003 / ADR-008.
---
## Decision
### 1. API tokens are managed secrets, least-privilege
A Forgejo API token (PAT) is a secret and follows ADR-002: stored in **Vaultwarden**
(item `boma-forgejo-api`), fetched via `rbw get boma-forgejo-api` (run `rbw sync`
first if it was just added), **never** written to a file or pasted into chat. Tokens
are **least-privilege** — scoped to their purpose, never admin.
Note what does *not* need a token: git push/pull (SSH key), and Terraform state
(local — ADR-006). A token for CI / registry use needs only:
- `read:repository`
- `read:package`, `write:package` (pull/push the Molecule image)
### 2. Declarative-first, not click-ops
Forgejo configuration lives in the repo where possible:
- Actions workflows in `.forgejo/workflows/` (version-controlled).
- Repo/instance settings are codified or documented; changing them ad-hoc via the
API or UI is a **documented exception**, recorded when done — not the norm.
The point: the Forgejo instance must not become the kind of undocumented drift that
`/review-repo` exists to catch.
### 3. Automation boundary
Automation / AI **may**, via the API or CLI: read repo and CI state, manage the
container registry, run and inspect CI. It must **not**, without explicit human
direction: change instance/admin settings, delete repos or packages, or rotate
credentials.
---
## CI pipeline (planned)
Trunk-based, matching ADR-003 / ADR-008:
```
push to main → lint + Molecule → deploy staging → [manual gate] → deploy production
```
Runner: `act_runner` on `ubongo` (the control node — ADR-015), or a dedicated runner VM
later if CI load warrants a separate host. Actions is not yet enabled — see STATUS.md.
---
## What was ruled out
| Option | Reason |
|---|---|
| Terraform Forgejo HTTP state backend | Forgejo's `/raw/` API is read-only; state can't be written there. Local state instead (ADR-006). |
| Admin-scoped automation tokens | Unnecessary privilege; scope to `read:repository` + `read`/`write:package`. |
| Ad-hoc UI/API configuration as the norm | Becomes undocumented drift; codify or document instead. |
---
## Consequences
- The planned CI pipeline (see "CI pipeline (planned)") is trunk-based per ADR-003 /
ADR-008 — `push to main → lint + Molecule → deploy staging → [manual gate] → deploy
production` — running `act_runner` on `ubongo` (or a dedicated runner VM later if CI
load warrants); Actions is not yet enabled, so this remains future work tracked in
STATUS.md.
- Terraform state is not held in Forgejo: its `/raw/` API is read-only and cannot be
written, so local state is used instead (ADR-006) (see "What was ruled out").
- Automation tokens are scoped to `read:repository` + `read`/`write:package` rather
than admin, accepting the limits that least-privilege imposes on what automation can
do (see "What was ruled out").
- Instance/repo configuration must be codified or documented rather than changed
ad-hoc, to avoid the undocumented drift `/review-repo` exists to catch (see "What was
ruled out").