diff --git a/.github/workflows/bump_prisma.yml b/.github/workflows/bump_prisma.yml
new file mode 100644
index 0000000000..661b6419ad
--- /dev/null
+++ b/.github/workflows/bump_prisma.yml
@@ -0,0 +1,114 @@
+name: Bump Prisma CLI
+run-name: "Bump Prisma CLI to ${{ inputs.prisma_version }} on ${{ inputs.ref || 'main' }}"
+
+# Updates the Prisma CLI dependencies and pushes the change to the branch.
+#
+# Publishing is a separate workflow. A bump pushed to main triggers an insider
+# release through release.yml's push trigger; a stable release is always a
+# manual dispatch of release.yml.
+
+on:
+ workflow_dispatch:
+ inputs:
+ prisma_version:
+ description: 'Prisma CLI version to pin the dependencies to (e.g. 7.9.0)'
+ required: true
+ ref:
+ description: 'Branch to bump. Defaults to main. Use an x.y.x branch to patch an older version.'
+ required: false
+
+concurrency:
+ group: bump-prisma
+ cancel-in-progress: false
+
+permissions:
+ contents: read
+
+env:
+ ENVIRONMENT: ${{ secrets.ENVIRONMENT }}
+ PRISMA_TELEMETRY_INFORMATION: 'language-tools bump_prisma.yml'
+
+jobs:
+ pin:
+ name: Pin the Prisma CLI dependencies
+ if: github.repository == 'prisma/language-tools'
+ runs-on: ubuntu-latest
+ timeout-minutes: 10
+ outputs:
+ ref: ${{ steps.validate.outputs.ref }}
+ steps:
+ - name: Validate inputs
+ id: validate
+ env:
+ PRISMA_VERSION: ${{ inputs.prisma_version }}
+ INPUT_REF: ${{ inputs.ref }}
+ run: |
+ if ! echo "$PRISMA_VERSION" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$'; then
+ echo "'$PRISMA_VERSION' is not a Prisma CLI version." >&2
+ exit 1
+ fi
+ REF="${INPUT_REF:-main}"
+ case "$REF" in
+ main) ;;
+ *)
+ if ! echo "$REF" | grep -Eq '^[0-9]+\.[0-9]+\.x$'; then
+ echo "Refusing to bump '$REF'. Bumps run on main or an x.y.x patch branch." >&2
+ exit 1
+ fi
+ ;;
+ esac
+ echo "ref=$REF" >> "$GITHUB_OUTPUT"
+ - uses: actions/checkout@v4
+ with:
+ ref: ${{ steps.validate.outputs.ref }}
+ persist-credentials: false
+ - name: Install pnpm
+ uses: pnpm/action-setup@v4
+ - name: Use Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: '22'
+ cache: 'pnpm'
+ - name: Install Dependencies
+ run: pnpm install
+ - name: Pin the Prisma CLI dependencies
+ env:
+ PRISMA_VERSION: ${{ inputs.prisma_version }}
+ run: node scripts/bump_prisma_dependencies.mjs "$PRISMA_VERSION"
+ - name: Update the lockfile
+ run: pnpm install --no-frozen-lockfile
+ - name: Upload the pinned manifests
+ uses: actions/upload-artifact@v4
+ with:
+ name: pinned-manifests
+ path: |
+ packages/language-server/package.json
+ pnpm-lock.yaml
+ if-no-files-found: error
+
+ push:
+ name: Commit and push the bump
+ needs: [pin]
+ runs-on: ubuntu-latest
+ timeout-minutes: 10
+ env:
+ REF: ${{ needs.pin.outputs.ref }}
+ PRISMA_VERSION: ${{ inputs.prisma_version }}
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ ref: ${{ needs.pin.outputs.ref }}
+ token: ${{ secrets.PRISMA_BOT_TOKEN }}
+ - name: Download the pinned manifests
+ uses: actions/download-artifact@v4
+ with:
+ name: pinned-manifests
+ - name: Commit and push
+ run: |
+ if git diff --quiet; then
+ echo "Dependencies are already pinned to $PRISMA_VERSION, nothing to commit."
+ exit 0
+ fi
+ sh scripts/set_git_credentials.sh
+ git commit -am "bump Prisma CLI to $PRISMA_VERSION"
+ git push origin "HEAD:$REF"
diff --git a/.github/workflows/check_for_prisma_update.yml b/.github/workflows/check_for_prisma_update.yml
index 66a94e620d..758dda697d 100644
--- a/.github/workflows/check_for_prisma_update.yml
+++ b/.github/workflows/check_for_prisma_update.yml
@@ -1,11 +1,11 @@
name: Check for Prisma CLI update
-# Polls npm for new Prisma CLI versions and starts the Release workflow
-# (release.yml) for every channel that has a new version:
+# Polls npm for new Prisma CLI versions and starts the Bump Prisma CLI
+# workflow (bump_prisma.yml) for every channel that has a new version:
#
-# - dev -> insider release from main
-# - latest -> stable release from the stable branch
-# - patch-dev -> insider release from the x.y.x patch branch
+# - dev, latest -> bump main; the push to main publishes an insider release,
+# and a stable release is a manual dispatch of release.yml
+# - patch-dev -> bump the x.y.x patch branch, then release from it
on:
# Scheduled trigger disabled: ORM iteration is paused; CLI-update polling
@@ -14,6 +14,13 @@ on:
# - cron: '*/5 * * * *'
workflow_dispatch:
+concurrency:
+ group: check-for-prisma-update
+ cancel-in-progress: false
+
+permissions:
+ contents: read
+
env:
ENVIRONMENT: ${{ secrets.ENVIRONMENT }}
PRISMA_TELEMETRY_INFORMATION: 'language-tools check_for_prisma_update.yml'
@@ -24,13 +31,15 @@ jobs:
if: github.repository == 'prisma/language-tools'
runs-on: ubuntu-latest
timeout-minutes: 7
- env:
- GH_TOKEN: ${{ secrets.PRISMA_BOT_TOKEN }}
+ outputs:
+ dev_version: ${{ steps.check_update.outputs.dev_version }}
+ latest_version: ${{ steps.check_update.outputs.latest_version }}
+ patch_dev_version: ${{ steps.check_update.outputs.patch-dev_version }}
steps:
- uses: actions/checkout@v4
with:
- token: ${{ secrets.PRISMA_BOT_TOKEN }}
- fetch-depth: 0 # patch branches are created from release tags
+ ref: main
+ persist-credentials: false
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Use Node.js
@@ -40,39 +49,37 @@ jobs:
cache: 'pnpm'
- name: Install Dependencies
run: pnpm install
-
- name: Check for Prisma CLI update
id: check_update
run: node scripts/check_for_update.mjs
+ record:
+ name: Record versions and start the bumps
+ needs: [check]
+ if: needs.check.outputs.dev_version || needs.check.outputs.latest_version || needs.check.outputs.patch_dev_version
+ runs-on: ubuntu-latest
+ timeout-minutes: 7
+ env:
+ DEV_VERSION: ${{ needs.check.outputs.dev_version }}
+ LATEST_VERSION: ${{ needs.check.outputs.latest_version }}
+ PATCH_DEV_VERSION: ${{ needs.check.outputs.patch_dev_version }}
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ ref: main
+ token: ${{ secrets.PRISMA_BOT_TOKEN }}
+ fetch-depth: 0 # patch branches are created from release tags
- name: Record new versions
- if: steps.check_update.outputs.dev_version || steps.check_update.outputs.latest_version || steps.check_update.outputs.patch-dev_version
- env:
- DEV_VERSION: ${{ steps.check_update.outputs.dev_version }}
- LATEST_VERSION: ${{ steps.check_update.outputs.latest_version }}
- PATCH_DEV_VERSION: ${{ steps.check_update.outputs.patch-dev_version }}
run: |
sh scripts/set_git_credentials.sh
if [ -n "$DEV_VERSION" ]; then echo "$DEV_VERSION" > scripts/versions/prisma_dev; fi
if [ -n "$LATEST_VERSION" ]; then echo "$LATEST_VERSION" > scripts/versions/prisma_latest; fi
if [ -n "$PATCH_DEV_VERSION" ]; then echo "$PATCH_DEV_VERSION" > scripts/versions/prisma_patch-dev; fi
git commit -am "[skip ci] record new Prisma CLI versions"
- git push
-
- - name: Release insider (Prisma dev)
- if: steps.check_update.outputs.dev_version
- env:
- DEV_VERSION: ${{ steps.check_update.outputs.dev_version }}
- run: gh workflow run release.yml --ref main -f channel=insider -f prisma_version="$DEV_VERSION"
- - name: Release stable (Prisma latest)
- if: steps.check_update.outputs.latest_version
- env:
- LATEST_VERSION: ${{ steps.check_update.outputs.latest_version }}
- run: gh workflow run release.yml --ref main -f channel=stable -f prisma_version="$LATEST_VERSION"
- - name: Release insider from patch branch (Prisma patch-dev)
- if: steps.check_update.outputs.patch-dev_version
- env:
- PATCH_DEV_VERSION: ${{ steps.check_update.outputs.patch-dev_version }}
+ git push origin HEAD:main
+ - name: Create the patch branch if it is new
+ id: patch_branch
+ if: needs.check.outputs.patch_dev_version
run: |
BRANCH=$(node scripts/setup_branch.mjs patch-dev)
if [ -z "$(git ls-remote --heads origin "$BRANCH")" ]; then
@@ -80,4 +87,20 @@ jobs:
git branch "$BRANCH" "$(cat scripts/versions/tested_extension_stable)"
git push origin "$BRANCH"
fi
- gh workflow run release.yml --ref main -f channel=insider -f ref="$BRANCH" -f prisma_version="$PATCH_DEV_VERSION"
+ echo "branch=$BRANCH" >> "$GITHUB_OUTPUT"
+ - name: Bump main (Prisma dev)
+ if: needs.check.outputs.dev_version
+ env:
+ GH_TOKEN: ${{ secrets.PRISMA_BOT_TOKEN }}
+ run: gh workflow run bump_prisma.yml --ref main -f prisma_version="$DEV_VERSION"
+ - name: Bump main (Prisma latest)
+ if: needs.check.outputs.latest_version && !needs.check.outputs.dev_version
+ env:
+ GH_TOKEN: ${{ secrets.PRISMA_BOT_TOKEN }}
+ run: gh workflow run bump_prisma.yml --ref main -f prisma_version="$LATEST_VERSION"
+ - name: Bump the patch branch (Prisma patch-dev)
+ if: needs.check.outputs.patch_dev_version
+ env:
+ GH_TOKEN: ${{ secrets.PRISMA_BOT_TOKEN }}
+ BRANCH: ${{ steps.patch_branch.outputs.branch }}
+ run: gh workflow run bump_prisma.yml --ref main -f prisma_version="$PATCH_DEV_VERSION" -f ref="$BRANCH"
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 4cbcb11658..ab1e025e70 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -1,19 +1,17 @@
name: Release
-run-name: "Release ${{ github.event_name == 'push' && 'insider (push to main)' || format('{0}{1}', inputs.channel, inputs.prisma_version != '' && format(' — Prisma CLI {0}', inputs.prisma_version) || '') }}"
+run-name: "Release ${{ github.event_name == 'push' && 'insider (push to main)' || format('{0} from {1}', inputs.channel, inputs.ref || 'main') }}"
# The single publishing pipeline for both the insider and the stable extension.
#
# - A push to main publishes an insider release.
-# - A manual dispatch publishes an insider or stable release, optionally
-# bumping the Prisma CLI dependencies first (`prisma_version`), optionally
-# from another branch (`ref`, e.g. an x.y.x patch branch).
-# - check_for_prisma_update.yml dispatches this workflow when a new Prisma CLI
-# version is published to npm.
+# - A manual dispatch publishes an insider or stable release, optionally from
+# an x.y.x patch branch (`ref`).
#
-# The next extension version is derived from the git release tags (`x.y.z` for
-# stable, `insider/x.y.z` for insider), so a release only creates a commit when
-# it actually changes dependencies (`prisma_version` given). All other jobs
-# check out the exact commit resolved by the `plan` job.
+# This workflow never writes to the repository. The next extension version is
+# derived from the git release tags (`x.y.z` for stable, `insider/x.y.z` for
+# insider), and Prisma CLI dependency updates are a separate workflow
+# (bump_prisma.yml) that commits to main. Only the `release` job holds write
+# access, to create the tag and GitHub release.
on:
push:
@@ -32,21 +30,17 @@ on:
- stable
default: insider
ref:
- description: 'Branch to release from. Defaults to main for insider and stable for stable. Use an x.y.x branch to patch an older version.'
+ description: 'Branch to release from. Defaults to main. Use an x.y.x branch to patch an older version.'
required: false
bump:
- description: "Extension version bump (stable only; 'auto' derives it from the Prisma CLI version)"
+ description: 'Extension version bump (stable only; insider is always a patch)'
required: false
type: choice
options:
- - auto
- patch
- minor
- major
- default: auto
- prisma_version:
- description: 'Bump the Prisma CLI dependencies to this version before releasing (creates one commit on the release branch)'
- required: false
+ default: patch
concurrency:
group: release
@@ -66,8 +60,6 @@ jobs:
if: github.repository == 'prisma/language-tools'
runs-on: ubuntu-latest
timeout-minutes: 10
- permissions:
- contents: write
outputs:
channel: ${{ steps.params.outputs.channel }}
ref: ${{ steps.params.outputs.ref }}
@@ -91,15 +83,12 @@ jobs:
REF="$PUSH_SHA"
else
CHANNEL="$INPUT_CHANNEL"
- REF="$INPUT_REF"
- if [ -z "$REF" ]; then
- if [ "$CHANNEL" = "stable" ]; then REF=stable; else REF=main; fi
- fi
+ REF="${INPUT_REF:-main}"
case "$REF" in
- main | stable) ;;
+ main) ;;
*)
if ! echo "$REF" | grep -Eq '^[0-9]+\.[0-9]+\.x$'; then
- echo "Refusing to release from '$REF'. Releases run from main, stable or an x.y.x patch branch." >&2
+ echo "Refusing to release from '$REF'. Releases run from main or an x.y.x patch branch." >&2
exit 1
fi
;;
@@ -113,7 +102,7 @@ jobs:
with:
ref: ${{ steps.params.outputs.ref }}
fetch-depth: 0 # all branches and tags: the next version is derived from release tags
- token: ${{ secrets.PRISMA_BOT_TOKEN }}
+ persist-credentials: false
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Use Node.js
@@ -127,26 +116,8 @@ jobs:
id: version
env:
CHANNEL: ${{ steps.params.outputs.channel }}
- BUMP: ${{ inputs.bump || 'auto' }}
- PRISMA_VERSION: ${{ inputs.prisma_version }}
- run: node scripts/next_extension_version.mjs "$CHANNEL" "$BUMP" "$PRISMA_VERSION"
- - name: Reset stable branch to main (new Prisma minor/major)
- if: steps.params.outputs.channel == 'stable' && inputs.prisma_version != '' && steps.version.outputs.release_type != 'patch'
- run: |
- git checkout -B stable origin/main
- git push --force origin stable
- - name: Bump Prisma dependencies
- if: inputs.prisma_version != ''
- env:
- NPM_CHANNEL: ${{ steps.version.outputs.npm_channel }}
- VERSION: ${{ steps.version.outputs.version }}
- PRISMA_VERSION: ${{ inputs.prisma_version }}
- RELEASE_REF: ${{ steps.params.outputs.ref }}
- run: |
- node scripts/update_package_json_files.mjs "$NPM_CHANNEL" "$VERSION" "$PRISMA_VERSION"
- sh scripts/set_git_credentials.sh
- git commit -am "[skip ci] bump Prisma CLI to $PRISMA_VERSION and extension to $VERSION"
- git push origin "HEAD:$RELEASE_REF"
+ BUMP: ${{ inputs.bump || 'patch' }}
+ run: node scripts/next_extension_version.mjs "$CHANNEL" "$BUMP"
- name: Resolve release commit
id: sha
run: echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
@@ -293,7 +264,6 @@ jobs:
timeout-minutes: 10
env:
ASSET_FILE: ${{ needs.plan.outputs.asset_name }}-${{ needs.plan.outputs.version }}.vsix
- VSCE_PAT: ${{ secrets.AZURE_DEVOPS_PERSONAL_ACCESS_TOKEN }}
steps:
- uses: actions/checkout@v4
with:
@@ -313,6 +283,8 @@ jobs:
with:
name: vsix
- name: Publish vsix to marketplace
+ env:
+ VSCE_PAT: ${{ secrets.AZURE_DEVOPS_PERSONAL_ACCESS_TOKEN }}
run: cd packages/vscode && npx vsce publish --packagePath "$GITHUB_WORKSPACE/$ASSET_FILE"
publish-open-vsx:
@@ -322,7 +294,6 @@ jobs:
timeout-minutes: 10
env:
ASSET_FILE: ${{ needs.plan.outputs.asset_name }}-${{ needs.plan.outputs.version }}.vsix
- OVSX_PAT: ${{ secrets.OPEN_VSX_ACCESS_TOKEN }}
steps:
- uses: actions/checkout@v4
with:
@@ -342,4 +313,6 @@ jobs:
with:
name: vsix
- name: Publish vsix to open-vsx.org
+ env:
+ OVSX_PAT: ${{ secrets.OPEN_VSX_ACCESS_TOKEN }}
run: cd packages/vscode && npx ovsx --debug publish "$GITHUB_WORKSPACE/$ASSET_FILE"
diff --git a/docs/architecture.md b/docs/architecture.md
index a0dd696b33..8691d86942 100644
--- a/docs/architecture.md
+++ b/docs/architecture.md
@@ -69,10 +69,12 @@ assets (`pglite.data`, `pglite.wasm`) are copied separately
⁴ Kept separate to support runtime switching between Prisma 6 and latest
language servers via the `prisma.pinToPrisma6` setting
-> **Note:** These dependencies are updated via CI by
-> `.github/workflows/check_for_prisma_update.yml`, which checks npm for new
-> Prisma CLI releases and dispatches `release.yml`. Its cron schedule is
-> currently disabled; dispatch it manually. See [CI/CD](ci-cd.md).
+> **Note:** These dependencies are updated by
+> `.github/workflows/bump_prisma.yml`, which pins them to a given Prisma CLI
+> version and pushes the change. `check_for_prisma_update.yml` dispatches it
+> when npm has a newer CLI, but its cron schedule is currently disabled, so
+> both are manual dispatches today. `release.yml` only publishes; it never
+> changes dependencies. See [CI/CD](ci-cd.md).
## File Organization
diff --git a/docs/ci-cd.md b/docs/ci-cd.md
index 2af4cd9184..b276007622 100644
--- a/docs/ci-cd.md
+++ b/docs/ci-cd.md
@@ -3,30 +3,34 @@
## Publishing pipeline
All publishing — insider **and** stable — happens in a single workflow:
-[`release.yml`](../.github/workflows/release.yml). There are no chained
-workflows and no version-bump commits: the next extension version is derived
-from the git release tags (`x.y.z` for stable, `insider/x.y.z` for insider,
-one shared monotonic counter). The only commit a release can create is a real
-dependency bump when a new Prisma CLI version is passed in.
+[`release.yml`](../.github/workflows/release.yml). It **never writes to the
+repository**. The next extension version is derived from the git release tags
+(`x.y.z` for stable, `insider/x.y.z` for insider, one shared monotonic
+counter), so releasing creates no bot commits. Prisma CLI dependency updates
+are a separate workflow, [`bump_prisma.yml`](../.github/workflows/bump_prisma.yml).
+
+Standard releases, insider and stable alike, are cut from `main`. Both channels
+ship the same code and the same Prisma CLI pins; the channel only decides the
+extension identity (`prisma` vs `prisma-insider`) and the Language Server npm
+dist-tag. Patch releases for an older version are cut from the `x.y.x` branch
+passed as `ref`, which must be given explicitly — `ref` defaults to `main`.
### Triggers
-| Trigger | Result |
-| ---------------------------------------------- | ------------------------------------------------------------------------- |
-| Push to `main` | Insider release |
-| Manual `workflow_dispatch` | Insider or stable release, optional Prisma CLI bump, optional branch |
-| `check_for_prisma_update.yml` (cron, disabled) | Dispatches `release.yml` when a new Prisma CLI version is released on npm |
+| Trigger | Result |
+| -------------------------- | ------------------------------------------------ |
+| Push to `main` | Insider release |
+| Manual `workflow_dispatch` | Insider or stable release, optional patch branch |
### Jobs
```mermaid
graph TD
PUSH(Push to main) --> PLAN
- MANUAL(Manual dispatch: channel, bump, prisma_version) --> PLAN
- CRON(check_for_prisma_update.yml cron) --> PLAN
+ MANUAL(Manual dispatch: channel, bump, ref) --> PLAN
subgraph release.yml
- PLAN[plan: resolve channel + branch, derive next version from git tags,
optionally commit Prisma CLI dependency bump]
+ PLAN[plan: resolve channel + branch,
derive next version from git tags]
PLAN --> TEST[test: build, typecheck, LS unit tests, E2E tests
on ubuntu / macos / windows]
TEST --> LS[publish-language-server:
npm publish with dist-tag dev or latest]
TEST --> PKG[package: build vsix, upload artifact]
@@ -50,37 +54,49 @@ graph TD
### Permissions
-The workflow default is `contents: read`. Write access is granted per job:
-`plan` (pushes the dependency-bump commit and can reset `stable`), `release`
-(creates the tag and GitHub release) and `publish-language-server`
-(`id-token: write` for npm Trusted Publishers). Every checkout except `plan`'s
-sets `persist-credentials: false`, so build and test steps never see a git
-credential.
+The workflow default is `contents: read`. Only two jobs are granted more:
+`release` (`contents: write`, to create the tag and GitHub release) and
+`publish-language-server` (`id-token: write`, for npm Trusted Publishers).
+Every checkout sets `persist-credentials: false`, so no job has a git
+credential in its config while running dependency code.
-Releases only run from `main`, `stable` or an `x.y.x` patch branch; `plan`
-rejects any other `ref`.
+Releases only run from `main` or an `x.y.x` patch branch; `plan` rejects any
+other `ref`.
-### Channels and branches
+### Channels
-| Channel | Branch | Extension name | LS npm dist-tag |
-| ------- | --------------- | ---------------- | --------------- |
-| insider | `main` | `prisma-insider` | `dev` |
-| stable | `stable` | `prisma` | `latest` |
-| insider | `x.y.x` patches | `prisma-insider` | `dev` |
+| Channel | Extension name | Tag | LS npm dist-tag |
+| ------- | ---------------- | --------------- | --------------- |
+| insider | `prisma-insider` | `insider/x.y.z` | `dev` |
+| stable | `prisma` | `x.y.z` | `latest` |
-The `stable` branch pins the Prisma CLI `latest` dependencies while `main`
-tracks `dev`. When a stable release ships a new Prisma minor or major, the
-`plan` job resets `stable` to `main`. Patch releases for older versions are
-made by dispatching `release.yml` with an `x.y.x` branch as `ref`
-(channel `insider` for a `patch-dev` CLI, `stable` for the final patch).
+An insider release is always a patch bump. A stable release takes the `bump`
+input (`patch`, `minor` or `major`, defaulting to `patch`). Both channels draw
+from the same version counter, so a stable release picks up from the highest
+tag either channel has reached.
-### Prisma CLI update automation
+To patch an older version, dispatch `release.yml` with an `x.y.x` branch as
+`ref`.
+
+## Prisma CLI dependency updates
+
+[`bump_prisma.yml`](../.github/workflows/bump_prisma.yml) is the only workflow
+that changes dependency pins. Dispatch it with a `prisma_version` (and
+optionally a `ref` for a patch branch). It runs
+`scripts/bump_prisma_dependencies.mjs`, which rewrites `@prisma/config`,
+`@prisma/prisma-schema-wasm`, `@prisma/schema-files-loader`,
+`prisma.enginesVersion` and `prisma.cliVersion` in
+`packages/language-server/package.json`, refreshes the lockfile, and pushes one
+commit.
+
+That push to `main` triggers an insider release through `release.yml`. A stable
+release on the new pins is a separate manual dispatch.
[`check_for_prisma_update.yml`](../.github/workflows/check_for_prisma_update.yml)
(cron, currently disabled — dispatch manually) compares the npm versions of
`prisma@dev`, `prisma@latest` and `prisma@patch-dev` against
`scripts/versions/prisma_*`, records new versions there, and dispatches
-`release.yml` for each channel that changed.
+`bump_prisma.yml` for each channel that changed.
## Other workflows
diff --git a/packages/vscode/CONTRIBUTING.md b/packages/vscode/CONTRIBUTING.md
index 59289474d1..1a248ac53b 100644
--- a/packages/vscode/CONTRIBUTING.md
+++ b/packages/vscode/CONTRIBUTING.md
@@ -82,15 +82,17 @@ The extension is automatically published via GitHub Actions using an
[pat-docs]: https://code.visualstudio.com/api/working-with-extensions/publishing-extension#get-a-personal-access-token
-### Automatic Publishing
+### Prisma CLI updates
-Upon any Prisma `dev` release a new insiders release of the extension is automatically performed.
+[`Check for Prisma CLI update`][check-workflow] polls npm and dispatches
+[`Bump Prisma CLI`][bump-workflow] for each channel that has a new version. Its
+cron schedule is currently disabled, so it has to be dispatched manually — as
+does `Bump Prisma CLI` itself if you want to pin a specific version.
-Upon any Prisma `latest` release a new stable release of the extension is automatically performed.
+A bump pushed to `main` triggers an insider release. A stable release on the new
+pins is always a separate manual dispatch.
-### Manual Publishing (Extension-Only Release)
-
-For releases that don't coincide with a Prisma ORM release:
+### Publishing
**Insider release:**
@@ -101,9 +103,13 @@ For releases that don't coincide with a Prisma ORM release:
**Stable release:**
- Manually dispatch [`Release`][release-workflow] with channel `stable`
-- Select the bump: `auto`, `patch`, `minor` or `major`
+- Select the bump: `patch`, `minor` or `major`
+- To patch an older version, pass that `x.y.x` branch as `ref`. Without it the
+ release is cut from `main`.
[release-workflow]: ../../.github/workflows/release.yml
+[bump-workflow]: ../../.github/workflows/bump_prisma.yml
+[check-workflow]: ../../.github/workflows/check_for_prisma_update.yml
## Dependencies
diff --git a/scripts/__tests__/bump-prisma-dependencies.test.mjs b/scripts/__tests__/bump-prisma-dependencies.test.mjs
new file mode 100644
index 0000000000..09dae73595
--- /dev/null
+++ b/scripts/__tests__/bump-prisma-dependencies.test.mjs
@@ -0,0 +1,48 @@
+import { describe, it, expect } from 'vitest'
+import { applyPrismaVersion } from '../bump_prisma_dependencies.mjs'
+
+const PACKAGE_JSON = {
+ name: '@prisma/language-server',
+ prisma: { enginesVersion: 'oldsha', cliVersion: '7.8.0' },
+ dependencies: {
+ '@prisma/config': '7.8.0',
+ '@prisma/prisma-schema-wasm': '7.8.0-6.oldsha',
+ '@prisma/schema-files-loader': '7.8.0',
+ 'vscode-languageserver': '9.0.1',
+ },
+}
+
+describe('applyPrismaVersion', () => {
+ const bumped = applyPrismaVersion({
+ packageJson: PACKAGE_JSON,
+ prismaVersion: '7.9.0',
+ engineVersion: '7.9.0-23.9b816b3aa13cc270074f172f30d6eda8a8ce867d',
+ })
+
+ it('pins every Prisma dependency to the new CLI version', () => {
+ expect(bumped.dependencies['@prisma/config']).toEqual('7.9.0')
+ expect(bumped.dependencies['@prisma/schema-files-loader']).toEqual('7.9.0')
+ expect(bumped.dependencies['@prisma/prisma-schema-wasm']).toEqual(
+ '7.9.0-23.9b816b3aa13cc270074f172f30d6eda8a8ce867d',
+ )
+ })
+
+ it('records the CLI version and the engine sha', () => {
+ expect(bumped.prisma.cliVersion).toEqual('7.9.0')
+ expect(bumped.prisma.enginesVersion).toEqual('9b816b3aa13cc270074f172f30d6eda8a8ce867d')
+ })
+
+ it('leaves unrelated dependencies alone', () => {
+ expect(bumped.dependencies['vscode-languageserver']).toEqual('9.0.1')
+ })
+
+ it('does not mutate the input', () => {
+ expect(PACKAGE_JSON.prisma.cliVersion).toEqual('7.8.0')
+ })
+
+ it('throws when the engine version carries no sha', () => {
+ expect(() =>
+ applyPrismaVersion({ packageJson: PACKAGE_JSON, prismaVersion: '7.9.0', engineVersion: '7.9.0' }),
+ ).toThrow()
+ })
+})
diff --git a/scripts/__tests__/next-extension-version.test.mjs b/scripts/__tests__/next-extension-version.test.mjs
index 04395060b6..e807873210 100644
--- a/scripts/__tests__/next-extension-version.test.mjs
+++ b/scripts/__tests__/next-extension-version.test.mjs
@@ -27,27 +27,17 @@ describe('latestReleasedVersion', () => {
describe('releaseType', () => {
it('insider releases are always a patch', () => {
- expect(releaseType({ channel: 'insider', bump: 'auto', prismaVersion: '7.9.0-dev.4' })).toEqual('patch')
+ expect(releaseType({ channel: 'insider', bump: 'major' })).toEqual('patch')
})
- it('stable release for a Prisma CLI patch', () => {
- expect(releaseType({ channel: 'stable', bump: 'auto', prismaVersion: '7.8.1' })).toEqual('patch')
+ it('stable releases use the requested bump', () => {
+ expect(releaseType({ channel: 'stable', bump: 'patch' })).toEqual('patch')
+ expect(releaseType({ channel: 'stable', bump: 'minor' })).toEqual('minor')
+ expect(releaseType({ channel: 'stable', bump: 'major' })).toEqual('major')
})
- it('stable release for a Prisma CLI minor', () => {
- expect(releaseType({ channel: 'stable', bump: 'auto', prismaVersion: '7.9.0' })).toEqual('minor')
- })
-
- it('stable release for a Prisma CLI major', () => {
- expect(releaseType({ channel: 'stable', bump: 'auto', prismaVersion: '8.0.0' })).toEqual('major')
- })
-
- it('stable extension-only release defaults to a patch', () => {
- expect(releaseType({ channel: 'stable', bump: 'auto' })).toEqual('patch')
- })
-
- it('an explicit bump wins over the Prisma CLI version', () => {
- expect(releaseType({ channel: 'stable', bump: 'minor', prismaVersion: '7.8.1' })).toEqual('minor')
+ it('stable defaults to a patch', () => {
+ expect(releaseType({ channel: 'stable' })).toEqual('patch')
})
it('throws on an unknown channel', () => {
@@ -58,28 +48,14 @@ describe('releaseType', () => {
expect(() => releaseType({ channel: 'stable', bump: 'mega' })).toThrow()
})
- it('throws on a Prisma CLI version that is not a semantic version', () => {
- expect(() => releaseType({ channel: 'stable', bump: 'auto', prismaVersion: 'invalid.0.0' })).toThrow(
- /Invalid Prisma CLI version/,
- )
- })
-
- it('throws on a Prisma CLI prerelease for a stable release', () => {
- expect(() => releaseType({ channel: 'stable', bump: 'auto', prismaVersion: '7.9.0-dev.4' })).toThrow(/prerelease/)
- })
-
- it('validates the Prisma CLI version even when the bump is explicit', () => {
- expect(() => releaseType({ channel: 'stable', bump: 'minor', prismaVersion: 'invalid.0.0' })).toThrow()
- })
-
- it('does not validate the Prisma CLI version on the insider channel', () => {
- expect(releaseType({ channel: 'insider', bump: 'auto', prismaVersion: 'anything' })).toEqual('patch')
+ it('throws on the removed auto bump', () => {
+ expect(() => releaseType({ channel: 'stable', bump: 'auto' })).toThrow()
})
})
describe('planRelease', () => {
it('plans an insider release', () => {
- expect(planRelease({ channel: 'insider', bump: 'auto', prismaVersion: '7.9.0-dev.4', tags: TAGS })).toEqual({
+ expect(planRelease({ channel: 'insider', bump: 'patch', tags: TAGS })).toEqual({
version: '31.12.1',
release_type: 'patch',
tag_name: 'insider/31.12.1',
@@ -89,8 +65,8 @@ describe('planRelease', () => {
})
})
- it('plans a stable release for a Prisma CLI minor', () => {
- expect(planRelease({ channel: 'stable', bump: 'auto', prismaVersion: '7.9.0', tags: TAGS })).toEqual({
+ it('plans a stable minor release', () => {
+ expect(planRelease({ channel: 'stable', bump: 'minor', tags: TAGS })).toEqual({
version: '31.13.0',
release_type: 'minor',
tag_name: '31.13.0',
diff --git a/scripts/bump_prisma_dependencies.mjs b/scripts/bump_prisma_dependencies.mjs
new file mode 100644
index 0000000000..97ca1faa37
--- /dev/null
+++ b/scripts/bump_prisma_dependencies.mjs
@@ -0,0 +1,52 @@
+import execa from 'execa'
+import path from 'path'
+import { fileURLToPath } from 'url'
+import { argv } from 'process'
+import { writeJsonToPackageJson, getPackageJsonContent } from './util.mjs'
+
+const __filename = fileURLToPath(import.meta.url)
+const __dirname = path.dirname(__filename)
+
+export async function enginesVersionFor(prismaVersion) {
+ const { stdout } = await execa('pnpm', ['show', `@prisma/engines@${prismaVersion}`, 'dependencies', '--json'])
+ const engineVersion = JSON.parse(stdout)['@prisma/engines-version']
+ if (typeof engineVersion !== 'string') {
+ throw new Error(`@prisma/engines@${prismaVersion} does not declare an @prisma/engines-version dependency.`)
+ }
+ return engineVersion
+}
+
+export function applyPrismaVersion({ packageJson, prismaVersion, engineVersion }) {
+ const engineSha = engineVersion.split('.')[3]
+ if (!engineSha) {
+ throw new Error(`Could not read an engine sha out of '${engineVersion}'.`)
+ }
+ return {
+ ...packageJson,
+ prisma: { ...packageJson.prisma, enginesVersion: engineSha, cliVersion: prismaVersion },
+ dependencies: {
+ ...packageJson.dependencies,
+ '@prisma/config': prismaVersion,
+ '@prisma/prisma-schema-wasm': engineVersion,
+ '@prisma/schema-files-loader': prismaVersion,
+ },
+ }
+}
+
+if (fileURLToPath(import.meta.url) === argv[1]) {
+ const [prismaVersion] = argv.slice(2)
+ if (!prismaVersion) {
+ throw new Error('Expected a Prisma CLI version, for example: node scripts/bump_prisma_dependencies.mjs 7.9.0')
+ }
+ const packageJsonPath = path.join(__dirname, '../packages/language-server/package.json')
+ const engineVersion = await enginesVersionFor(prismaVersion)
+ console.log({ prismaVersion, engineVersion })
+ writeJsonToPackageJson({
+ content: applyPrismaVersion({
+ packageJson: getPackageJsonContent({ path: packageJsonPath }),
+ prismaVersion,
+ engineVersion,
+ }),
+ path: packageJsonPath,
+ })
+}
diff --git a/scripts/next_extension_version.mjs b/scripts/next_extension_version.mjs
index 0284f31234..b886cc71b9 100644
--- a/scripts/next_extension_version.mjs
+++ b/scripts/next_extension_version.mjs
@@ -4,7 +4,7 @@ import { execSync } from 'child_process'
import { fileURLToPath } from 'url'
import { argv } from 'process'
-const BUMPS = ['auto', 'patch', 'minor', 'major']
+const BUMPS = ['patch', 'minor', 'major']
// The extension version is a single monotonic counter shared by both channels.
// It is derived from the release tags (`x.y.z` for stable, `insider/x.y.z` for
@@ -22,20 +22,7 @@ export function latestReleasedVersion({ tags }) {
return versions[0]
}
-function parseStablePrismaVersion(prismaVersion) {
- const parsed = semVer.parse(prismaVersion)
- if (parsed === null) {
- throw new Error(`Invalid Prisma CLI version '${prismaVersion}'. Expected a semantic version such as 7.9.0.`)
- }
- if (parsed.prerelease.length > 0) {
- throw new Error(
- `Prisma CLI version '${prismaVersion}' is a prerelease and can not be released on the stable channel.`,
- )
- }
- return parsed
-}
-
-export function releaseType({ channel, bump = 'auto', prismaVersion = '' }) {
+export function releaseType({ channel, bump = 'patch' }) {
if (channel === 'insider') {
return 'patch'
}
@@ -45,28 +32,12 @@ export function releaseType({ channel, bump = 'auto', prismaVersion = '' }) {
if (!BUMPS.includes(bump)) {
throw new Error(`Unknown bump '${bump}'. Expected one of: ${BUMPS.join(', ')}.`)
}
-
- const prisma = prismaVersion === '' ? null : parseStablePrismaVersion(prismaVersion)
-
- if (bump !== 'auto') {
- return bump
- }
- // 'auto' on stable mirrors the Prisma CLI release this extension ships:
- // x.0.0 -> major, x.y.0 -> minor, everything else (or no CLI bump) -> patch
- if (prisma !== null) {
- if (prisma.minor === 0 && prisma.patch === 0) {
- return 'major'
- }
- if (prisma.patch === 0) {
- return 'minor'
- }
- }
- return 'patch'
+ return bump
}
-export function planRelease({ channel, bump, prismaVersion, tags }) {
+export function planRelease({ channel, bump, tags }) {
const currentVersion = latestReleasedVersion({ tags })
- const type = releaseType({ channel, bump, prismaVersion })
+ const type = releaseType({ channel, bump })
const version = semVer.inc(currentVersion, type)
const stable = channel === 'stable'
@@ -84,10 +55,10 @@ export function planRelease({ channel, bump, prismaVersion, tags }) {
// Only run top-level code if this file is being executed directly (not imported)
if (fileURLToPath(import.meta.url) === argv[1]) {
- const [channel, bump = 'auto', prismaVersion = ''] = process.argv.slice(2)
+ const [channel, bump = 'patch'] = process.argv.slice(2)
const tags = execSync('git tag --list', { encoding: 'utf-8' }).split('\n')
- const plan = planRelease({ channel, bump, prismaVersion, tags })
+ const plan = planRelease({ channel, bump, tags })
console.log(plan)
for (const [key, value] of Object.entries(plan)) {
core.setOutput(key, value)
diff --git a/scripts/update_package_json_files.mjs b/scripts/update_package_json_files.mjs
index 75afeb9819..3702ab5773 100644
--- a/scripts/update_package_json_files.mjs
+++ b/scripts/update_package_json_files.mjs
@@ -17,7 +17,7 @@ function bumpVersionInVSCodeRepo({ version, name, displayName, description, prev
writeJsonToPackageJson({ content: content, path: vscodePackageJsonPath })
}
-async function bumpVersionsInRepo({ channel, newExtensionVersion, newPrismaVersion = '' }) {
+async function bumpVersionsInRepo({ channel, newExtensionVersion }) {
const languageServerPackageJsonPath = path.join(__dirname, '../packages/language-server/package.json')
const rootPackageJsonPath = path.join(__dirname, '../package.json')
@@ -43,36 +43,6 @@ async function bumpVersionsInRepo({ channel, newExtensionVersion, newPrismaVersi
})
}
- // update dependency and engines versions in packages/language-server/package.json
- if (newPrismaVersion !== '') {
- // Find the version needed for `@prisma/prisma-schema-wasm`
- // Let's look into the `package.json` of the `@prisma/engines` package
- // and get the version of `@prisma/engines-version` it uses
- const { stdout } = await execa('pnpm', ['show', `@prisma/engines@${newPrismaVersion}`, 'dependencies', '--json'])
- console.debug(stdout)
- const npmInfoOutput = JSON.parse(stdout)
- const engineVersion = npmInfoOutput['@prisma/engines-version'] // 2.26.0-23.9b816b3aa13cc270074f172f30d6eda8a8ce867d
- console.debug({ engineVersion })
- const engineSha = engineVersion.split('.')[3]
- console.debug({ engineSha })
-
- const languageServerPackageJson = getPackageJsonContent({
- path: languageServerPackageJsonPath,
- })
- // update engines sha
- languageServerPackageJson['prisma']['enginesVersion'] = engineSha
- // update engines version
- languageServerPackageJson['dependencies']['@prisma/config'] = newPrismaVersion
- languageServerPackageJson['dependencies']['@prisma/prisma-schema-wasm'] = engineVersion
- languageServerPackageJson['dependencies']['@prisma/schema-files-loader'] = newPrismaVersion
- // update CLI version
- languageServerPackageJson['prisma']['cliVersion'] = newPrismaVersion
- writeJsonToPackageJson({
- content: languageServerPackageJson,
- path: languageServerPackageJsonPath,
- })
- }
-
// update version in root package.json
const rootPackageJson = getPackageJsonContent({ path: rootPackageJsonPath })
rootPackageJson['version'] = newExtensionVersion
@@ -95,19 +65,8 @@ async function bumpVersionsInRepo({ channel, newExtensionVersion, newPrismaVersi
export { bumpVersionsInRepo }
const args = process.argv.slice(2)
-if (args.length === 3) {
- console.log('Bumping Prisma CLI version, extension and Language Server version in repo.')
- await bumpVersionsInRepo({
- channel: args[0],
- newExtensionVersion: args[1],
- newPrismaVersion: args[2],
- })
-} else if (args.length === 2) {
- console.log('Bumping extension and Language Server version in repo.')
- await bumpVersionsInRepo({
- channel: args[0],
- newExtensionVersion: args[1],
- })
-} else {
- throw new Error(`Expected 2 or 3 arguments, but received ${args.length}.`)
+if (args.length !== 2) {
+ throw new Error(`Expected 2 arguments (channel, version), but received ${args.length}.`)
}
+console.log('Bumping extension and Language Server version in repo.')
+await bumpVersionsInRepo({ channel: args[0], newExtensionVersion: args[1] })