Files
esh-pfi-infrastructure/stacks/hrafn/ci/README.md
T
vh b001d0cb2e feat(hrafn): author the CI deploy that replaces the hand-rsync path
hrafn was handed to infra-ops for uptime ownership with no CI deploy and
no commit provenance -- the image was always local/hrafn:v1 and the whole
working tree lived in the compose directory.

These two files fix both. They are authored here because infra-ops owns
hrafn's uptime, but they belong in vh/hrafn; claude-bot is not a
collaborator there, so they are handed to the repo holder rather than
committed directly.

- playbooks-deploy.yaml -> vh/hrafn playbooks/deploy.yaml
- gitea-workflows-deploy.yaml -> vh/hrafn .gitea/workflows/deploy.yaml

Design calls recorded in the README: the build context travels as one
tarball rather than per-file upload steps (nevermore's pattern fails open
when a new source file has no matching step), and the playbook refuses to
deploy unless .env exists at 0600 -- a guard prompted by it arriving 0644
with a live bearer token in it.

Validated with `elway --dry-run`, which caught a real interpolation bug
during authoring. No new Actions secrets needed.
2026-08-22 15:26:45 -07:00

2.5 KiB

hrafn CI deploy — authored here, lands in vh/hrafn

These two files replace hrafn's hand-rsync deploy. They are authored and version-controlled here because infra-ops owns hrafn's uptime, but they belong in the vh/hrafn repo — infra-ops has no write access to it (claude-bot is not a collaborator), so they are handed to the repo holder rather than committed directly.

file here destination in vh/hrafn
playbooks-deploy.yaml playbooks/deploy.yaml
gitea-workflows-deploy.yaml .gitea/workflows/deploy.yaml

Keep this copy in sync if the deployed version changes, or delete it once infra-ops has write access to vh/hrafn and the repo copy is canonical.

What the change buys

The pre-CI shape was: rsync a working tree into /opt/docker/compose/hrafn/, then docker compose build && up. Two problems, both fixed here.

  1. No provenance. The image was always local/hrafn:v1, so nothing on the box could answer "what commit is running". The image is now tagged with the commit SHA, and /opt/docker/compose/hrafn/.deployed records the SHA and timestamp. Rollback becomes a retag.
  2. The whole repo lived in the compose directory — tests/, docs/, ROADMAP.md, persistent-memory.md, CLAUDE.md. Only the build context ships now (Dockerfile, compose.yaml, pyproject.toml, README.md, src/).

Two design calls worth knowing

  • Tarball, not per-file upload steps. nevermore's playbook enumerates every source file as its own upload: step. That is explicit, but it fails open: add src/hrafn/newthing.py, forget the matching step, and the deploy silently ships without it. hrafn's build context travels as one archive so it cannot go partial.
  • .env is never deployed. It is host-owned, 0600, and holds the bearer token. The playbook refuses to run if it is missing or not 0600 — a guard added because the file arrived at 0644 on handoff.

Validation

The playbook parses and interpolates clean under elway's own parser:

scripts/elway ana-docker --playbook stacks/hrafn/ci/playbooks-deploy.yaml \
  --var hrafn_sha=abc123def456 --dry-run

That dry-run is worth running after any edit — it caught a real bug during authoring, where a comment containing a literal {{ ... }} identifier was picked up by elway's variable substitution and failed the run.

No new Actions secrets are required: DEPLOY_SSH_KEY and MGMT_REPO_TOKEN already exist at user scope on vh from the nevermore/task-board wiring.