chore: switch releases to tag-based publishing
Some checks failed
Release / release (push) Has been cancelled
Some checks failed
Release / release (push) Has been cancelled
This commit is contained in:
parent
88f9742221
commit
706e31b23d
124
.github/workflows/release.yml
vendored
124
.github/workflows/release.yml
vendored
@ -1,17 +1,9 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
increment:
|
||||
description: "Version bump (patch, minor, major)"
|
||||
required: true
|
||||
default: "patch"
|
||||
type: choice
|
||||
options:
|
||||
- patch
|
||||
- minor
|
||||
- major
|
||||
push:
|
||||
tags:
|
||||
- "v*.*.*"
|
||||
|
||||
concurrency:
|
||||
group: release-${{ github.workflow }}-${{ github.ref }}
|
||||
@ -30,7 +22,7 @@ jobs:
|
||||
# "Unsupported GitHub Actions runner environment: self-hosted".
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
contents: read
|
||||
id-token: write
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
@ -47,8 +39,6 @@ jobs:
|
||||
check-latest: true
|
||||
cache: pnpm
|
||||
|
||||
- run: git config user.name "github-actions[bot]"
|
||||
- run: git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
- run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Validate package metadata for trusted publishing
|
||||
@ -92,47 +82,73 @@ jobs:
|
||||
console.log("Package metadata validated.");
|
||||
NODE
|
||||
|
||||
- name: Validate release tag
|
||||
env:
|
||||
RELEASE_SHA: ${{ github.sha }}
|
||||
RELEASE_TAG: ${{ github.ref_name }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
git fetch --no-tags origin main --depth=1
|
||||
|
||||
node - <<'NODE'
|
||||
const { execFileSync } = require("node:child_process");
|
||||
const { readFileSync } = require("node:fs");
|
||||
|
||||
const releaseTag = process.env.RELEASE_TAG ?? "";
|
||||
const releaseSha = process.env.RELEASE_SHA ?? "";
|
||||
const semverTag = /^v\d+\.\d+\.\d+$/;
|
||||
|
||||
if (!semverTag.test(releaseTag)) {
|
||||
console.error(
|
||||
`Release tags must match vX.Y.Z; received ${releaseTag || "<missing>"}.`
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const pkg = JSON.parse(readFileSync("package.json", "utf8"));
|
||||
const expectedTag = `v${pkg.version}`;
|
||||
|
||||
if (releaseTag !== expectedTag) {
|
||||
console.error(
|
||||
`Release tag ${releaseTag} does not match package.json version ${pkg.version}; expected ${expectedTag}.`
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
try {
|
||||
execFileSync(
|
||||
"git",
|
||||
["merge-base", "--is-ancestor", releaseSha, "origin/main"],
|
||||
{ stdio: "ignore" }
|
||||
);
|
||||
} catch {
|
||||
console.error(
|
||||
`Tagged commit ${releaseSha} is not contained in origin/main.`
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(
|
||||
`Release tag ${releaseTag} matches package.json and points to a commit on origin/main.`
|
||||
);
|
||||
NODE
|
||||
|
||||
- name: Ensure version is not already published
|
||||
run: |
|
||||
set -euo pipefail
|
||||
PACKAGE_VERSION=$(node -p "require('./package.json').version")
|
||||
PUBLISHED_VERSION=$(npm view acpx version 2>/dev/null || true)
|
||||
|
||||
if [ "$PUBLISHED_VERSION" = "$PACKAGE_VERSION" ]; then
|
||||
echo "acpx@$PACKAGE_VERSION is already published on npm."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Publishing acpx@$PACKAGE_VERSION"
|
||||
|
||||
- run: pnpm run lint
|
||||
- run: pnpm run typecheck
|
||||
- run: pnpm run build
|
||||
|
||||
# Sync the working tree to the currently published version, then let
|
||||
# release-it perform the requested bump from that baseline.
|
||||
- name: Bump version from npm registry
|
||||
run: |
|
||||
LATEST=$(npm view acpx version 2>/dev/null || echo "0.0.0")
|
||||
echo "Latest on npm: $LATEST"
|
||||
TARGET=$(node - "$LATEST" "${{ inputs.increment }}" <<'NODE'
|
||||
const [version, increment] = process.argv.slice(2);
|
||||
const match = /^(\d+)\.(\d+)\.(\d+)$/.exec(version);
|
||||
if (!match) {
|
||||
throw new Error(`Unsupported semver: ${version}`);
|
||||
}
|
||||
const [major, minor, patch] = match.slice(1).map(Number);
|
||||
|
||||
if (increment === "patch") {
|
||||
console.log(`${major}.${minor}.${patch + 1}`);
|
||||
process.exit(0);
|
||||
}
|
||||
if (increment === "minor") {
|
||||
console.log(`${major}.${minor + 1}.0`);
|
||||
process.exit(0);
|
||||
}
|
||||
if (increment === "major") {
|
||||
console.log(`${major + 1}.0.0`);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
throw new Error(`Unsupported increment: ${increment}`);
|
||||
NODE
|
||||
)
|
||||
npm version --no-git-tag-version "$LATEST" --allow-same-version
|
||||
echo "VERSION=$TARGET" >> "$GITHUB_ENV"
|
||||
echo "Releasing: $TARGET"
|
||||
|
||||
- name: Release
|
||||
run: |
|
||||
pnpm exec release-it "$VERSION" --ci
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
NPM_CONFIG_PROVENANCE: "true"
|
||||
- name: Publish
|
||||
run: npm publish --access public --provenance
|
||||
|
||||
@ -178,11 +178,12 @@ CI lives in [`.github/workflows/ci.yml`](.github/workflows/ci.yml).
|
||||
|
||||
Release automation lives in [`.github/workflows/release.yml`](.github/workflows/release.yml).
|
||||
|
||||
- Releases are manual (`workflow_dispatch`)
|
||||
- Releases run when a `vX.Y.Z` tag is pushed
|
||||
- The workflow installs dependencies with `pnpm install --frozen-lockfile`
|
||||
- It validates `package.json` release metadata before publishing
|
||||
- It validates that the tag matches `package.json` version and that the tagged commit is on `main`
|
||||
- It runs `pnpm run lint`, `pnpm run typecheck`, and `pnpm run build`
|
||||
- It bumps from the latest npm version and publishes through `release-it`
|
||||
- It publishes directly to npm with trusted publishing and provenance
|
||||
|
||||
The release workflow currently requires these `package.json` values:
|
||||
|
||||
|
||||
2207
package-lock.json
generated
2207
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -46,8 +46,6 @@
|
||||
"precommit": "pnpm exec lint-staged && pnpm run -s build",
|
||||
"prepack": "pnpm run build",
|
||||
"prepare": "husky",
|
||||
"release": "release-it",
|
||||
"release:ci": "release-it --ci",
|
||||
"test": "pnpm run build:test && node --test dist-test/test/*.test.js",
|
||||
"test:coverage": "pnpm run build:test && node --experimental-test-coverage --test-coverage-lines=83 --test-coverage-branches=76 --test-coverage-functions=86 --test dist-test/test/*.test.js",
|
||||
"typecheck": "tsgo --noEmit",
|
||||
@ -67,7 +65,6 @@
|
||||
"oxfmt": "^0.36.0",
|
||||
"oxlint": "^1.51.0",
|
||||
"oxlint-tsgolint": "^0.16.0",
|
||||
"release-it": "^19.2.4",
|
||||
"tsdown": "^0.21.0-beta.2",
|
||||
"tsx": "^4.0.0",
|
||||
"typescript": "^5.7.0"
|
||||
|
||||
1389
pnpm-lock.yaml
generated
1389
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user