From e9970fcad3302211fc706652de1a25e87da04176 Mon Sep 17 00:00:00 2001 From: Hunter Bown Date: Sun, 26 Apr 2026 12:22:15 -0500 Subject: [PATCH] ci: switch npm publish to NPM_TOKEN + add auto-tag workflow The OIDC Trusted Publisher path for npm has 404'd on PUT for v0.5.1, v0.5.2, and v0.6.1, even with valid OIDC tokens. Switch publish-npm and publish-npm-manual to a classic NPM_TOKEN automation token (set the NPM_TOKEN repo secret to a granular access token scoped to deepseek-tui with publish permission) so future releases ship reliably. Also add .github/workflows/auto-tag.yml: when the workspace version on main changes, push the matching v$VERSION tag automatically so release.yml fires without a manual tag push. Requires a RELEASE_TAG_PAT secret to trigger downstream workflows (GITHUB_TOKEN tag pushes don't trigger on: push: tags by design). Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/auto-tag.yml | 85 ++++++++++++++++++++++++++++++++++ .github/workflows/release.yml | 15 +++--- 2 files changed, 94 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/auto-tag.yml diff --git a/.github/workflows/auto-tag.yml b/.github/workflows/auto-tag.yml new file mode 100644 index 00000000..eb258efe --- /dev/null +++ b/.github/workflows/auto-tag.yml @@ -0,0 +1,85 @@ +name: Auto-tag on version bump + +# When the workspace version on `main` advances past the latest existing +# `vX.Y.Z` tag, push the matching tag automatically. The push then triggers +# `release.yml`, which runs parity, builds binaries, drafts the GitHub +# Release, and publishes the npm wrapper. +# +# IMPORTANT: tag pushes signed by the default `GITHUB_TOKEN` do NOT trigger +# downstream `on: push: tags` workflows (GitHub Actions safety rule). For +# this auto-tag flow to actually fire `release.yml`, store a PAT (or +# fine-grained token) with `contents: write` on this repo as the +# `RELEASE_TAG_PAT` secret. Without it, the tag is created but `release.yml` +# does NOT run automatically — you'd have to push the tag again manually +# (`git push origin v$VERSION` from a developer machine) to trigger release. + +on: + push: + branches: [main] + paths: + - 'Cargo.toml' + - 'npm/deepseek-tui/package.json' + workflow_dispatch: + +permissions: + contents: write + +jobs: + tag: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + # Prefer PAT so the resulting tag push triggers release.yml. + # Falls back to GITHUB_TOKEN, which will tag but NOT trigger. + token: ${{ secrets.RELEASE_TAG_PAT || github.token }} + + - name: Read workspace version + id: ver + run: | + v="$(grep -E '^version = "' Cargo.toml | head -n1 | sed -E 's/^version = "([^"]+)".*/\1/')" + if [ -z "$v" ]; then + echo "::error::Could not parse workspace version from Cargo.toml" >&2 + exit 1 + fi + echo "version=$v" >> "$GITHUB_OUTPUT" + echo "tag=v$v" >> "$GITHUB_OUTPUT" + echo "Workspace version: $v" + + - name: Check whether tag already exists + id: check + env: + TAG: ${{ steps.ver.outputs.tag }} + run: | + git fetch --tags --quiet + if git rev-parse -q --verify "refs/tags/${TAG}" >/dev/null \ + || git ls-remote --tags origin "refs/tags/${TAG}" | grep -q .; then + echo "exists=true" >> "$GITHUB_OUTPUT" + echo "Tag ${TAG} already exists; nothing to do." + else + echo "exists=false" >> "$GITHUB_OUTPUT" + echo "Tag ${TAG} does not exist; will create." + fi + + - name: Verify version consistency + if: steps.check.outputs.exists == 'false' + run: ./scripts/release/check-versions.sh + + - name: Create and push tag + if: steps.check.outputs.exists == 'false' + env: + TAG: ${{ steps.ver.outputs.tag }} + run: | + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git tag "${TAG}" + git push origin "${TAG}" + echo "Pushed ${TAG}. release.yml should now run (requires RELEASE_TAG_PAT for trigger)." + + - name: Warn if PAT missing + if: steps.check.outputs.exists == 'false' && env.HAS_PAT != 'true' + env: + HAS_PAT: ${{ secrets.RELEASE_TAG_PAT != '' }} + run: | + echo "::warning::RELEASE_TAG_PAT secret is not set. The tag was pushed using GITHUB_TOKEN, which does NOT trigger release.yml. Manually re-push the tag from a developer machine, or run 'gh workflow run release.yml --ref ${{ steps.ver.outputs.tag }}'." diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8a340617..274eefda 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -126,11 +126,13 @@ jobs: publish-npm: needs: release runs-on: ubuntu-latest - # Trusted Publishing via OIDC. Configure npm to trust this workflow - # filename (`release.yml`) for Hmbown/DeepSeek-TUI. + # Token-based publish (npm classic automation token). The OIDC + # Trusted Publisher path was unreliable across v0.5.1/v0.5.2/v0.6.1 + # (npm returned 404 on PUT despite valid OIDC). Set the `NPM_TOKEN` + # repo secret to a granular access token scoped to `deepseek-tui` + # with publish permission. permissions: contents: read - id-token: write steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -148,16 +150,15 @@ jobs: fi - name: Publish wrapper to npm working-directory: npm/deepseek-tui + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} run: npm publish --access public publish-npm-manual: if: github.event_name == 'workflow_dispatch' runs-on: ubuntu-latest - # npm can trust only one workflow filename; keep npm-only retries here so - # the trusted publisher can remain `release.yml`. permissions: contents: read - id-token: write steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -175,4 +176,6 @@ jobs: fi - name: Publish wrapper to npm working-directory: npm/deepseek-tui + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} run: npm publish --access public