From ec4007cd239d306b3d2faabe0bf714f0419102ec Mon Sep 17 00:00:00 2001 From: Haze <709547807@qq.com> Date: Mon, 20 Apr 2026 18:43:53 +0800 Subject: [PATCH] chore(release): update version to 0.3.10-beta.4 and enhance release validation - Bump version in package.json to 0.3.10-beta.4. - Add a new GitHub Actions job to validate that the version in package.json matches the release tag. - Introduce scripts for versioning and release validation to streamline the release process. --- .github/workflows/release.yml | 11 +++++++ package.json | 5 ++- scripts/assert-release-version.mjs | 45 ++++++++++++++++++++++++++ scripts/assert-tag-matches-package.mjs | 35 ++++++++++++++++++++ 4 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 scripts/assert-release-version.mjs create mode 100644 scripts/assert-tag-matches-package.mjs diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index aed1724..3bc3f03 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,7 +18,18 @@ permissions: actions: read jobs: + # Fails fast on tag pushes if package.json "version" does not match the tag. + validate-release: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Assert tag matches package.json + run: node scripts/assert-tag-matches-package.mjs + release: + needs: validate-release strategy: matrix: include: diff --git a/package.json b/package.json index 7188b90..f4e4adf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "clawx", - "version": "0.3.10-beta.3", + "version": "0.3.10-beta.4", "pnpm": { "onlyBuiltDependencies": [ "@discordjs/opus", @@ -62,9 +62,12 @@ "package:win": "pnpm run prep:win-binaries && pnpm run package && electron-builder --win --publish never", "package:linux": "pnpm run package && electron-builder --linux --publish never", "release": "pnpm run uv:download && pnpm run package && electron-builder --publish always", + "version": "node scripts/assert-release-version.mjs", "version:patch": "pnpm version patch", "version:minor": "pnpm version minor", "version:major": "pnpm version major", + "version:prerelease-beta": "pnpm version prerelease --preid=beta", + "release:validate": "node scripts/assert-tag-matches-package.mjs", "postversion": "git push && git push --tags" }, "dependencies": { diff --git a/scripts/assert-release-version.mjs b/scripts/assert-release-version.mjs new file mode 100644 index 0000000..03ca9fb --- /dev/null +++ b/scripts/assert-release-version.mjs @@ -0,0 +1,45 @@ +#!/usr/bin/env node +/** + * npm/pnpm `version` lifecycle hook: runs after package.json is bumped, before + * `git tag`. Aborts if the target tag already exists so we never fail late on + * `fatal: tag 'vX.Y.Z' already exists`. + */ +import { readFileSync } from 'node:fs'; +import { execSync } from 'node:child_process'; +import { dirname, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const root = join(dirname(fileURLToPath(import.meta.url)), '..'); + +function readPackageVersion() { + const raw = readFileSync(join(root, 'package.json'), 'utf8'); + return JSON.parse(raw).version; +} + +const version = process.env.npm_package_version || readPackageVersion(); +const tag = `v${version}`; + +function localTagExists(t) { + try { + execSync(`git rev-parse -q --verify refs/tags/${t}`, { stdio: 'pipe' }); + return true; + } catch { + return false; + } +} + +if (localTagExists(tag)) { + console.error(` +Release version check failed: git tag ${tag} already exists locally. + +You cannot run \`pnpm version …\` for ${version} until that tag is gone or the +version is bumped to a value that does not yet have a tag. + +Typical fixes: + • Use the next prerelease explicitly, e.g. \`pnpm version 0.3.10-beta.4\` + • Or delete only if you are sure it was created by mistake: \`git tag -d ${tag}\` +`); + process.exit(1); +} + +console.log(`Release version OK: tag ${tag} is not present locally yet.`); diff --git a/scripts/assert-tag-matches-package.mjs b/scripts/assert-tag-matches-package.mjs new file mode 100644 index 0000000..1622395 --- /dev/null +++ b/scripts/assert-tag-matches-package.mjs @@ -0,0 +1,35 @@ +#!/usr/bin/env node +/** + * CI / global release sanity: when building from a version tag, the root + * package.json "version" must match the tag (without the leading "v"). + * + * Exits 0 when GITHUB_REF is not refs/tags/v* (e.g. branch builds, PRs). + */ +import { readFileSync } from 'node:fs'; +import { join, dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const root = join(dirname(fileURLToPath(import.meta.url)), '..'); +const ref = process.env.GITHUB_REF || ''; + +if (!ref.startsWith('refs/tags/v')) { + console.log( + `[assert-tag-matches-package] Skip: GITHUB_REF is not a version tag (${ref || '(empty)'})`, + ); + process.exit(0); +} + +const tagVersion = ref.slice('refs/tags/v'.length); +const pkgVersion = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8')).version; + +if (tagVersion !== pkgVersion) { + console.error( + `[assert-tag-matches-package] Mismatch: git tag is "${tagVersion}" but package.json version is "${pkgVersion}".`, + ); + console.error( + 'Push a commit that sets package.json "version" to match the tag before cutting the release.', + ); + process.exit(1); +} + +console.log(`[assert-tag-matches-package] OK: tag v${tagVersion} matches package.json.`);