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
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ on:
workflow_dispatch:
inputs:
dist-tag:
description: "npm dist-tag. Empty = the version's canonical tag (next on the RC line, latest for stable). Pass latest explicitly to move latest onto an RC — that is the deliberate cutover act."
description: "npm dist-tag. Empty = latest, the canonical tag for every release since the 2026-08-25 cutover. Pass another tag (e.g. beta) for a hand-cut preview."
required: false
default: ""
type: string
Expand Down
16 changes: 8 additions & 8 deletions docs/oss/versioning.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ Prisma 8 ships as a release-candidate line ahead of `8.0.0` final: releases are

RC respins may include breaking changes until `8.0.0` final ships. There are no patch releases on the RC line — a fix ships as the next `rc.N`.

For the packages this repository's publish workflow ships (`prisma`, `@prisma/cli`, `@prisma/cli-engine`), **each release publishes under its line's canonical dist-tag**: RC-line versions under `next`, stable versions under `latest` (operator ruling 2026-08-12; supersedes the earlier "`latest` tracks the newest release, RC or stable"). A dist-tag moves only through a deliberately merged version-bump PR (or a manual `workflow_dispatch`); creating and merging the bump PR is the operator's explicit act. `latest` stays on the pre-8 CLI until the operator moves it deliberately. Existing installs are unaffected — lockfiles pin resolved versions, and nobody lands on the RC line without asking for `@next`.
For the packages this repository's publish workflow ships (`prisma`, `@prisma/cli`, `@prisma/cli-engine`), **every release publishes under `latest`, RC-line versions included** (operator cutover ruling 2026-08-25, executing rollout-plan step 5; supersedes the 2026-08-12 "RC under `next`" ruling). A dist-tag moves only through a deliberately merged version-bump PR (or a manual `workflow_dispatch`); creating and merging the bump PR is the operator's explicit act. Existing installs are unaffected — lockfiles pin resolved versions.

**The bare `prisma` name is what this discipline is for.** Its `latest` serves Prisma 7 (`7.9.1`) to everyone who types `npm install prisma`, so the v8 line lives on `next` until a deliberate cutover. The products' packages are all new — nobody is installing `@prisma/composer-cli` or `@prisma/orm-toolchain` expecting a version 7 — so they publish releases straight to `latest`, pre-release versions included, and this repository follows `latest` for them (operator ruling 2026-08-17).
**History of the bare `prisma` name.** Its `latest` served Prisma 7 (`7.9.1`) until the 2026-08-25 cutover, so the v8 RC line lived on `next` while it matured. The product-family packages (`@prisma/composer-cli`, `@prisma/orm-toolchain` and their siblings — not this repository's three) were never held back — all new names with no version-7 audience — so they always published releases straight to `latest`, pre-release versions included, and this repository follows `latest` for them (operator ruling 2026-08-17).

The transition onto the RC line is a one-time bump from the pre-8 base to `8.0.0-rc.1`; `pnpm bump-version` encodes it (a pre-8 stable base advances to `8.0.0-rc.1`, an RC base advances its counter).

Expand Down Expand Up @@ -39,11 +39,11 @@ This is enforced, not remembered: the conformance checks refuse to publish a rel

The npm registry exposes the CLI packages under these dist-tags:

- **`latest`** — what a bare `npm install` gets. It stays on the pre-8 CLI while the Prisma 8 RC line matures; moving it to 8.x is a deliberate operator act (dispatching the publish workflow with `dist-tag: latest`, or widening `releaseDistTag` when the RC line is ready), not a side effect of any routine release (operator ruling 2026-08-12). Once the line is stable, stable release bumps publish here.
- **`next`** — the Prisma 8 RC line (`8.0.0-rc.N`). A merged release PR on the RC line publishes here automatically.
- **`latest`** — what a bare `npm install` gets: the newest release, RC or stable. A merged release PR publishes here automatically (operator cutover ruling 2026-08-25; before it, `latest` stayed on the pre-8 CLI and the RC line lived on `next`).
- **`next`** — retired by the cutover: it froze at the last pre-cutover RC and the publish path no longer moves it (operator ruling 2026-08-25). Keeping it synced to `latest` was considered and dropped — re-pointing a tag on an already-published version cannot authenticate over OIDC, and npm has no token permission narrower than package write, so a standing sync would mean a standing publish-capable token. The operator re-points or removes the tag by hand (`scripts/cutover-dist-tags.sh`); text that says `prisma@next` should move to plain `prisma`.
- **`beta`** — reserved for hand-cut previews ahead of significant changes, published by dispatching the workflow with that dist-tag. Routine releases do not use this tag.

- **`dev`** — every routine push to `main` publishes `<base>-dev.<run>` here automatically (operator ruling 2026-08-13, superseding the earlier "no dev channel" ruling). The suffix derives from the workflow run number and is stamped ephemerally in CI, never committed, so release versions remain exactly what a commit says. The channel exists so a product's new version reaches a working CLI without a human: an auto-merging pull request moves the version, runs the full quality and conformance checks, and its merge ships the dev build. Today a daily scheduled run is what notices a product release; the immediate path needs a notification step in each product repository, which neither has yet. See [release automation](./release-automation.md). Only a real release — an `rc.N` bump under `next`, or moving `latest` — is a human act.
- **`dev`** — every routine push to `main` publishes `<base>-dev.<run>` here automatically (operator ruling 2026-08-13, superseding the earlier "no dev channel" ruling). The suffix derives from the workflow run number and is stamped ephemerally in CI, never committed, so release versions remain exactly what a commit says. The channel exists so a product's new version reaches a working CLI without a human: an auto-merging pull request moves the version, runs the full quality and conformance checks, and its merge ships the dev build. Today a daily scheduled run is what notices a product release; the immediate path needs a notification step in each product repository, which neither has yet. See [release automation](./release-automation.md). Only a real release — a merged `rc.N` bump publishing under `latest` — is a human act.

**Every** run of the publish workflow ships a dev build, including the one that cuts a release — the release publish is an additional half, not an alternative (operator ruling 2026-08-18). When they were alternatives, the release commit was the one merge to `main` that never reached the dev channel, so `dev` named an older version than the release until an unrelated commit landed. The dev build is published as its own version rather than by moving the `dev` tag, because OIDC trusted publishing authorises `npm publish` and nothing else.

Expand All @@ -68,7 +68,7 @@ This is by design. The alternatives cause silent problems:

[`scripts/set-version.ts`](../../scripts/set-version.ts) is what enforces lockstep: a single invocation walks every lockstep workspace `package.json` and writes the requested version (rewriting `workspace:` dependency pins to match). It is a maintainer's tool, invoked through `pnpm bump-version`; the publish workflow does not run it.

The publish workflow is **triggered by a change to the root `version`**: a push to `main` whose root `package.json` carries a different `version` than the previous tip is recognised as a release bump and ships that version under its canonical dist-tag — `next` on the RC line (the accompanying GitHub Release is marked pre-release), `latest` for stable. This is what makes "merge the release PR" the publish trigger; there is no separate dispatch step. Every push publishes a `dev` build; one that changes the version publishes a release as well (operator ruling 2026-08-18). Within a publish, `@prisma/cli-engine` goes first, then `@prisma/cli` (which depends on it), then `prisma`.
The publish workflow is **triggered by a change to the root `version`**: a push to `main` whose root `package.json` carries a different `version` than the previous tip is recognised as a release bump and ships that version under `latest` (the accompanying GitHub Release is marked pre-release on the RC line). This is what makes "merge the release PR" the publish trigger; there is no separate dispatch step. Every push publishes a `dev` build; one that changes the version publishes a release as well (operator ruling 2026-08-18). Within a publish, `@prisma/cli-engine` goes first, then `@prisma/cli` (which depends on it), then `prisma`.

**Nothing rewrites a `version` field outside a commit.** `set-version.ts` is run by `pnpm bump-version`, whose output a maintainer reviews and commits; the publish workflow never invokes it. That is what makes "the version is whatever `package.json` says" true rather than aspirational — CI has no way to ship a version no commit describes. It also keeps `pnpm-lock.yaml` honest: the lockfile records the `workspace:` specifiers that `set-version.ts` rewrites, so `bump-version` refreshes it in the same breath and the bump lands as one internally consistent commit.

Expand All @@ -81,9 +81,9 @@ Before anything reaches the registry, the workflow verifies the artifact it is a
The release cadence is one PR per release (on the RC line: one PR per `rc.N`). A maintainer:

1. **Runs the [`publish-npm-version` skill](../../skills-contrib/publish-npm-version/SKILL.md)**, which drives `pnpm bump-version` in a fresh worktree off `origin/main` and opens the release PR under real maintainer credentials (so CI runs on it normally). The script reads the root version committed at HEAD, computes the next release version (`8.0.0-rc.N` → `8.0.0-rc.N+1`), and writes it to every lockstep `package.json`. `bump-version` refreshes `pnpm-lock.yaml` itself, because the lockfile records the `workspace:` pins it rewrites and a stale one fails every later frozen install. Commit both and open a `chore(release): 8.0.0-rc.N+1` PR.
2. **Reviews and merges the PR.** This is the point where a human verifies the release is intended — merging the bump PR is the deliberate act that publishes. The resulting push to `main` carries the bumped root `version`, the publish workflow detects the change, publishes under the line's canonical dist-tag (`next` on the RC line, `latest` for stable), and creates a matching GitHub Release (marked pre-release on the RC line).
2. **Reviews and merges the PR.** This is the point where a human verifies the release is intended — merging the bump PR is the deliberate act that publishes. The resulting push to `main` carries the bumped root `version`, the publish workflow detects the change, publishes under `latest`, and creates a matching GitHub Release (marked pre-release on the RC line).

If the publish needs to be re-run (transient registry failure, etc.), a maintainer can dispatch the [`Publish to npm`](../../.github/workflows/publish.yml) workflow from `main` with the version's canonical dist-tag (`next` on the RC line, `latest` for stable) and `dry-run=false`; the workflow re-publishes the version currently committed at HEAD, and because the chosen tag matches the canonical one it also re-creates the GitHub Release if it is missing. This is the same path used to cut a hand-rolled `beta` (`dist-tag=beta`, no Release).
If the publish needs to be re-run (transient registry failure, etc.), a maintainer can dispatch the [`Publish to npm`](../../.github/workflows/publish.yml) workflow from `main` with `dist-tag: latest` and `dry-run=false`; the workflow re-publishes the version currently committed at HEAD, and because the chosen tag matches the canonical one it also re-creates the GitHub Release if it is missing. This is the same path used to cut a hand-rolled `beta` (`dist-tag=beta`, no Release).

## Procedure: validate publish changes

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "prisma-cli",
"version": "8.0.0-rc.9",
"version": "8.0.0-rc.10",
"private": true,
"engines": {
"node": ">=24"
Expand Down
4 changes: 2 additions & 2 deletions packages/cli-conformance/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@repo/cli-conformance",
"private": true,
"version": "8.0.0-rc.9",
"version": "8.0.0-rc.10",
"description": "Reusable conformance checks for the engine's consumers: import purity over built output, config-section validators that never throw, and verification of the tarballs a registry would receive. Depends on no package it checks.",
"type": "module",
"exports": {
Expand All @@ -24,7 +24,7 @@
"test": "pnpm run typecheck && vitest run"
},
"devDependencies": {
"@repo/tsconfig": "workspace:8.0.0-rc.9",
"@repo/tsconfig": "workspace:8.0.0-rc.10",
"@types/node": "^22.19.19",
"es-module-lexer": "^2.1.0",
"tsx": "^4.22.4",
Expand Down
4 changes: 2 additions & 2 deletions packages/cli-engine/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@
"string-width": "^8.2.1"
},
"devDependencies": {
"@repo/cli-conformance": "workspace:8.0.0-rc.9",
"@repo/tsconfig": "workspace:8.0.0-rc.9",
"@repo/cli-conformance": "workspace:8.0.0-rc.10",
"@repo/tsconfig": "workspace:8.0.0-rc.10",
"@types/node": "^22.19.19",
"ci-info": "^4.3.1",
"tsdown": "^0.21.10",
Expand Down
4 changes: 2 additions & 2 deletions packages/cli-telemetry/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@repo/cli-telemetry",
"private": true,
"version": "8.0.0-rc.9",
"version": "8.0.0-rc.10",
"description": "CLI telemetry child sender: the detached subprocess the engine hands a composed payload to, its system probes, and the POST",
"type": "module",
"sideEffects": [
Expand Down Expand Up @@ -35,7 +35,7 @@
"@vercel/detect-agent": "^1.2.3"
},
"devDependencies": {
"@repo/tsconfig": "workspace:8.0.0-rc.9",
"@repo/tsconfig": "workspace:8.0.0-rc.10",
"@types/node": "^22.19.19",
"tsdown": "^0.21.10",
"typescript": "^6.0.3",
Expand Down
14 changes: 7 additions & 7 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@prisma/cli",
"version": "8.0.0-rc.9",
"version": "8.0.0-rc.10",
"description": "Command-line interface for the Prisma Developer Platform.",
"type": "module",
"bin": {
Expand Down Expand Up @@ -50,22 +50,22 @@
"dependencies": {
"@manypkg/tools": "^2.1.2",
"@prisma/cli-engine": "workspace:0.2.3",
"@prisma/composer-cli": "0.13.0",
"@prisma/composer-cli": "0.14.0",
"@prisma/compute-sdk": "0.39.0",
"@prisma/credentials-store": "^7.8.0",
"@prisma/management-api-sdk": "1.55.0",
"@prisma/orm-toolchain": "8.0.0-rc.6",
"@prisma/orm-toolchain": "8.0.0-rc.7",
"@vercel/detect-agent": "^1.2.3",
"better-result": "^2.9.2",
"dotenv": "^17.4.2",
"execa": "^9.6.1",
"open": "^11.0.0"
},
"devDependencies": {
"@prisma/composer": "0.13.0",
"@repo/cli-conformance": "workspace:8.0.0-rc.9",
"@repo/cli-telemetry": "workspace:8.0.0-rc.9",
"@repo/tsconfig": "workspace:8.0.0-rc.9",
"@prisma/composer": "0.14.0",
"@repo/cli-conformance": "workspace:8.0.0-rc.10",
"@repo/cli-telemetry": "workspace:8.0.0-rc.10",
"@repo/tsconfig": "workspace:8.0.0-rc.10",
"@types/node": "^22.19.19",
"tsdown": "^0.21.10",
"tsx": "^4.22.4",
Expand Down
35 changes: 7 additions & 28 deletions packages/cli/scripts/conformance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,34 +109,13 @@ async function tarball(): Promise<readonly Finding[]> {
shellPackage: "@prisma/cli",
enginePackage: "@prisma/cli-engine",
familyPackages: ["@prisma/composer-cli", "@prisma/orm-toolchain"],
// The empty list is the goal state: both families peering the
// exact engine version this repo ships, one engine per install
// (ADR 0004). The two entries below are an engine version
// transition in flight — a family cannot peer an engine version
// that is not on the registry, so the engine publishes first and
// the mismatch is real until both families release against it.
// The entries expire with the versions they name, and the PR
// that pins the families' 0.2.3 releases removes them; while
// they stand, a release could ship the two-engine install they
// describe, which is why they must not outlive the transition.
exceptions: [
{
familyPackage: "@prisma/composer-cli",
familyPin: "0.2.2",
shellPin: "0.2.3",
reason: "engine 0.2.3 must publish before composer-cli can peer it",
removeWhen:
"composer-cli releases peering 0.2.3 and the follow-up bump PR pins that release",
},
{
familyPackage: "@prisma/orm-toolchain",
familyPin: "0.2.2",
shellPin: "0.2.3",
reason: "engine 0.2.3 must publish before orm-toolchain can peer it",
removeWhen:
"orm-toolchain releases peering 0.2.3 and the follow-up bump PR pins that release",
},
],
// No exceptions. Both families declare @prisma/cli-engine as an
// exact peer at the version this repo ships, so one engine
// resolves in an install — what ADR 0004 asks for. An entry here
// exists only while an engine version transition is in flight
// (the engine must publish before a family can peer it), and the
// release PR that pins the families' new versions removes it.
exceptions: [],
channel: CHANNEL,
sandboxDir: join(WORK_DIR, "sandbox"),
},
Expand Down
2 changes: 1 addition & 1 deletion packages/compute/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"test": "vitest run"
},
"devDependencies": {
"@repo/tsconfig": "workspace:8.0.0-rc.9",
"@repo/tsconfig": "workspace:8.0.0-rc.10",
"@types/node": "^22.19.19",
"tsdown": "^0.21.10",
"typescript": "^6.0.3",
Expand Down
12 changes: 6 additions & 6 deletions packages/prisma/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "prisma",
"version": "8.0.0-rc.9",
"version": "8.0.0-rc.10",
"description": "The Prisma CLI: one binary for the ORM, Composer, and the Prisma Developer Platform.",
"type": "module",
"bin": {
Expand Down Expand Up @@ -50,21 +50,21 @@
"dependencies": {
"@manypkg/tools": "^2.1.2",
"@prisma/cli-engine": "workspace:0.2.3",
"@prisma/composer-cli": "0.13.0",
"@prisma/composer-cli": "0.14.0",
"@prisma/compute-sdk": "0.39.0",
"@prisma/credentials-store": "^7.8.0",
"@prisma/management-api-sdk": "1.55.0",
"@prisma/orm-toolchain": "8.0.0-rc.6",
"@prisma/orm-toolchain": "8.0.0-rc.7",
"@vercel/detect-agent": "^1.2.3",
"better-result": "^2.9.2",
"dotenv": "^17.4.2",
"execa": "^9.6.1",
"open": "^11.0.0"
},
"devDependencies": {
"@prisma/cli": "workspace:8.0.0-rc.9",
"@repo/cli-telemetry": "workspace:8.0.0-rc.9",
"@repo/tsconfig": "workspace:8.0.0-rc.9",
"@prisma/cli": "workspace:8.0.0-rc.10",
"@repo/cli-telemetry": "workspace:8.0.0-rc.10",
"@repo/tsconfig": "workspace:8.0.0-rc.10",
"@types/node": "^22.19.19",
"tsdown": "^0.21.10",
"typescript": "^6.0.3",
Expand Down
2 changes: 1 addition & 1 deletion packages/tsconfig/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@repo/tsconfig",
"private": true,
"version": "8.0.0-rc.9",
"version": "8.0.0-rc.10",
"description": "Base tsconfig providing package for the monorepo",
"license": "Apache-2.0",
"files": [
Expand Down
Loading
Loading