Gating only the push was not enough. This runner builds on the host's Docker daemon — the same daemon the
live container runs on — so `docker build -t …:latest` IS a deployment: Watchtower compares the running
container's image against :latest, finds they differ, and recreates the container from the locally built
image.
That is not hypothetical. The PR builds for this branch deployed unmerged code to itsthevine.com several
times this evening, and each time Watchtower's next pull of the older registry :latest reverted it, so the
site flapped between the two. One of those deploys ran V4 against the production database, which is why
the wedding-row correction had to be a new migration rather than an edit to V4.
A PR now builds pr-<number>, which nothing watches; Trivy scans whatever was built; the push step is
unchanged and still only runs off a PR. Nothing was lost — 40 products, 6 categories and 2 enquiries are
all present, and the old image tolerates the newer schema (it warns that the schema is ahead of its
migrations and carries on).
The other five apps on the platform share this workflow and this daemon, so they have the same hole —
including for Renovate's PRs, which build before they automerge. Not touched here; each needs the same
three lines and its own green run.
Run the workflow on pull_request too, so tests + build + Trivy must pass before main can be
merged (branch protection requires this check). Push the image only on a real push to main —
never from a PR. Also standardises the workflow across all apps (three had drifted).
act_runner mounts it at the full repo path (/workspace/Owner/repo), not at /workspace, so
the previous lookup found nothing and the step refused to run — correctly, but for the
wrong reason.
The image build runs 'mvn -DskipTests', and the workflow was only build -> Trivy -> push, so
no app test has ever run in CI. Only Trivy gated a merge. ContactControllerTest had been
broken since platform 0.1.6 and nothing noticed; the platform contract tests added in 0.1.9
were not running either, which defeated their purpose.
They cannot run inside 'docker build' — Testcontainers needs a Docker daemon and a build has
none. Maven runs as a sibling container instead, mounting the workspace volume act_runner
gave this job (discovered from our own container rather than guessed) and sharing the host
network so published test ports are reachable as localhost.
Fails loudly if the volume cannot be found, rather than quietly skipping the tests, which
would recreate exactly the problem this fixes.
Replaces the Next.js app. Same site, same look; the parts that were decisions rather
than markup now live in Java.
- catalogue, curated order, category filter and image URLs move from a TypeScript array
into Postgres behind /api/products and /api/categories
- contact form uses the shared platform-starter-contact: validate, RECORD, send, then
fan out to n8n. Recording first means a relay outage costs a notification, not an enquiry
- PageMetaController rewrites title/description/OG per route, replacing what Next's SSR
gave crawlers and link-preview scrapers
- 50MB of photos leave the repo for the MinIO bucket, re-encoded to webp (14MB) with EXIF
(including phone GPS) stripped
- fixes a catalogue typo: 'Strawberry Pie' was category 'Pies', which no filter matched, so
it was unreachable unless browsing All