feat(fixtures): regenerate example-app migration snapshots via fixtures:emit#764
Conversation
|
Important Review skippedReview was skipped as selected files did not have any reviewable changes. 💤 Files selected but had no reviewable changes (13)
⚙️ Run configurationConfiguration used: Path: .coderabbit.yml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (13)
You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughTightens the "never hand-edit" fixture rule and .gitignore, then regenerates example migration contracts (Mongo and Prisma-next) to a namespace-oriented storage/emit shape, updating emitted JSON/.d.ts, type aliases, index metadata, and migration fingerprints. ChangesFixture rules and tooling
MongoDB demo contract regeneration
Prisma-next demo contract regeneration
Estimated code review effort 🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
✨ Finishing Touches🧪 Generate unit tests (beta)
|
size-limit report 📦
|
@prisma-next/extension-author-tools
@prisma-next/mongo-runtime
@prisma-next/family-mongo
@prisma-next/sql-runtime
@prisma-next/family-sql
@prisma-next/extension-arktype-json
@prisma-next/middleware-cache
@prisma-next/mongo
@prisma-next/extension-paradedb
@prisma-next/extension-pgvector
@prisma-next/extension-postgis
@prisma-next/postgres
@prisma-next/sql-orm-client
@prisma-next/sqlite
@prisma-next/extension-supabase
@prisma-next/target-mongo
@prisma-next/adapter-mongo
@prisma-next/driver-mongo
@prisma-next/contract
@prisma-next/utils
@prisma-next/config
@prisma-next/errors
@prisma-next/framework-components
@prisma-next/operations
@prisma-next/ts-render
@prisma-next/contract-authoring
@prisma-next/ids
@prisma-next/psl-parser
@prisma-next/psl-printer
@prisma-next/cli
@prisma-next/cli-telemetry
@prisma-next/emitter
@prisma-next/migration-tools
prisma-next
@prisma-next/vite-plugin-contract-emit
@prisma-next/mongo-codec
@prisma-next/mongo-contract
@prisma-next/mongo-value
@prisma-next/mongo-contract-psl
@prisma-next/mongo-contract-ts
@prisma-next/mongo-emitter
@prisma-next/mongo-schema-ir
@prisma-next/mongo-query-ast
@prisma-next/mongo-orm
@prisma-next/mongo-query-builder
@prisma-next/mongo-lowering
@prisma-next/mongo-wire
@prisma-next/sql-contract
@prisma-next/sql-errors
@prisma-next/sql-operations
@prisma-next/sql-schema-ir
@prisma-next/sql-contract-psl
@prisma-next/sql-contract-ts
@prisma-next/sql-contract-emitter
@prisma-next/sql-lane-query-builder
@prisma-next/sql-relational-core
@prisma-next/sql-builder
@prisma-next/target-postgres
@prisma-next/target-sqlite
@prisma-next/adapter-postgres
@prisma-next/adapter-sqlite
@prisma-next/driver-postgres
@prisma-next/driver-sqlite
commit: |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
examples/prisma-next-demo/migrations/app/20260422T0720_initial/contract.prisma (1)
57-69: Bug and Feature intentionally omit primary keys (keyless tables)
examples/prisma-next-demo/migrations/app/20260422T0720_initial/contract.prismadefinesBugandFeaturewithout any@idor@@id, andstart-contract.jsonfor the related migrations representsBug/Featurewithfields/storageonly (noprimaryKey), unlike the keyed models (e.g.,User,Post,Task).
- Consider adding a short comment in the schema explaining the rationale for these keyless models/tables if this is intentional.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@examples/prisma-next-demo/migrations/app/20260422T0720_initial/contract.prisma` around lines 57 - 69, The Bug and Feature models in contract.prisma are defined without primary keys (keyless tables), which can be confusing; add a short explanatory comment above the model declarations (the model Bug and model Feature definitions) stating that these are intentionally keyless (e.g., read-only logs, denormalized views, or external-managed IDs) and why they lack `@id/`@@id so future readers and maintainers understand the rationale and the corresponding start-contract.json representation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@examples/mongo-demo/migrations/app/20260415_add-posts-author-index/migration.json`:
- Around line 2-3: The migration metadata file migration.json for
20260415_add-posts-author-index incorrectly lists identical "from" and "to"
contract hashes, which hides the index changes added by migration.ts (which
creates posts indexes authorId and { createdAt: -1, authorId: 1 }); investigate
and fix by regenerating the contract hash after applying the migration so the
"to" hash reflects the updated contract (ensure contract.prisma and
end-contract.json reflect the new indexes under
.storage.namespaces.__unbound__.entries.collection.posts.indexes), or update the
contract generation logic to include index changes so migration.json's "from"
and "to" differ appropriately.
---
Nitpick comments:
In
`@examples/prisma-next-demo/migrations/app/20260422T0720_initial/contract.prisma`:
- Around line 57-69: The Bug and Feature models in contract.prisma are defined
without primary keys (keyless tables), which can be confusing; add a short
explanatory comment above the model declarations (the model Bug and model
Feature definitions) stating that these are intentionally keyless (e.g.,
read-only logs, denormalized views, or external-managed IDs) and why they lack
`@id/`@@id so future readers and maintainers understand the rationale and the
corresponding start-contract.json representation.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: 938b728e-8187-408c-8284-a94c264ec497
📒 Files selected for processing (86)
.agents/rules/never-hand-edit-contract-fixtures.mdc.gitignoreexamples/mongo-demo/migrations/app/20260409T1030_migration/contract.prismaexamples/mongo-demo/migrations/app/20260409T1030_migration/end-contract.d.tsexamples/mongo-demo/migrations/app/20260409T1030_migration/end-contract.jsonexamples/mongo-demo/migrations/app/20260409T1030_migration/migration.jsonexamples/mongo-demo/migrations/app/20260409T1030_migration/migration.tsexamples/mongo-demo/migrations/app/20260415_add-posts-author-index/contract.prismaexamples/mongo-demo/migrations/app/20260415_add-posts-author-index/end-contract.d.tsexamples/mongo-demo/migrations/app/20260415_add-posts-author-index/end-contract.jsonexamples/mongo-demo/migrations/app/20260415_add-posts-author-index/migration.jsonexamples/mongo-demo/migrations/app/20260415_add-posts-author-index/migration.tsexamples/mongo-demo/migrations/app/20260415_add-posts-author-index/start-contract.d.tsexamples/mongo-demo/migrations/app/20260415_add-posts-author-index/start-contract.jsonexamples/prisma-next-demo/migrations/app/20260422T0720_initial/contract.prismaexamples/prisma-next-demo/migrations/app/20260422T0720_initial/end-contract.d.tsexamples/prisma-next-demo/migrations/app/20260422T0720_initial/end-contract.jsonexamples/prisma-next-demo/migrations/app/20260422T0720_initial/migration.jsonexamples/prisma-next-demo/migrations/app/20260422T0720_initial/migration.tsexamples/prisma-next-demo/migrations/app/20260422T0742_migration/contract.prismaexamples/prisma-next-demo/migrations/app/20260422T0742_migration/end-contract.d.tsexamples/prisma-next-demo/migrations/app/20260422T0742_migration/end-contract.jsonexamples/prisma-next-demo/migrations/app/20260422T0742_migration/migration.jsonexamples/prisma-next-demo/migrations/app/20260422T0742_migration/migration.tsexamples/prisma-next-demo/migrations/app/20260422T0742_migration/start-contract.d.tsexamples/prisma-next-demo/migrations/app/20260422T0742_migration/start-contract.jsonexamples/prisma-next-demo/migrations/app/20260422T0748_migration/contract.prismaexamples/prisma-next-demo/migrations/app/20260422T0748_migration/end-contract.d.tsexamples/prisma-next-demo/migrations/app/20260422T0748_migration/end-contract.jsonexamples/prisma-next-demo/migrations/app/20260422T0748_migration/migration.jsonexamples/prisma-next-demo/migrations/app/20260422T0748_migration/migration.tsexamples/prisma-next-demo/migrations/app/20260422T0748_migration/ops.jsonexamples/prisma-next-demo/migrations/app/20260422T0748_migration/start-contract.d.tsexamples/prisma-next-demo/migrations/app/20260422T0748_migration/start-contract.jsonexamples/prisma-next-demo/migrations/app/20260518T1701_namespaces_bookend/contract.prismaexamples/prisma-next-demo/migrations/app/20260518T1701_namespaces_bookend/end-contract.d.tsexamples/prisma-next-demo/migrations/app/20260518T1701_namespaces_bookend/end-contract.jsonexamples/prisma-next-demo/migrations/app/20260518T1701_namespaces_bookend/migration.jsonexamples/prisma-next-demo/migrations/app/20260518T1701_namespaces_bookend/migration.tsexamples/prisma-next-demo/migrations/app/20260518T1701_namespaces_bookend/ops.jsonexamples/prisma-next-demo/migrations/app/20260518T1701_namespaces_bookend/start-contract.d.tsexamples/prisma-next-demo/migrations/app/20260518T1701_namespaces_bookend/start-contract.jsonexamples/prisma-next-demo/migrations/app/20260605T1143_public_namespaces_bookend/contract.prismaexamples/prisma-next-demo/migrations/app/20260605T1143_public_namespaces_bookend/end-contract.d.tsexamples/prisma-next-demo/migrations/app/20260605T1143_public_namespaces_bookend/end-contract.jsonexamples/prisma-next-demo/migrations/app/20260605T1143_public_namespaces_bookend/migration.jsonexamples/prisma-next-demo/migrations/app/20260605T1143_public_namespaces_bookend/migration.tsexamples/prisma-next-demo/migrations/app/20260605T1143_public_namespaces_bookend/ops.jsonexamples/prisma-next-demo/migrations/app/20260605T1143_public_namespaces_bookend/start-contract.d.tsexamples/prisma-next-demo/migrations/app/20260605T1143_public_namespaces_bookend/start-contract.jsonexamples/prisma-next-demo/migrations/app/20260605T1145_mti_variant_link_columns/contract.prismaexamples/prisma-next-demo/migrations/app/20260605T1145_mti_variant_link_columns/end-contract.jsonexamples/prisma-next-demo/migrations/app/20260605T1145_mti_variant_link_columns/migration.jsonexamples/prisma-next-demo/migrations/app/20260605T1145_mti_variant_link_columns/ops.jsonexamples/prisma-next-demo/migrations/app/20260605T1145_mti_variant_link_columns/start-contract.d.tsexamples/prisma-next-demo/migrations/app/20260605T1145_mti_variant_link_columns/start-contract.jsonexamples/prisma-next-postgis-demo/migrations/app/20260512T1309_migration/contract.prismaexamples/prisma-next-postgis-demo/migrations/app/20260512T1309_migration/end-contract.d.tsexamples/prisma-next-postgis-demo/migrations/app/20260512T1309_migration/end-contract.jsonexamples/prisma-next-postgis-demo/migrations/app/20260512T1309_migration/migration.jsonexamples/prisma-next-postgis-demo/migrations/app/20260512T1309_migration/migration.tsexamples/prisma-next-postgis-demo/migrations/app/20260512T1309_migration/ops.jsonexamples/retail-store/migrations/app/20260513T0505_initial/contract.prismaexamples/retail-store/migrations/app/20260513T0505_initial/end-contract.d.tsexamples/retail-store/migrations/app/20260513T0505_initial/end-contract.jsonexamples/retail-store/migrations/app/20260513T0505_initial/migration.jsonexamples/retail-store/migrations/app/20260513T0505_initial/migration.tsexamples/retail-store/migrations/app/20260513T0505_initial/ops.jsonexamples/retail-store/migrations/app/20260513T0507_add_product_category_index/contract.prismaexamples/retail-store/migrations/app/20260513T0507_add_product_category_index/end-contract.d.tsexamples/retail-store/migrations/app/20260513T0507_add_product_category_index/end-contract.jsonexamples/retail-store/migrations/app/20260513T0507_add_product_category_index/migration.jsonexamples/retail-store/migrations/app/20260513T0507_add_product_category_index/migration.tsexamples/retail-store/migrations/app/20260513T0507_add_product_category_index/ops.jsonexamples/retail-store/migrations/app/20260513T0507_add_product_category_index/start-contract.d.tsexamples/retail-store/migrations/app/20260513T0507_add_product_category_index/start-contract.jsonexamples/retail-store/migrations/app/20260513T0508_backfill_product_status/contract.prismaexamples/retail-store/migrations/app/20260513T0508_backfill_product_status/end-contract.d.tsexamples/retail-store/migrations/app/20260513T0508_backfill_product_status/end-contract.jsonexamples/retail-store/migrations/app/20260513T0508_backfill_product_status/migration.jsonexamples/retail-store/migrations/app/20260513T0508_backfill_product_status/migration.tsexamples/retail-store/migrations/app/20260513T0508_backfill_product_status/ops.jsonexamples/retail-store/migrations/app/20260513T0508_backfill_product_status/start-contract.d.tsexamples/retail-store/migrations/app/20260513T0508_backfill_product_status/start-contract.jsonpackage.jsonscripts/regen-example-migrations.mjs
…es:emit
Example-app migrations carry on-disk contract snapshots
(`start-contract.*` / `end-contract.*`) that went stale silently when the
contract IR shape changed: nothing regenerated them, since only extension
migrations were covered by `pnpm migrations:regen`. A stale snapshot
surfaced only when a test deserialized it and tripped the serializer
validator (TML-2808 hit this on retail-store).
Give each example-app migration a live, re-emittable source: store the
migration's end-state schema as `contract.prisma` in its directory, then
regenerate the snapshots from it with the Prisma Next CLI. This is
repeatable for any future shape change with no per-change code, because
the emitter always produces current-shape output from schema source.
- `scripts/regen-example-migrations.mjs`: walks each example-app chain and
per migration emits `end-contract.*` from its `contract.prisma` (temp
config that reuses the example's real `prisma-next.config.ts` and
overrides only the schema source, so extensions / db / family stay
correct), copies predecessor end -> successor start, rewrites the
`migration.ts` `from:`/`to:` hash literals, re-emits `ops.json` /
`migration.json` via `tsx`, and biome-formats. Covers retail-store,
mongo-demo, prisma-next-demo, and prisma-next-postgis-demo.
- Wire into `fixtures:emit` via a `migrations:regen:examples` script, and
widen the `fixtures:check` glob to `{start,end}-contract.*` so stale
example snapshots fail the check the same way stale `contract.*`
fixtures do.
- Regenerate all four chains' snapshots to the current contract shape.
- Make the retail-store and mongo-demo baseline migrations load their
collection validators from `end-contract.json` instead of hardcoding
them, so re-emitted ops match the emitter's current validators
(including `additionalProperties: false`).
- Give prisma-next-demo's `0720_initial` foreign keys an explicit
`schema: 'public'`; without it the FK builder emits
`REFERENCES "undefined"` (tracked separately as a framework bug).
- `never-hand-edit-contract-fixtures`: the rule's "regenerate via
`pnpm fixtures:emit`" promise is now true for example migrations.
Refs: TML-2838
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Will Madden <madden@prisma.io>
…te-table refactor
Main's `planner-create-table-adopts-ddl-ast` refactor removed the standalone
`createTable` migration op; the prisma-next-demo initial migration still called
it. Now that `fixtures:emit` executes each example `migration.ts` (via
`migrations:regen:examples`), that surfaced as a load-time SyntaxError in CI.
Port the five `createTable(...)` calls to the base-class `this.createTable({...})`
method with `col()` / `fn()` / `lit()` / `primaryKey()` builders, and regenerate
the migration's `ops.json` / `migration.json` (rendered DDL is unchanged). Record
an incidental-diff declaration in the 0.12→0.13 upgrade instructions so
`check-upgrade-coverage` passes.
Refs: TML-2838
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Will Madden <madden@prisma.io>
7056e6c to
da92da8
Compare
c06b600 to
f90aa48
Compare
CI flakily failed with "Worker exited unexpectedly" while every test passed,
across the E2E, Integration, and packages Test jobs. The worker fork was
aborting natively inside V8:
# Check failed: jit_page_->allocations_.erase(addr) == 1
Every affected suite stands up @prisma/dev servers backed by PGlite (Postgres
compiled to WebAssembly). Repeatedly creating and tearing down those WASM
instances trips a bug in V8 PKU-based JIT write-protection (ThreadIsolation) —
the --memory-protection-keys feature, which only engages on Linux, so it never
reproduced on macOS.
Pass --no-memory-protection-keys to the test worker forks. The flag is
rejected in NODE_OPTIONS and vitest reads it from top-level test.execArgv (not
poolOptions.forks.execArgv, which it silently drops), and a root-config
execArgv does not cascade to project workers — so it has to be set on each
config that starts PGlite. The flag lives once as pgliteWorkerExecArgv in
@prisma-next/test-utils and is wired into every PGlite-backed suite. PGlite is
unaffected.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Will Madden <madden@prisma.io>
f90aa48 to
9f6c6f2
Compare
# Conflicts: # skills/upgrade/prisma-next-upgrade/upgrades/0.12-to-0.13/instructions.md
The PGlite WASM crash fix touches vitest configs under
packages/3-extensions/{postgres,supabase}. check-upgrade-coverage requires
the extension-author upgrade instructions to acknowledge any 3-extensions
substrate diff. This is test-harness only (no runtime/contract/public-API
change), recorded as an incidental diff.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Will Madden <madden@prisma.io>
What & why
Example-app migrations carry on-disk contract snapshots (
start-contract.*/end-contract.*) that went stale silently whenever the contract IR shape changed — nothing regenerated them, becausepnpm migrations:regenonly covered extension migrations. A stale snapshot surfaced only when a test happened to deserialize one and tripped the serializer validator (this is the trap TML-2808 hit on retail-store; its fix was a one-shot transform, explicitly not repeatable).The root cause was that intermediate migrations had no live source on disk to re-emit from. This PR fixes that directly: give each example-app migration a live, re-emittable source — store the migration's end-state schema as
contract.prismain its directory — then regenerate the snapshots from it with the Prisma Next CLI. It's repeatable for any future shape change with no per-change code, because the emitter always produces current-shape output from schema source.How to review (most of the diff is mechanical)
86 files, but the reviewable substance is small. The bulk is regenerated
{start,end}-contract.*/ops.json/migration.json— output of the new script, not hand-written.Read these:
scripts/regen-example-migrations.mjs— the chain walker. Per migration: emitend-contract.*fromcontract.prismavia a temp config that reuses the example's realprisma-next.config.tsand overrides only the schema source (so extensions / db / family stay correct by construction), copy predecessor end → successor start, rewrite themigration.tsfrom:/to:hash literals, re-emitops.json/migration.jsonviatsx, biome-format.package.json—migrations:regen:exampleschained intofixtures:emit(after the per-exampleemit, so the head emits from a freshsrccontract);fixtures:checkglob widened to{start,end}-contract.*..agents/rules/never-hand-edit-contract-fixtures.mdc— the rule's "regenerate viapnpm fixtures:emit" promise is now true for example migrations.*/contract.prismasources, and themigration.tschanges (hash literals + two validator refactors + one FK fix — see below).Scope: the four example apps with
app/chains — retail-store (mongo, 3), mongo-demo (mongo, 2), prisma-next-demo (postgres + pgvector, 6, incl. namespaces/MTI), prisma-next-postgis-demo (postgis, 1). Out of scope: pgvector/postgis seed namespaces (single migration,refs/head.json),multi-extension-monorepo(already covered by the extension regen), andprisma-next-demo/fixtures/*(hand-crafted, no live src).Two behavioural changes worth a closer look
0505_initial, mongo-demo): refactored to load collection validators fromend-contract.jsoninstead of hardcoding them, so re-emitted ops match the emitter's current validators (the current emitter addsadditionalProperties: false).0720_initialforeign keys now pass an explicitschema: 'public'. Without it, the FK builder emits invalidREFERENCES "undefined"."user"DDL. The explicit schema matches the convention the same example's MTI migration already uses. The underlying builder behaviour (emitting"undefined"when the reference schema is omitted) is a latent framework bug this work exposed — tracked separately, out of scope here.Verification
pnpm fixtures:emitis idempotent (run twice → no diff); after mergepnpm fixtures:checkis clean from a fresh tree.fixtures:checknow fails on a stale example{start,end}-contract.*and passes again after regen (demonstrated by hand-corrupting a snapshot).storageHashandprofileHashmatch a freshprisma-next contract emitofsrcfor all four examples; each non-headend-contract.jsonis byte-identical to the next migration'sstart-contract.json.pnpm test:packagesgreen (9923). Example suites: retail-store 55/55, mongo-demo 35/35, postgis 7 skipped (needs live PostGIS). prisma-next-demo has 2–3 pre-existing PGlite-contention flaky failures (verified against a pre-change baseline; unrelated to this PR and they don't read the snapshots).Refs: TML-2838
🤖 Generated with Claude Code
Summary by CodeRabbit