From 83f8a95546b49a3a0f62c6b3ac0f06a3e53835a5 Mon Sep 17 00:00:00 2001 From: Josh Creek <8179928+jcreek@users.noreply.github.com> Date: Thu, 5 Mar 2026 22:00:50 +0000 Subject: [PATCH] build(*): Verify baseline tags --- .github/workflows/release.yml | 4 ++ package.json | 3 +- .../tech-radar-editor-backend/package.json | 4 ++ .../tech-radar-editor-backstage/package.json | 4 ++ packages/tech-radar-editor/package.json | 4 ++ scripts/verify-release-baseline.mjs | 55 +++++++++++++++++++ 6 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 scripts/verify-release-baseline.mjs diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3468e61..a2a59f2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -33,6 +33,9 @@ jobs: node-version: 22 cache: pnpm + - name: Verify release baseline tags + run: pnpm release:verify-baseline + - name: Install dependencies run: pnpm install --frozen-lockfile @@ -55,4 +58,5 @@ jobs: - name: Publish packages env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_CONFIG_PROVENANCE: true run: pnpm release diff --git a/package.json b/package.json index 75f91df..a06650e 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,8 @@ "commitlint": "commitlint", "dev": "pnpm --filter tech-radar-editor dev", "release": "pnpm -r --workspace-concurrency=1 --filter './packages/*' exec semantic-release", - "release:dry-run": "pnpm -r --workspace-concurrency=1 --filter './packages/*' exec semantic-release --dry-run" + "release:dry-run": "pnpm -r --workspace-concurrency=1 --filter './packages/*' exec semantic-release --dry-run", + "release:verify-baseline": "node scripts/verify-release-baseline.mjs" }, "engines": { "node": ">=18" diff --git a/packages/tech-radar-editor-backend/package.json b/packages/tech-radar-editor-backend/package.json index 4a4f537..148f063 100644 --- a/packages/tech-radar-editor-backend/package.json +++ b/packages/tech-radar-editor-backend/package.json @@ -16,6 +16,10 @@ }, "author": "Josh Creek", "license": "GPL-3.0", + "publishConfig": { + "provenance": true, + "registry": "https://registry.npmjs.org/" + }, "release": { "extends": [ "../../release.config.cjs", diff --git a/packages/tech-radar-editor-backstage/package.json b/packages/tech-radar-editor-backstage/package.json index f27f1a6..0c3e8ad 100644 --- a/packages/tech-radar-editor-backstage/package.json +++ b/packages/tech-radar-editor-backstage/package.json @@ -13,6 +13,10 @@ }, "author": "Josh Creek", "license": "GPL-3.0", + "publishConfig": { + "provenance": true, + "registry": "https://registry.npmjs.org/" + }, "release": { "extends": [ "../../release.config.cjs", diff --git a/packages/tech-radar-editor/package.json b/packages/tech-radar-editor/package.json index 6ce5fcd..0424132 100644 --- a/packages/tech-radar-editor/package.json +++ b/packages/tech-radar-editor/package.json @@ -20,6 +20,10 @@ ], "author": "Josh Creek", "license": "GPL-3.0", + "publishConfig": { + "provenance": true, + "registry": "https://registry.npmjs.org/" + }, "release": { "extends": [ "../../release.config.cjs", diff --git a/scripts/verify-release-baseline.mjs b/scripts/verify-release-baseline.mjs new file mode 100644 index 0000000..8eab38f --- /dev/null +++ b/scripts/verify-release-baseline.mjs @@ -0,0 +1,55 @@ +import { readdirSync, readFileSync } from 'node:fs'; +import { join } from 'node:path'; +import { execFileSync } from 'node:child_process'; + +const packagesDir = join(process.cwd(), 'packages'); + +const packageDirs = readdirSync(packagesDir, { withFileTypes: true }) + .filter((entry) => entry.isDirectory()) + .map((entry) => join(packagesDir, entry.name)); + +const missingTags = []; + +for (const packageDir of packageDirs) { + const manifestPath = join(packageDir, 'package.json'); + const manifest = JSON.parse(readFileSync(manifestPath, 'utf8')); + + if (manifest.private) { + continue; + } + + const expectedTag = `${manifest.name}-v${manifest.version}`; + const existingTag = execFileSync('git', ['tag', '--list', expectedTag], { + cwd: process.cwd(), + encoding: 'utf8', + }).trim(); + + if (!existingTag) { + missingTags.push({ + name: manifest.name, + version: manifest.version, + tag: expectedTag, + }); + } +} + +if (missingTags.length > 0) { + console.error('Release baseline is incomplete.'); + console.error('Create tags for the versions that were already published before semantic-release was enabled:'); + + for (const pkg of missingTags) { + console.error(`- ${pkg.name}: expected tag ${pkg.tag}`); + } + + console.error(''); + console.error('Example commands:'); + + for (const pkg of missingTags) { + console.error(` git tag ${pkg.tag}`); + } + + console.error(' git push origin --tags'); + process.exit(1); +} + +console.log('Release baseline tags are present for all publishable packages.');