01 · A different kind of repo
No HelmReleases, no Kustomizations. Just roles.
An Ansible repository looks nothing like a Flux repository. The
Kubernetes-shaped agents parse nothing in it, so the failure mode
is not a wrong proposal. It is silent zero coverage: the repo
is scanned, nothing is found, and nothing is said.
Treating Ansible repositories as first-class targets starts with
admitting that, and building lanes that understand them.
02 · What CI already does
Lint and plan on every MR. Apply every hour.
The typical setup: a merge request runs syntax-check,
ansible-lint and a --check --diff plan;
main applies on push and on a schedule. The scheduled apply is this
repo's reconciler, the Ansible equivalent of Flux.
The MR gate is good at what it checks. It structurally cannot
report its own reconciler dying.
03 · Watch the reconciler In development
OK, stale, red, or unknown. Never "probably fine".
A deterministic run-health check reads the scheduled runs and gives
one of four verdicts. Stale: no scheduled run in two
cadences. Red: the last K scheduled applies all failed.
Unknown: no token, an API error, or incomplete pages, and
unknown never reads as OK.
Thresholds are tuned by replaying the full run history, not by
waiting a week. Today it runs report-only; turning it into an issue
is on the roadmap.
04 · Read the run log In development
A PLAY RECAP is structured data.
A parser turns an ansible-playbook job log into facts:
plays, tasks, per-host results and the recap. In
--check mode, changed>0 is a genuine
drift signal against the live hosts.
It is honest about its ceiling: a run log cannot prove a named
resource exists, so it answers "can't tell", never "absent". The
parser is built; no production lane consumes it yet.
05 · CI hygiene Roadmap
The plan on this MR belongs to a different MR.
The plan step writes to a fixed /tmp/plan.txt on a
self-hosted runner whose /tmp survives between jobs.
The publish step runs if: always(). When this MR's
plan never ran, reviewers see yesterday's plan from someone else's
change.
That misleads reviewers and discloses diffs across merge requests.
It is also detectable from the workflow file alone.
06 · CI hygiene Roadmap
Green every hour, doing nothing every hour.
A guard step that finds a required secret missing sets
ready=false and lets the job finish green, "rather
than failing hourly". Every scheduled apply becomes a successful
no-op, and a run-health check that only reads the status says OK.
The rule flags the pattern; the fix is to fail loudly on scheduled
runs, or to read step outcomes and demote a skipped run to unknown.
07 · Role pins Roadmap
Versions live in role defaults, not in requirements.yml.
In practice the pins that matter sit in
roles/*/defaults/main.yml (*_version,
*_ref, image digests) and in the CI image's build
arguments. A deterministic lane reads them, looks up upstream
releases, and proposes the same evidence-based target the
Kubernetes upgrade lane uses.
08 · Failure triage Roadmap
When the playbook is the victim, not the cause.
A failed job's log tail is classified against known signatures: a
sealed Vault, a registry pull error, DNS. When the repo declares
the dependency, the failure is attributed to the repo that owns
it, and the proposal lands there. The
cross-domain story follows one such
failure all the way to a missing probe.
09 · The proposal
A small workflow fix, with the reason spelled out.
The fix is two lines: a per-run path and a guard on the publish
step. The MR explains the mechanism, shows the evidence from the
repo's own history, and warns that the MR itself triggers the
check job on the fleet. The full MR is below.