make prod ansible check fails if dest dir doesn't exist #50
Labels
No labels
needs-info
needs-triage
ready-for-agent
ready-for-human
wontfix
needs-info
needs-triage
ready-for-agent
ready-for-human
review/merge-ready
review/needs-fix
review/needs-human
review/needs-review
wayfinder:grilling
wayfinder:map
wayfinder:prototype
wayfinder:research
wayfinder:task
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
olympus/infra-forge#50
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
make prod(andmake pre) stop at the service step. TheserviceTarget rehearses withansible-playbook --check --diffbefore the real run (Makefile:266-271), and the check itself fails on any Guest that has not been converged, so the service is never applied.Reproduced live on fresh PRE (LXC 142):
--checkexitsfailed=1:The Prod Guest has also never had the
forgejo_mcprole applied (/srv/forgejo-mcpabsent), so this is the normal firstmake prod, and everymake prerehearsal (PRE is created fresh each time). It is not an edge case — it is the default path.Root cause
Check mode makes first-class steps no-ops that later steps depend on, and several modules do not tolerate their input being absent even under
--check:file: state=directoryreportschanged, creates nothing.get_urlfails when itsdest's parent directory is absent.unarchivefails when itssrc(the archive) is absent;copywithremote_srcwhen its source is absent.systemd: state=started/restartedfails on a unit file that was never rendered (Could not find the requested service …: host).become_user: postgresfails before reaching any module when the apt install that creates the user was check-skipped:Unprivileged become user would be unable to read the file.uriandwait_forare unaffected — Ansible auto-skips modules with no check-mode support. On a converged Guest none of this fires: every input exists, the check previews, and the run is unchanged.Reproduced live on fresh PRE, in order — the
forgejorole fails first, beforeforgejo_mcpruns:forgejo : download the pinned release binary—/srv/forgejo/binmissing.forgejo : ensure the service role exists—postgresuser absent (check-skipped install).forgejo_mcp : fetch the pinned release archive—/srv/forgejo-mcp/releasesmissing.forgejo_mcp : enable and start the serviceand itsrestart forgejo-mcphandler — unit never rendered.Fix
Prefer declarative shapes; guard only what
--checkgenuinely cannot produce. Do not make the check mutate: the Makefile and runbook both state it writes nothing, so acheck_mode: false"create the tree even when checking" is not the fix.One
statper fact, read in check mode, used as the guard predicate:forgejo_tree(/srv/forgejo/binexists) around theget_urls, the twosystemdstarts, and the two handlers in theforgejorole.forgejo_pg(/usr/bin/psqlexists) around the fivepostgrestasks in theforgejorole.forgejo_mcp_tree(/srv/forgejo-mcp/releasesexists) around the install block (§2), the start block (§4), and the handler inforgejo_mcp.Plus the declarative fold in
forgejo_mcp:unarchivestraight into{{ forgejo_mcp_home }}/binwithextra_opts: ["--strip-components=1"], deleting the separateinstall the binary the unit runscopy task and the intermediatereleases/<stem>/directory.Constraint to keep:
get_urlmust stay.unarchivehas nochecksumparameter (its own docs say to useget_urlwhen checksum validation is wanted), so fetching insideunarchivewould drop the pinned-sha256 verification the runbook records.get_urlis also the cache: it revalidates with a HEAD (no body) on later runs, whileunarchive-from-URL re-downloads the full ~5.7 MB on every run and every check (measured against a local server log).Acceptance criteria
--checkagainst a not-yet-converged Guest completesfailed=0and writes nothing to the Guest (both roles).forgejorole only) converges; stage 2 (site.yml, addingforgejo_mcp) converges on top; a re-run reports0 changed.--checkagainst a converged Guest previews the install unchanged (failed=0, nothing newly skipped).401to a credential-less request and403to an unlistedHost, on PRE.make prodreaches step 4's real apply on a fresh Guest instead of dying in its check.Evidence (live on PRE 142)
--check:failed=1withDestination /srv/forgejo/bin does not exist(pre-fix) →failed=0(post-fix), nothing written.changed=22; stage 2changed=7; re-runchanged=0; converged--checkfailed=0.POST http://10.12.0.142:8089/mcp→401; unlistedHost→403;forgejo,forgejo-runner,forgejo-mcpallactive.Out of scope
--check-must-mutate-nothing contract.get_url(see the constraint above).