fix(deploy): prevent Next.js chunk version skew
Independent Staging Quality Gate / validate (push) Successful in 13m28s
Independent Staging Quality Gate / publish (push) Successful in 10m14s

This commit is contained in:
Jesse_Chen
2026-08-16 09:09:27 +08:00
parent 7b620c7a2e
commit 8ddcef4cf1
6 changed files with 42 additions and 2 deletions
+9
View File
@@ -156,6 +156,15 @@ Gitea is the primary source repository and Actions control plane. Gitea automati
`Independent Staging Quality Gate` runs for relevant `pull_request` paths, pushes to `staging`, and `workflow_dispatch`. It validates the Python/database/frontend contract; only a successful push to `staging` publishes the API/web images and a run-bound artifact containing their `sha256` digests plus the allowlisted controller bundle. The publish job rechecks the current staging head and dispatches `.gitea/workflows/deploy-staging.yml` from `refs/heads/staging` with the exact SHA and source gate run ID. The deploy workflow waits for that gate's success, validates the artifact against the full 40-character commit, and deploys digest references rather than trusting discoverability tags.
Every Web image build must pass that same full 40-character commit as the Docker
build argument `NEXT_DEPLOYMENT_ID`. Next.js embeds it during `next build`, adds
the deployment marker to rendered documents and static asset requests, and can
replace a stale client-side navigation with a full navigation when a release
changes underneath an already-open browser tab. Never omit it, substitute a
branch name, or set it only as a runtime environment variable: doing so can
leave users on an old client runtime that fails to load the new release's
immutable chunks.
The staging env file must include these non-secret selectors so Compose cannot fall back to production paths:
```dotenv
+3 -1
View File
@@ -11,9 +11,11 @@ COPY frontend/scripts ./scripts
COPY frontend/db ./db
COPY frontend/supabase/migrations ./supabase/migrations
ARG NEXT_DEPLOYMENT_ID
ARG NEXT_PUBLIC_SUPABASE_URL
ARG NEXT_PUBLIC_SUPABASE_ANON_KEY
ENV NEXT_PUBLIC_SUPABASE_URL=${NEXT_PUBLIC_SUPABASE_URL} \
ENV NEXT_DEPLOYMENT_ID=${NEXT_DEPLOYMENT_ID} \
NEXT_PUBLIC_SUPABASE_URL=${NEXT_PUBLIC_SUPABASE_URL} \
NEXT_PUBLIC_SUPABASE_ANON_KEY=${NEXT_PUBLIC_SUPABASE_ANON_KEY}
COPY SKILL.md /app/SKILL.md
COPY assets /app/assets