Commit Graph

5 Commits

Author SHA1 Message Date
Marcel
fe1451f570 ci(smoke): pin curl to 127.0.0.1 via --resolve
The smoke step previously curled the public hostname unconditionally,
which routes the runner's request via DNS → router → back into the same
host. Many SOHO routers do not implement hairpin NAT (or do so only after
a firmware update), so the deploy may pass on day one and silently fail
on day 90.

--resolve "<host>:443:127.0.0.1" pins the hostname to the runner's
loopback while keeping SNI on the public name (so the cert validates
correctly and the Caddy vhost block matches). The smoke test now
verifies that the Caddy-on-the-same-host is serving the right
hostname end-to-end, with no router dependency.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-11 13:12:05 +02:00
Marcel
f2ec81547b ci(deploy): add --pull to docker compose build for CVE pickup
Without --pull, the host's Docker layer cache wins: if a CVE drops in
node:20.19.0-alpine3.21 / postgres:16-alpine and the vendor re-publishes
the same tag, the runner keeps serving the cached layer until the cache
is manually cleared — a silent supply-chain blind spot.

Adding --pull to both `compose build` invocations costs a single
re-pull per run and lifts the base-image patch lag from "next host
prune" to "next nightly".

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-11 13:10:59 +02:00
Marcel
83565c6bb5 docs(ci): document workflow operational assumptions
The two deploy workflows make two non-obvious assumptions that future
maintainers should not have to rediscover by reading the diff:

  1. Single-tenant self-hosted runner — the .env.* file lands on disk
     during the deploy and is cleaned up unconditionally. Multi-tenant
     usage would require switching to stdin-piped env input.

  2. Host docker layer cache is authoritative — there is no
     actions/cache directive; a host-level `docker system prune` will
     cold-start the next build.

Both notes added as block comments at the top of each workflow.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-11 12:06:48 +02:00
Marcel
a91a3e1f61 feat(ci): smoke test production deploy after up --wait
Mirrors the nightly.yml smoke step against archiv.raddatz.cloud. Catches
the same three failure modes (Caddy not reloaded, DNS missing, HSTS
dropped, /actuator block bypassed) on the prod path.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-11 12:05:41 +02:00
Marcel
334b507476 feat(ci): add release production deploy workflow
Fires on `v*` tag push. Tags the built images with the git tag so
rollbacks are a one-liner (TAG=<previous> docker compose ... up -d).

`up -d --wait` blocks until every service healthcheck reports
healthy; a bad release fails the workflow rather than crash-looping
silently. The .env.production file containing all Gitea secrets is
removed in `if: always()` after the deploy step.

Refs #497.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 21:56:37 +02:00