From 77ef5483ed0e9b8af381f1f530e32d386ba7243e Mon Sep 17 00:00:00 2001 From: SikongJueluo Date: Thu, 17 Sep 2026 17:59:00 +0800 Subject: [PATCH] ci(publish): add tag-driven npm publish workflow - add .github/workflows/publish.yml triggered by @ tags - verify tag matches package.json name and version before publishing - run check and test before publishing with npm provenance - pin pnpm via packageManager field for pnpm/action-setup - document the release flow in both READMEs --- .github/workflows/publish.yml | 71 +++++++++++++++++++++++++++++++++++ README.md | 11 ++++++ README.zh-CN.md | 11 ++++++ package.json | 1 + 4 files changed, 94 insertions(+) create mode 100644 .github/workflows/publish.yml diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..3ad2641 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,71 @@ +# Publishes a single package when a `@` tag is pushed. +# The tag must match name+version in packages//package.json exactly; +# otherwise the workflow fails without touching the registry. +name: publish + +on: + push: + tags: + - "*@*" + +permissions: + contents: read + id-token: write # npm provenance; remove if the repository is private + +concurrency: + group: publish-${{ github.ref_name }} + cancel-in-progress: false + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + + - uses: pnpm/action-setup@v4 # reads packageManager from package.json + + - uses: actions/setup-node@v5 + with: + node-version: 24 + registry-url: https://registry.npmjs.org + cache: pnpm + + - name: Resolve package from tag + id: pkg + run: | + tag="${GITHUB_REF_NAME}" + name="${tag%@*}" # strip @version (handles @scope/ names) + version="${tag##*@}" + dir="packages/${name#*/}" + if [ ! -f "$dir/package.json" ]; then + echo "::error::no package at $dir for tag $tag" >&2 + exit 1 + fi + echo "name=$name" >> "$GITHUB_OUTPUT" + echo "version=$version" >> "$GITHUB_OUTPUT" + echo "dir=$dir" >> "$GITHUB_OUTPUT" + + - name: Verify tag matches package.json + run: | + name="${{ steps.pkg.outputs.name }}" + version="${{ steps.pkg.outputs.version }}" + dir="${{ steps.pkg.outputs.dir }}" + pkg_name=$(jq -r '.name' "$dir/package.json") + pkg_version=$(jq -r '.version' "$dir/package.json") + if [ "$pkg_name" != "$name" ] || [ "$pkg_version" != "$version" ]; then + echo "::error::tag $name@$version does not match $dir/package.json ($pkg_name@$pkg_version)" >&2 + exit 1 + fi + echo "Publishing $pkg_name@$pkg_version" + + - run: pnpm install --frozen-lockfile + + - run: pnpm -r check + + - run: pnpm -r test + + - name: Publish + run: pnpm --filter "${{ steps.pkg.outputs.name }}" publish --no-git-checks + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + NPM_CONFIG_PROVENANCE: true diff --git a/README.md b/README.md index 221e074..2a8ba89 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,17 @@ pnpm test # vitest run Design decisions live in [docs/adr/](docs/adr/). +## Release + +Bump the version in `packages//package.json`, commit, then tag and push: + +```bash +jj tag set @sikongjueluo/pi-permission-ai-judge@0.1.0 -r +jj git push # pushes the bookmark and new tags +``` + +The [publish workflow](.github/workflows/publish.yml) verifies the tag matches the `package.json` name and version, runs check and tests, then publishes to npm with provenance. Requires the `NPM_TOKEN` repository secret (granular token with publish rights on the `@sikongjueluo` scope, or a classic automation token). + ## License GPL-3.0 diff --git a/README.zh-CN.md b/README.zh-CN.md index 944b517..ece32b4 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -50,6 +50,17 @@ pnpm test # vitest run 设计决策见 [docs/adr/](docs/adr/)。 +## 发版 + +先改 `packages//package.json` 的版本号并提交,然后打 tag、推送: + +```bash +jj tag set @sikongjueluo/pi-permission-ai-judge@0.1.0 -r +jj git push # 推送 bookmark 和新 tag +``` + +[发布工作流](.github/workflows/publish.yml)会校验 tag 与 `package.json` 的 name、version 完全一致,跑 check 和 test,通过后带 provenance 发布到 npm。需要在仓库配置 `NPM_TOKEN` secret(对 `@sikongjueluo` scope 有发布权限的 granular token,或经典 automation token)。 + ## License GPL-3.0 diff --git a/package.json b/package.json index 3fffb06..f664dae 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "publish:packages": "pnpm -r publish --no-git-checks" }, "type": "module", + "packageManager": "pnpm@11.25.0", "private": true, "dependencies": { "@gotgenes/pi-permission-system": "^32.0.2"