Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 13 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -190,24 +190,28 @@ jobs:
cache: npm

- name: Install dependencies
# `npm ci` triggers the `postinstall` hook (`npx prisma generate`),
# so the Prisma client is already regenerated against the current
# schema before the build step runs.
run: npm ci

- name: Generate Prisma client
run: npm run db:generate

- name: Build site
run: npm run build

- name: Deploy to Netlify (prod)
# --skip-functions-cache forces a fresh function bundle so the
# `--build` runs `netlify build` first, which pulls the Netlify
# project env vars (VITE_ANALYTICS_*, VITE_POSTHOG_*, VITE_GOOGLE_*,
# SITE_URL, etc.) into the Vite build process. Without this flag we
# would run `npm run build` here with no VITE_* values in scope and
# silently ship a bundle where analytics, OAuth visibility, and any
# other frontend env-driven feature is empty. Source of truth for
# those values stays in Netlify's project env.
#
# `--skip-functions-cache` forces a fresh function bundle so the
# deployed Prisma client always matches the current schema. The
# earlier deploy-race incident happened because Netlify reused a
# cached function bundle generated under a stale schema.
run: |
npx -y netlify-cli@latest deploy \
--prod \
--dir dist \
--functions netlify/functions \
--build \
--skip-functions-cache \
--message "ci: ${GITHUB_SHA::7} (${GITHUB_REF_NAME})"

Expand Down
6 changes: 4 additions & 2 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -760,7 +760,7 @@ Pipeline contract (`.github/workflows/ci.yml`):
| `check-production-migrate` | push to `main` | gates the migrate job on `PRODUCTION_DATABASE_URL` |
| `migrate-production` | push to `main` (when gated true) | `npm run db:migrate:deploy` + `npm run db:seed` |
| `check-production-deploy` | push to `main` | gates the deploy job on `NETLIFY_AUTH_TOKEN` + `NETLIFY_SITE_ID` |
| `deploy-production` | push to `main` (when gated true) | builds, generates Prisma client, `netlify deploy --prod --skip-functions-cache`, then smoke-checks the live API |
| `deploy-production` | push to `main` (when gated true) | `npm ci` (postinstall regenerates Prisma client), `netlify deploy --prod --build --skip-functions-cache` (Netlify build injects `VITE_*` project env into the bundle), then smoke-checks the live API |

Required GitHub secrets:

Expand All @@ -770,9 +770,11 @@ Required GitHub secrets:

Notes:

- `--build` is mandatory: it runs `netlify build` which loads the Netlify project env vars into the Vite build, so `VITE_*` values (PostHog key, analytics flags, Google client id, etc.) are baked into the deployed bundle. Without it we would silently ship a bundle with empty `VITE_*` values.
- `--skip-functions-cache` is mandatory: the older "Deploying functions from cache" path can publish a function bundle whose Prisma client predates the current schema.
- The deploy job runs a 5-attempt curl smoke check against `/api/tournaments?status=active,upcoming` and fails the CI run if the live API does not 200.
- Netlify's git auto-deploy remains enabled as a fallback. With `[build.environment] NODE_VERSION = "24.1.0"` pinned in `netlify.toml`, future image rollouts have one fewer variable; but the GitHub Actions path is the source of truth.
- Source of truth for both frontend (`VITE_*`) and backend runtime env vars is Netlify's project env, not GitHub Actions secrets. GitHub secrets only carry the values needed to authenticate the deploy itself (`NETLIFY_AUTH_TOKEN`, `NETLIFY_SITE_ID`) plus `PRODUCTION_DATABASE_URL` for the migrate job.
- Netlify's git auto-deploy is disabled (`stop_builds: true`) so the only deploy path is GitHub Actions. `[build.environment] NODE_VERSION = "24.1.0"` is still pinned in `netlify.toml` for defence in depth if auto-deploys are ever re-enabled.

### Destructive Migrations And The Deploy Race

Expand Down
Loading