fix(web): stop dry-runs reporting a phantom bitborg-web restart #295
Inga granskare
Etiketter
Inga etiketter
area/backups
area/ci
area/control-panel
area/identity
area/infra
area/observability
area/payments
area/security
area/storage
area/web
blocked
needs-info
needs-triage
ready-for-implementation
type
bug
type
chore
type
docs
type
epic
type
feature
type
task
wontfix
Ingen milstolpe
Inget projekt
Inga tilldelade
1 deltagare
Notiser
Förfallodatum
Inget förfallodatum satt.
Beroenden
Inga beroenden satta
Referens
bitborg/bitborg-infra!295
Läser in…
Hänvisa till i nytt ärende
Ingen beskrivning angiven.
Ta bort grenen "fix/294-checkmode-phantom-web-restart"
Borttagning av en gren är permanent. Även om den borttagna grenen kan fortsätta existera en kort tid innan den faktiskt tas bort, kan det INTE ångras i de flesta fall. Vill du fortsätta?
Closes #294. Two lines of
check_mode: false, plus the comments explaining why.How this surfaced
Gating the docs-only #293 through the apply procedure. The dry-run came back
changed=1, whichunder this repo's own rule — account for every
changedtask, because that is how amerged-but-unapplied PR gets caught — had to be explained before the gate could be cleared.
It was not drift. It is a permanent artefact of the dry-run itself.
Mechanism
The restart decision is computed from two
commandprobes.--checkdoes not run commands, andcrucially it does not register "no data" in their place — it registers plausible success:
Confirmed empirically with a throwaway probe playbook against the host rather than inferred from
the docs, because the two fabricated fields break the role in opposite directions:
stdout: ""can never equalgit.gitborg.se/gitborg/gitborg-web:latest, so(web_running_image.stdout … ) != (web_image ~ ':' ~ web_image_tag)is always true and theexpression resolves to
state: restarted. Hence achangedon every dry-run that a real rundoes not perform.
rc: 0means everywhen: web_image_present.rc == 0guard takes the success branchregardless. So a dry-run silently assumes the image is published even when it is not — which is
exactly the condition "Note when the bitborg-web image is not yet published" exists to report.
That one is a dry-run that cannot warn you, the quieter half of the same bug.
Worth recording because the obvious reading is wrong: the existing
| default('')onstdoutisnot what rescues or breaks this. The value is registered as
""outright, so the default neverfires. Anyone reasoning from the guard alone would conclude the task is already protected.
Why these two tasks and not the third
Both probes are strictly read-only —
podman image existsandpodman container inspect— andalready carry
changed_when: falseandfailed_when: false. Running them under check modeobserves the host without touching it, which is precisely what a dry-run is for.
systemctl --user reset-failedsits in the same block and is deliberately left skipped. Itclears latched systemd state; that is a mutation, and a dry-run must not perform it. The point is
not "make check mode run more tasks", it is "let check mode read, never write".
Verification
Scoped
--check --diff --limit gitborg-prod --tags web, before → after:skippingok(really running)skippingok(really running)changedokchanged=1changed=0Independently corroborated before changing anything: the running container was already on
git.gitborg.se/gitborg/gitborg-web:latest, matchingweb_image:web_image_tag— so no restart wasever pending and
changed=0is the truthful answer, not a suppressed one. This is the distinctionthat mattered: the goal was to make the dry-run honest, not to silence it.
ansible-lint roles/web/passes on the production profile;site.yml --syntax-checkclean.Note on applying
No apply is needed for this PR. It changes only what
--checkreports, and the host is alreadyconverged — the full dry-run that started this was
ok=237 changed=1 failed=0, whose singlechangedis the artefact being removed here.Follow-up
Left in #294: other roles were checked and none share the drift-comparison shape, so nothing else
reports a phantom change today. The general trap is broader though — any
when:or stateexpression derived from a
commandregister is reading fabricated values under--check— so asweep for read-only probes that want
check_mode: false, plus a line in the apply procedure, wouldstop the next person re-deriving this from scratch.
fix(web): stop dry-runs reporting a phantom gitborg-web restarttill fix(web): stop dry-runs reporting a phantom bitborg-web restart