You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
## At a glance
```bash
# before this PR merges
npm install prisma # -> 7.9.1 (Prisma 7)
npm install prisma@next # -> 8.0.0-rc.9
# after this PR merges
npm install prisma # -> 8.0.0-rc.10 (the unified v8 CLI)
```
## The decision
We are cutting the bare `prisma` npm name over to the v8 line. Until
now, every 8.0.0-rc release published under the `next` dist-tag and
`latest` kept serving Prisma 7, so nobody landed on v8 without asking
for it. The operator ruled today (2026-08-25) that the RC line is ready
to be what a bare `npm install prisma` gets. The version number does not
change meaning: we stay on `8.0.0-rc.N` (this release is rc.10), and
GitHub Releases remain marked pre-release. Only the dist-tag policy
moves.
## How the flip actually happens
In this repo, merging a version-bump PR is the act that publishes: the
push to `main` carries a changed root version, and the publish workflow
ships it under the tag `releaseDistTag()` returns. This PR widens that
function so every release — RC or stable — publishes under `latest`.
**Merging this PR is therefore the cutover itself**: it bumps rc.9 →
rc.10 and the resulting publish moves `latest` on `prisma` and
`@prisma/cli` in one deliberate, reviewable act.
## What rc.10 ships (since rc.9)
- Config files evaluate correctly when the CLI is reached through pnpm
symlink layouts that are not realpath'd (#222) — previously every
config-reading command failed with `CLI.CONFIG_UNREADABLE` in those
setups.
- The engine's CI detector is exported and the skills staleness notice
uses it, so Jenkins/TeamCity/Azure pipelines stop seeing the notice in
their logs (#224).
- The `prisma init` scaffold fixes (#225).
- Current command-family releases, both peering the exact engine this
repo ships (`@prisma/cli-engine@0.2.3`), so one engine resolves per
install and the conformance exception list is empty again:
`@prisma/composer-cli@0.14.0` and `@prisma/orm-toolchain@8.0.0-rc.7`
(which carries the PostgreSQL temporal-codec representations and the
`limit`/`offset` pagination rename).
## What happens to the `next` tag and to v7 users
- `next` is retired: the publish path no longer moves it, and
`scripts/cutover-dist-tags.sh` (operator-run) removes it from all three
names and fixes the engine's stale tags. Text that says `prisma@next`
should move to plain `prisma` — after this merge they resolve the same
thing anyway, until the tag is removed.
- Existing v7 installs are untouched: lockfiles pin resolved versions,
and `prisma@7.9.1` stays installable by version. The v7 train's new
publish home (`prisma7`) is being handled separately and does not block
this.
## Alternatives considered
- **A one-off `workflow_dispatch` with `dist-tag: latest`** — moves
`latest` once, but every subsequent RC release would publish under
`next` again and leave `latest` stale on rc.10. The widened rule makes
the routine release path keep `latest` current.
- **Waiting for stable `8.0.0`** — the rollout plan always left the flip
timing to an operator judgement after an RC soak, not to the stable
release; the operator ruled the soak is over.
- **Keeping `next` synced to `latest`** — considered so existing
`prisma@next` instructions would keep resolving the newest release, and
dropped: re-pointing a tag on an already-published version cannot
authenticate over OIDC, and npm's granular tokens go no narrower than
package write — a standing sync would mean a standing publish-capable
token, defeating the repo's OIDC-only invariant. Retiring the tag is the
honest alternative.
## Verification
Script tests green (33/0 on determine-version-utils). Conformance with
the empty exception list: **5 subjects checked, nothing to report**, on
both the release and dev channels. Lint and the CLI/engine suites green.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Copy file name to clipboardExpand all lines: .github/workflows/publish.yml
+1-1Lines changed: 1 addition & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -16,7 +16,7 @@ on:
16
16
workflow_dispatch:
17
17
inputs:
18
18
dist-tag:
19
-
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."
19
+
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."
Copy file name to clipboardExpand all lines: docs/oss/versioning.md
+8-8Lines changed: 8 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,9 +8,9 @@ Prisma 8 ships as a release-candidate line ahead of `8.0.0` final: releases are
8
8
9
9
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`.
10
10
11
-
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`.
11
+
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.
12
12
13
-
**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).
13
+
**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).
14
14
15
15
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).
16
16
@@ -39,11 +39,11 @@ This is enforced, not remembered: the conformance checks refuse to publish a rel
39
39
40
40
The npm registry exposes the CLI packages under these dist-tags:
41
41
42
-
-**`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.
43
-
-**`next`** — the Prisma 8 RC line (`8.0.0-rc.N`). A merged release PR on the RC line publishes here automatically.
42
+
-**`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`).
43
+
-**`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`.
44
44
-**`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.
45
45
46
-
-**`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.
46
+
-**`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.
47
47
48
48
**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.
49
49
@@ -68,7 +68,7 @@ This is by design. The alternatives cause silent problems:
68
68
69
69
[`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.
70
70
71
-
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`.
71
+
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`.
72
72
73
73
**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.
74
74
@@ -81,9 +81,9 @@ Before anything reaches the registry, the workflow verifies the artifact it is a
81
81
The release cadence is one PR per release (on the RC line: one PR per `rc.N`). A maintainer:
82
82
83
83
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.
84
-
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).
84
+
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).
85
85
86
-
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).
86
+
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).
Copy file name to clipboardExpand all lines: packages/cli-conformance/package.json
+2-2Lines changed: 2 additions & 2 deletions
Original file line number
Diff line number
Diff line change
@@ -1,7 +1,7 @@
1
1
{
2
2
"name": "@repo/cli-conformance",
3
3
"private": true,
4
-
"version": "8.0.0-rc.9",
4
+
"version": "8.0.0-rc.10",
5
5
"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.",
0 commit comments