Commit Graph

1 Commits

Author SHA1 Message Date
Neo 2ae7352799 feat(release): adapt PrivacyLLC-Web's release.sh, and add the deploy half it deliberately omits
scripts/release.sh — publish. Bump, guards, build, verify the image's own
version label, push :vX.Y.Z and move :dev, commit last, tag.

Adapted, not copied. The arguments are PrivacyLLC's and were paid for there; the
mechanism is this project's, because almost none of it transferred. Three
differences, each a fact about this repository rather than a preference:

- It gates on verify.sh, not a test suite, because there is not one. The
  original refuses to release on a half-run 1,600-test run. This one says out
  loud that a build, a secret scan and a doc-header check are not tests and that
  nothing in the gate touched a route, a form or an API response.
- It moves :dev as well as publishing :vX.Y.Z, because Portainer stack 58
  follows :dev. That makes :dev a pointer and never evidence.
- It checks the public origin in three files, not one. The original passes its
  origin in as a build arg; here https://queuenorth.com is written out in
  src/lib/seo.js, src/components/SEO.jsx and scripts/prerender.js and is baked
  into every canonical URL, og:url, sitemap.xml and robots.txt. The guard asks
  whether the three still agree.

Why this was needed: publishing was `npm run docker:push` with the bump as a
separate thing to remember, and it was not remembered. package.json said 0.8.3
while four commits announced "batch 0.9.0" through "0.9.3", and NO image was
ever published for any of them — the registry's newest tag is v0.8.3.

No prune. The original has one; this project has published thirteen tags in its
life, deleting a published image is irreversible, and the one that matters is
whichever the container was created from — exactly what a newest-N rule gets
wrong.

scripts/deploy.sh — deploy, and do not build. The template's deploy.py builds,
pushes AND deploys; adopting it beside release.sh would mean two commands that
both build, a second image for the same code, and two answers to "what is
running". This does only the missing half: point stack 58 at an already
published tag, having taken a verified backup first.

Its most important guard is not the obvious one. Portainer treats a stack PUT as
the whole desired state, so sending it without the stack's Env array would strip
twelve variables — the reCAPTCHA secret and the Zoho form tokens among them —
and the container would come back HEALTHY while quietly capturing no leads. It
reads them, counts them, sends them back, and refuses outright if none.

Guards proven to refuse, not assumed: already-published tag, http origin,
trailing-slash origin, the three origin constants drifted, dirty tree, bad flag,
unpublished deploy tag, missing Portainer key, wrong stack id.

One real bug found and fixed while testing: the image-line rewrite used
`python3 -` with a heredoc while also piping the stack file to stdin, so python
tried to execute the YAML.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 02:49:03 -05:00