Skip to content

Merge pull request #60 from prisma/feat/node-22-floor #49

Merge pull request #60 from prisma/feat/node-22-floor

Merge pull request #60 from prisma/feat/node-22-floor #49

Workflow file for this run

name: Publish CLI
on:
push:
branches:
- main
workflow_dispatch:
inputs:
dry_run:
description: Validate the next official beta release without publishing or tagging
required: false
type: boolean
default: false
concurrency:
group: publish-cli-${{ github.event_name }}
cancel-in-progress: false
jobs:
publish-dev:
if: ${{ github.event_name == 'push' }}
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd
with:
persist-credentials: false
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e
with:
node-version: 24
registry-url: https://registry.npmjs.org
- name: Enable pnpm
run: |
corepack enable
PNPM_VERSION="$(node -p 'const pm = require("./package.json").packageManager; const match = pm && pm.match(/^pnpm@(.+)$/); if (!match) throw new Error("packageManager must be pnpm@<version>"); match[1]')"
corepack prepare "pnpm@${PNPM_VERSION}" --activate
echo "PNPM_STORE_PATH=$(pnpm store path)" >> "$GITHUB_ENV"
- name: Cache pnpm store
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830
with:
path: ${{ env.PNPM_STORE_PATH }}
key: pnpm-store-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
restore-keys: |
pnpm-store-${{ runner.os }}-
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Resolve dev version
id: cli_version
run: |
node scripts/resolve-cli-version.mjs dev \
--run-number "${GITHUB_RUN_NUMBER}" \
--run-attempt "${GITHUB_RUN_ATTEMPT}" >> "$GITHUB_OUTPUT"
- name: Fail if version already exists on npm
run: |
PACKAGE='@prisma/cli'
VERSION='${{ steps.cli_version.outputs.version }}'
if npm view "${PACKAGE}@${VERSION}" version >/dev/null 2>&1; then
echo "${PACKAGE}@${VERSION} already exists on npm."
exit 1
fi
- name: Run focused CLI tests
run: pnpm --filter @prisma/cli test
- name: Build CLI package
run: pnpm --filter @prisma/cli build
- name: Prepare staged publish package
run: node scripts/prepare-cli-publish.mjs .publish/cli --version '${{ steps.cli_version.outputs.version }}'
- name: Audit staged package contents
working-directory: .publish/cli
run: |
PACK_JSON="$(npm pack --dry-run --json)"
PACK_JSON="${PACK_JSON}" node -e "
const pack = JSON.parse(process.env.PACK_JSON)[0]
const files = pack.files.map((file) => file.path).sort()
const forbidden = files.filter((file) =>
file.startsWith('src/') ||
file.startsWith('tests/') ||
file.startsWith('fixtures/') ||
file.startsWith('docs/') ||
file.startsWith('.prisma/') ||
file.startsWith('.publish/')
)
if (forbidden.length) {
console.error('Forbidden files in npm package:', forbidden.join(', '))
process.exit(1)
}
for (const required of ['dist/cli.js', 'README.md', 'LICENSE', 'package.json']) {
if (!files.includes(required)) {
console.error('Missing required package file:', required)
process.exit(1)
}
}
"
- name: Smoke test staged tarball install
run: |
TARBALL="$(cd .publish/cli && npm pack --silent)"
TMPDIR="$(mktemp -d)"
cat > "${TMPDIR}/package.json" <<'EOF'
{
"name": "cli-publish-smoke",
"private": true
}
EOF
pnpm add -D "${PWD}/.publish/cli/${TARBALL}" --dir "${TMPDIR}"
(
cd "${TMPDIR}"
pnpm prisma-cli --help
pnpm prisma-cli auth whoami --json
)
- name: Publish dev package to npm
working-directory: .publish/cli
run: npm publish --access public --tag dev --provenance
- name: Summarize dev publish
run: |
VERSION='${{ steps.cli_version.outputs.version }}'
{
echo "## Publish CLI Dev"
echo
echo "- npm package: \`@prisma/cli@${VERSION}\`"
echo "- npm dist-tag: \`dev\`"
} >> "$GITHUB_STEP_SUMMARY"
publish-official:
if: ${{ github.event_name == 'workflow_dispatch' }}
runs-on: ubuntu-latest
permissions:
contents: write
id-token: write
steps:
- name: Ensure workflow runs from main
run: |
if [ "${GITHUB_REF}" != "refs/heads/main" ]; then
echo "This workflow only publishes official releases from main."
exit 1
fi
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd
with:
fetch-depth: 0
persist-credentials: false
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e
with:
node-version: 24
registry-url: https://registry.npmjs.org
- name: Enable pnpm
run: |
corepack enable
PNPM_VERSION="$(node -p 'const pm = require("./package.json").packageManager; const match = pm && pm.match(/^pnpm@(.+)$/); if (!match) throw new Error("packageManager must be pnpm@<version>"); match[1]')"
corepack prepare "pnpm@${PNPM_VERSION}" --activate
echo "PNPM_STORE_PATH=$(pnpm store path)" >> "$GITHUB_ENV"
- name: Cache pnpm store
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830
with:
path: ${{ env.PNPM_STORE_PATH }}
key: pnpm-store-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
restore-keys: |
pnpm-store-${{ runner.os }}-
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Resolve next beta version
id: cli_version
run: |
PACKAGE='@prisma/cli'
LATEST="$(npm view "${PACKAGE}" dist-tags.latest --silent 2>/dev/null || true)"
node scripts/resolve-cli-version.mjs next-beta --latest "${LATEST}" >> "$GITHUB_OUTPUT"
- name: Fail if version already exists on npm
run: |
PACKAGE='@prisma/cli'
VERSION='${{ steps.cli_version.outputs.version }}'
if npm view "${PACKAGE}@${VERSION}" version >/dev/null 2>&1; then
echo "${PACKAGE}@${VERSION} already exists on npm."
exit 1
fi
- name: Fail if release tag already exists
run: |
VERSION='${{ steps.cli_version.outputs.version }}'
TAG="cli-v${VERSION}"
if git ls-remote --exit-code --tags origin "refs/tags/${TAG}" >/dev/null 2>&1; then
echo "Release tag ${TAG} already exists."
exit 1
fi
- name: Run focused CLI tests
run: pnpm --filter @prisma/cli test
- name: Build CLI package
run: pnpm --filter @prisma/cli build
- name: Prepare staged publish package
run: node scripts/prepare-cli-publish.mjs .publish/cli --version '${{ steps.cli_version.outputs.version }}'
- name: Audit staged package contents
working-directory: .publish/cli
run: |
PACK_JSON="$(npm pack --dry-run --json)"
PACK_JSON="${PACK_JSON}" node -e "
const pack = JSON.parse(process.env.PACK_JSON)[0]
const files = pack.files.map((file) => file.path).sort()
const forbidden = files.filter((file) =>
file.startsWith('src/') ||
file.startsWith('tests/') ||
file.startsWith('fixtures/') ||
file.startsWith('docs/') ||
file.startsWith('.prisma/') ||
file.startsWith('.publish/')
)
if (forbidden.length) {
console.error('Forbidden files in npm package:', forbidden.join(', '))
process.exit(1)
}
for (const required of ['dist/cli.js', 'README.md', 'LICENSE', 'package.json']) {
if (!files.includes(required)) {
console.error('Missing required package file:', required)
process.exit(1)
}
}
"
- name: Smoke test staged tarball install
run: |
TARBALL="$(cd .publish/cli && npm pack --silent)"
TMPDIR="$(mktemp -d)"
cat > "${TMPDIR}/package.json" <<'EOF'
{
"name": "cli-publish-smoke",
"private": true
}
EOF
pnpm add -D "${PWD}/.publish/cli/${TARBALL}" --dir "${TMPDIR}"
(
cd "${TMPDIR}"
pnpm prisma-cli --help
pnpm prisma-cli auth whoami --json
)
- name: Ensure release still targets the latest main
if: ${{ !inputs.dry_run }}
run: |
git fetch origin main
if [ "$(git rev-parse HEAD)" != "$(git rev-parse origin/main)" ]; then
echo "main moved while the release was running. Rerun the workflow from the latest main."
exit 1
fi
- name: Publish official package to npm
if: ${{ !inputs.dry_run }}
working-directory: .publish/cli
run: npm publish --access public --tag latest --provenance
- name: Create release tag
if: ${{ !inputs.dry_run }}
env:
GH_TOKEN: ${{ github.token }}
run: |
VERSION='${{ steps.cli_version.outputs.version }}'
TAG="cli-v${VERSION}"
SHA="$(git rev-parse HEAD)"
gh api \
--method POST \
"repos/${GITHUB_REPOSITORY}/git/refs" \
-f ref="refs/tags/${TAG}" \
-f sha="${SHA}"
- name: Summarize release
run: |
VERSION='${{ steps.cli_version.outputs.version }}'
LATEST='${{ steps.cli_version.outputs.latest }}'
{
echo "## Publish CLI Official"
echo
echo "- Previous npm latest: \`${LATEST:-none}\`"
echo "- Version: \`${VERSION}\`"
echo "- Dry run: \`${{ inputs.dry_run }}\`"
if [ '${{ inputs.dry_run }}' = 'true' ]; then
echo "- Publish: skipped"
echo "- Tag creation: skipped"
else
echo "- npm package: \`@prisma/cli@${VERSION}\`"
echo "- npm dist-tag: \`latest\`"
echo "- git tag: \`cli-v${VERSION}\`"
fi
} >> "$GITHUB_STEP_SUMMARY"