import { readFileSync } from 'node:fs' import { fileURLToPath } from 'node:url' import * as semver from 'semver' import { $ } from 'zx' // How to test release script locally: // RELEASE_VERSION=5.0.0-beta.5 pnpm release // VITE_TEST_WATCHER_DEBUG=false PUBLISH_DRY_RUN=true PUBLISH_BRANCH=main pnpm publish-ci 5.0.0-beta.5 const $$ = $({ stdio: 'inherit' }) async function main() { if (process.env.VITE_TEST_WATCHER_DEBUG !== 'false') { throw new Error( `Cannot release Vitest without VITE_TEST_WATCHER_DEBUG=${process.env.VITE_TEST_WATCHER_DEBUG} environment variable. `, ) } const version = process.argv[2] if (!version) { throw new Error('Missing argument to specify version') } const pkgPath = fileURLToPath(new URL('../package.json', import.meta.url)) const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8')) if (pkg.version !== version) { throw new Error( `Input version "${version}" does not match package.json version "${pkg.version}"`, ) } const publishBranch = process.env.PUBLISH_BRANCH if (!publishBranch) { throw new Error('Missing PUBLISH_BRANCH environment variable') } const releaseTag = await getReleaseTag(version, publishBranch) const dryRun = process.env.PUBLISH_DRY_RUN === 'true' if (dryRun) { console.log('== DRY RUN ==') } console.log(`Staging version '${version}' with tag '${releaseTag}'`) await $$`pnpm -r stage publish --access public --no-git-checks --tag ${releaseTag} ${dryRun ? ['--dry-run'] : []}` } async function getReleaseTag(version: string, publishBranch: string) { // Always specify the dist-tag explicitly since otherwise `latest` would be overwritten. // Note that `main` branch doesn't always mean `latest` tag because of pre-release phase. // check prerelease e.g. beta, alpha, rc const parsed = semver.parse(version, {}, true) if (parsed.prerelease.length > 0) { return parsed.prerelease[0] } // If the version is not a pre-release and is greater than the latest version on npm, // then that should become the new latest version. const npmView = await $`npm view vitest dist-tags --json` const latestVersion = JSON.parse(npmView.stdout).latest if (semver.gt(version, latestVersion)) { return 'latest' } // Otherwise this is a backport release. // Use the uppercase of the branch name to avoid npm dist-tag caveats // https://docs.npmjs.com/cli/v11/commands/npm-dist-tag#caveats // - v4 branch -> V4 dist tag // - v4.1 branch -> V4.1 dist tag return publishBranch.toUpperCase() } main().catch((error) => { console.error('Error during publishing:', error) process.exit(1) })