docs(adr): restructure ADR-003 to ADR-023 conformance

Add Status, a descriptive Context, a Decision umbrella over the existing
topical sections (demoted to ###), and a Consequences section assembled
from the ADR's already-stated rationale. No decision substance changed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
sjat 2026-06-10 14:50:03 +02:00
parent 6d7d27b03b
commit 40a428975a

View file

@ -1,6 +1,20 @@
# ADR-003 — Toolchain decisions
## Execution engine
## Status
Accepted (2026-05-30)
## Context
boma needs a defined, reproducible toolchain for running and testing its Ansible
monorepo: an execution engine, a Python environment, secrets handling, a testing
framework, linting, CI/CD, developer-ergonomics conventions, and a collections/roles
policy. This ADR records the choice made for each, together with the alternatives
weighed and why they were not adopted.
## Decision
### Execution engine
**Choice**: `ansible-core` (pip-installed, pinned version) + explicit `requirements.yml`
@ -12,7 +26,7 @@ that isn't needed in a maintained monorepo.
---
## Python environment
### Python environment
**Choice**: `python3-venv` (system Python on Debian 13) + pinned `requirements.txt`
@ -24,7 +38,7 @@ reproducible, and has no extra dependencies.
---
## Secrets
### Secrets
**Choice**: Ansible Vault (file-based, built-in)
@ -40,7 +54,7 @@ CLAUDE.md → Secrets).
---
## Testing
### Testing
**Choice**: Molecule with Docker driver (`molecule-plugins[docker]`)
@ -59,7 +73,7 @@ are needed.
---
## Linting
### Linting
**Choice**: `ansible-lint` + `yamllint` + `pre-commit`
@ -71,7 +85,7 @@ Config files: `.ansible-lint`, `.yamllint` in repo root.
---
## CI/CD
### CI/CD
**Choice**: Forgejo Actions (self-hosted at forgejo.nyumbani.baobab.band) + `act_runner`
@ -87,7 +101,7 @@ a dedicated runner VM later if CI load warrants a separate host.
---
## Developer ergonomics
### Developer ergonomics
**Choice**: `Makefile` as the single interface for all operations
@ -102,7 +116,7 @@ The venv is activated in the user's shell profile.
---
## Collections and roles policy
### Collections and roles policy
**No Galaxy roles.** All roles are written and maintained locally in `roles/`.
Galaxy roles introduce external state, versioning surprises, and implicit
@ -136,3 +150,24 @@ are removed. Each entry in `requirements.yml` must justify its presence.
| NixOS targets | Poor Ansible fit; all hosts standardised on Debian 13 |
Terraform is **adopted** for VM provisioning only (no DNS) — see `docs/decisions/006-terraform.md`.
## Consequences
Drawn from the rationale and trade-offs this ADR already states:
- Pinning `ansible-core` + an explicit `requirements.yml` and a plain pinned venv keeps
the control-node environment small and fully reproducible, at the cost of maintaining
the pins (per Execution engine / Python environment).
- Ansible Vault's whole-file encryption makes diffs unreadable regardless of layout, so
secrets are organised for human lookup (`vault.<service>.<key>`) rather than diff
ergonomics — the trade accepted against SOPS/age (per Secrets).
- The `Makefile` is the single interface: Claude Code and CI invoke the same targets, so
local and CI behaviour can't drift and collaborators need not know raw flags (per
Developer ergonomics).
- Collections are added only on demand, so `requirements.yml` stays minimal; this defers
`community.crypto` (use `openssl` CLI until a role needs certs) and `community.general`
(add only the specific sub-module needed) until a real need appears (per Collections
and roles policy).
- The heavier orchestration tools were declined for this scale, each with a named
revisit trigger — e.g. Semaphore if non-SSH operators must trigger runs, AWX-adjacent
tooling only if AWX/AAP is ever adopted (per "What was explicitly ruled out").