make service-check / make service: the service layer through the Makefile (#31) #40

Merged
pit merged 2 commits from hermes/31-make-service into main 2026-10-06 15:52:50 +00:00
Owner

Closes #31 (part of #27).

Summary

The service layer — the Ansible role that installs Forgejo and the runner — becomes two Targets, alongside the Guest Stack Targets from #29.

 Makefile
   guest-plan / guest          # the Guest Stack (#29)
+  service-check               # the service layer, rehearsed (--check --diff)
+  service                     # the service layer, applied
   fmt / validate / ssh

The layer has no OpenTofu state, so its gate is the check run rather than a saved plan — service-check is that run alone, service is the run then the playbook for real:

make service
  require_secret(ansible/vault-pass)                 # refuse before composing anything
  cd ansible
  ansible-playbook -i inventories/prod/hosts --check --diff site.yml
  ansible-playbook -i inventories/prod/hosts site.yml

The check command lives in one define (service_rehearsal), shared by both Targets, mirroring the existing require_secret idiom. The runbook's "the Makefile" section gains the Target table, and the read-only list gains service-check.

One limitation, documented rather than fixed: --check --diff is a rehearsal, not a full preview. The role mutates mostly through ansible.builtin.command (account creation, the runner registration), which Ansible skips under --check, so those changes do not appear in the diff. Fixing that means reworking the role — outside this ticket, and outside the epic's scope. The runbook says so.

Evidence

Before — no such Target:

$ make service-check
make: *** No rule to make target 'service-check'.  Stop.

After — composes against the Prod inventory, and refuses on a missing Vault before any playbook runs:

$ make -n service-check
cd ansible
ansible-playbook -i inventories/prod/hosts --check --diff site.yml

$ make service            # ansible/vault-pass absent
error: required secret file ansible/vault-pass is missing; composing no command.
make: *** [Makefile:90: service] Error 1

With the Vault in place and ansible-playbook stubbed, both Targets reach the stub with the right argv:

$ make service-check
STUB ansible-playbook argv: -i inventories/prod/hosts --check --diff site.yml

$ make service
STUB ansible-playbook argv: -i inventories/prod/hosts --check --diff site.yml
STUB ansible-playbook argv: -i inventories/prod/hosts site.yml

make help and a bare make list all eight Targets, aligned; make fmt is clean.

The check-mode limitation was confirmed against a real --check run: a copy task reports changed with a diff, a command task reports skipping with an empty register.stdout.

Merge Danger

Door: two-way — additive Targets and docs. Reverting the merge restores the runbook's raw-command path unchanged.

Blast Radius: none until run. The Makefile only composes commands; no OpenTofu state is read or written, and service-check mutates nothing. The one behaviour worth noticing is service running the check pass before the apply — a deliberate reading of the epic's gate for this layer (the epic fixes make prod as … edge → service → verify … and says the service layer's gate is the check run); drop it if you disagree and it becomes a one-line deletion.

Closes #31 (part of #27). ## Summary The service layer — the Ansible role that installs Forgejo and the runner — becomes two Targets, alongside the Guest Stack Targets from #29. ```diff Makefile guest-plan / guest # the Guest Stack (#29) + service-check # the service layer, rehearsed (--check --diff) + service # the service layer, applied fmt / validate / ssh ``` The layer has no OpenTofu state, so its gate is the check run rather than a saved plan — `service-check` is that run alone, `service` is the run then the playbook for real: ```text make service require_secret(ansible/vault-pass) # refuse before composing anything cd ansible ansible-playbook -i inventories/prod/hosts --check --diff site.yml ansible-playbook -i inventories/prod/hosts site.yml ``` The check command lives in one `define` (`service_rehearsal`), shared by both Targets, mirroring the existing `require_secret` idiom. The runbook's "the Makefile" section gains the Target table, and the read-only list gains `service-check`. **One limitation, documented rather than fixed:** `--check --diff` is a rehearsal, not a full preview. The role mutates mostly through `ansible.builtin.command` (account creation, the runner registration), which Ansible skips under `--check`, so those changes do not appear in the diff. Fixing that means reworking the role — outside this ticket, and outside the epic's scope. The runbook says so. ## Evidence Before — no such Target: ```text $ make service-check make: *** No rule to make target 'service-check'. Stop. ``` After — composes against the Prod inventory, and refuses on a missing Vault before any playbook runs: ```text $ make -n service-check cd ansible ansible-playbook -i inventories/prod/hosts --check --diff site.yml $ make service # ansible/vault-pass absent error: required secret file ansible/vault-pass is missing; composing no command. make: *** [Makefile:90: service] Error 1 ``` With the Vault in place and `ansible-playbook` stubbed, both Targets reach the stub with the right argv: ```text $ make service-check STUB ansible-playbook argv: -i inventories/prod/hosts --check --diff site.yml $ make service STUB ansible-playbook argv: -i inventories/prod/hosts --check --diff site.yml STUB ansible-playbook argv: -i inventories/prod/hosts site.yml ``` `make help` and a bare `make` list all eight Targets, aligned; `make fmt` is clean. The check-mode limitation was confirmed against a real `--check` run: a `copy` task reports `changed` with a diff, a `command` task reports `skipping` with an empty `register.stdout`. ## Merge Danger **Door:** two-way — additive Targets and docs. Reverting the merge restores the runbook's raw-command path unchanged. **Blast Radius:** none until run. The Makefile only composes commands; no OpenTofu state is read or written, and `service-check` mutates nothing. The one behaviour worth noticing is `service` running the check pass before the apply — a deliberate reading of the epic's gate for this layer (the epic fixes `make prod` as `… edge → service → verify …` and says the service layer's gate *is* the check run); drop it if you disagree and it becomes a one-line deletion.
pit force-pushed hermes/31-make-service from f3eb9807cb to 27035d314b 2026-10-06 15:52:04 +00:00 Compare
pit merged commit 5d18336a67 into main 2026-10-06 15:52:50 +00:00
pit deleted branch hermes/31-make-service 2026-10-06 15:52:50 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
olympus/infra-forge!40
No description provided.