Add 'RUN --mount=type=cache,target=/pnpm-store' to all 3 pnpm install
stages (builder/pwa-builder/production) with --store-dir /pnpm-store, plus
the '# syntax=docker/dockerfile:1' directive. Set DOCKER_BUILDKIT=1 on the
publish build step so the legacy builder can't break on the mount syntax.
sharing=locked because builder and pwa-builder run in parallel.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add paths-ignore ['.gitea/**', '.planning/**'] to publish.yml's push
trigger. Doc/CI-only pushes to main (planning docs push straight to main;
workflow edits merge via PR) produce a byte-identical image (.dockerignore
already excludes .planning), so the build + :latest re-push was wasted.
paths-ignore skips only when every changed file matches; mixed code+docs
pushes still publish.
WR-02: capture docker run exit directly (not the piped head exit) so a
chatty booting image can't SIGPIPE to 141 and false-PASS; require the
FATAL guard marker in output as a positive assertion.
WR-05: strip comment lines and use anchored fixed-string (grep -qF)
matching so a commented-out rule can't satisfy the hygiene check and
patterns aren't treated as regexes.
- Static assertions step: verifies .dockerignore exists, covers all forbidden
patterns (.env, node_modules, apps/api/scripts, .git, .planning, apps/api/tests,
apps/pwa/e2e), and --target production is still pinned in publish.yml (T-16-19)
- Boot-smoke step: runs freshly-built sha_tag image with NODE_ENV=production +
DEV_AUTH_BYPASS=true; fails if image starts (EXIT==0) or times out (EXIT==124),
passes on any other non-zero exit — proves D-08 guard fires in shipped image (T-16-18)
- Both steps ordered after build and before push; a hygiene failure blocks publish (T-16-20)
- Separate 'Build and push' into 'Build production image' (build only) and 'Push image' steps
- Creates insertion point between build and push for hygiene assertions (Task 2)
- Preserves --target production, Dockerfile path, both tags, and root context
- WR-04 immutable-tag-first push ordering preserved in push step
- Replace "three required checks (CI / fast-checks, CI / api, CI / harness)"
with the new gating surface: CI / fast-checks + CI / gate
- Note that CI / api and CI / harness are conditionally skipped on doc-only PRs
and gated via the always-running CI / gate aggregate
- Comment-only change; no job/step/env/trigger modified
- Create .gitea/workflows/publish.yml (push-to-main only, name=Publish)
- Strip publish job, push trigger, and MILESTONE env from ci.yml
- Eliminates orphaned CI / publish (pull_request) status on PRs
- Preserves all three required PR status contexts unchanged