Template
Deploy from CI with Infisical and ship Payload changes as migrations
CI reads Infisical staging as the read-only convexmonorepo-ci machine identity, deploys the Convex functions, builds and pushes the image, and asks the VPS to redeploy. Payload schema changes now ship as migrations that production runs on startup; the baseline matches the production schema and is recorded as applied there. The local stack moves to its own ports and syncs the Convex runtime env, and the scripts pick up Infisical account switching, dev-kill and a cache-safe CI install.
This commit is contained in:
1 parent
f39376a887
commit
7d1884be41
23 files changed
+6235
-55
No files matched your search
@@ -7,8 +7,8 @@
|
||||
- `packages/backend/convex`: self-hosted Convex functions, schema, and auth.
|
||||
- `packages/ui`: shared shadcn-based UI components.
|
||||
- `tools`: shared ESLint, Prettier, Tailwind, TypeScript, and Vitest config.
|
||||
- Local development uses host-run apps, local Convex on ports 3210/3211, its
|
||||
own data volume, and Payload Postgres on port 5432. Convex does not use
|
||||
- Local development uses host-run apps, local Convex on ports 3240/3241, its
|
||||
own data volume, and Payload Postgres on port 5436. Convex does not use
|
||||
Postgres unless a cloned project explicitly enables the commented option.
|
||||
|
||||
## Protected and generated files
|
||||
@@ -29,8 +29,17 @@
|
||||
- Run `infisical login` and `infisical init` before local development.
|
||||
- Machine-generated values belong in `.local/<env>.generated.env`; never put
|
||||
the generated Convex admin key in shared Infisical.
|
||||
- CI uses Gitea-injected secrets or `CI_ENV_FILE` and must not call Infisical.
|
||||
- App code imports validated variables from `@/env`, never `process.env`.
|
||||
- CI reads `staging` through `scripts/ci-export-env.mjs`, logged in as the
|
||||
read-only `convexmonorepo-ci` machine identity (Gitea secrets
|
||||
`INFISICAL_CLIENT_ID` and `INFISICAL_CLIENT_SECRET`). `scripts/export-env`
|
||||
refuses to run in CI.
|
||||
- `staging` holds the production values that CI builds and deploys with.
|
||||
- If you are logged in to more than one Infisical account, put
|
||||
`INFISICAL_EMAIL=...` in `scripts/flags/infisical.env` (gitignored) and the
|
||||
scripts switch the CLI to that account before exporting.
|
||||
- Server code imports validated variables from `@/env`. Client components and
|
||||
`instrumentation-client.ts` import from `@/publicEnv`, which keeps zod out of
|
||||
the browser bundle. Never read `process.env` elsewhere.
|
||||
- Add cache-relevant variables to `turbo.json` `globalEnv`.
|
||||
|
||||
## Code and dependency rules
|
||||
@@ -52,10 +61,12 @@ bun dev:next # host Next + deploy/watch local Convex functions
|
||||
bun db:down # stop and preserve both data volumes
|
||||
bun db:down:wipe # remove both volumes, generated admin key, and seed marker
|
||||
bun db:sync:payload # refresh and apply the local Payload seed snapshot
|
||||
bun db:sync-env # re-push Infisical dev values into the local Convex env
|
||||
bun dev:kill # stop dev servers that survived a Ctrl-C
|
||||
```
|
||||
|
||||
Local URLs: app `http://localhost:3000`, Convex `http://localhost:3210`,
|
||||
dashboard `http://localhost:6791`, Payload Postgres `localhost:5432`.
|
||||
Local URLs: app `http://localhost:3000`, Convex `http://localhost:3240`,
|
||||
dashboard `http://localhost:6794`, Payload Postgres `localhost:5436`.
|
||||
Use `INFISICAL_ENV=staging bun dev:next` for staging services.
|
||||
|
||||
`db:sync:payload` is an explicit, destructive local operation. It validates a
|
||||
@@ -65,6 +76,37 @@ only under `.local/`, and never changes Convex or production data. Normal
|
||||
when `.local/payload-seed-state.env` is absent or stale. Do not store seed
|
||||
markers in Payload Postgres; schema push treats unmanaged tables as drift.
|
||||
|
||||
## Payload schema changes
|
||||
|
||||
Payload schema changes ship as migrations in `apps/next/src/migrations/`.
|
||||
Locally, Payload pushes schema edits straight into the localhost database. When
|
||||
a change is ready, run `bun with-env bunx payload migrate:create <name>` from
|
||||
`apps/next` and commit the generated files. Production runs pending migrations
|
||||
on startup (`prodMigrations` in `payload.config.ts`). Push only runs against a
|
||||
database on `localhost`: a push leaves a `dev` row in `payload_migrations`, and
|
||||
Payload's startup migration stops on a confirmation prompt when it finds one.
|
||||
For the same reason, a local production build against the local dev database
|
||||
hangs; point it at a database without that row.
|
||||
|
||||
## Analytics and bundle size
|
||||
|
||||
- Plausible (`NEXT_PUBLIC_PLAUSIBLE_SRC`, the per-site script URL) loads through
|
||||
a same-origin proxy under `/pa`, clear of Payload's `/api` routes. PostHog
|
||||
(`NEXT_PUBLIC_POSTHOG_KEY`, `NEXT_PUBLIC_POSTHOG_HOST`) loads after the page
|
||||
is idle through `/ingest`. Both stay off when their env is unset.
|
||||
- Session replay comes from PostHog. Sentry carries errors and traces only.
|
||||
- `packages/ui/src/index.tsx` holds re-exports only (`cn` and `ccn` live in
|
||||
`utils.ts`). With `optimizePackageImports` in `next.config.js`, each page
|
||||
loads only the UI modules it imports. Declaring anything in the index breaks
|
||||
that.
|
||||
|
||||
## Deployment
|
||||
|
||||
A push to `main` runs `.gitea/workflows/build-next.yml`: the quality gate, then
|
||||
`convex deploy` to production, then the image build and push, then
|
||||
`ssh [email protected] convexmonorepo` (the forced-command deploy on the VPS). A
|
||||
push to `main` is a production deploy.
|
||||
|
||||
## Validation
|
||||
|
||||
Use `bun typecheck`, never a production build for routine validation. The full
|
||||
|
||||
Reference in new issue
Block a user