From b53aa0c4a093130a0a3ab1060875e8526e199f72 Mon Sep 17 00:00:00 2001 From: wenxin-jiang Date: Wed, 1 Apr 2026 16:00:45 -0400 Subject: [PATCH 1/4] fix: simplify release to workflow_dispatch (no bot commits needed) Replace the two-workflow PR-based release flow with a single workflow_dispatch trigger, matching the socket-cli pattern. Changes: - Remove release-prep.yml (automated version bump + PR creation) - Make release.yml a manual workflow_dispatch that reads the version from Cargo.toml, tags, builds, and publishes - Add dry-run option to build without publishing - Use NPM_TOKEN secret for npm publish (fixes ENEEDAUTH on new packages) - Add registry-url to setup-node for proper auth Release flow after this change: 1. Bump version in a PR: run scripts/version-sync.sh, commit, merge 2. Click "Run workflow" on Release 3. Done - tags, builds, and publishes automatically This avoids the signed commit requirement that blocked github-actions[bot] from pushing to protected branches. Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/release-prep.yml | 68 ------------------------- .github/workflows/release.yml | 80 +++++++++++++++++------------- 2 files changed, 45 insertions(+), 103 deletions(-) delete mode 100644 .github/workflows/release-prep.yml diff --git a/.github/workflows/release-prep.yml b/.github/workflows/release-prep.yml deleted file mode 100644 index a42f2e9..0000000 --- a/.github/workflows/release-prep.yml +++ /dev/null @@ -1,68 +0,0 @@ -name: Prep Release - -on: - workflow_dispatch: - inputs: - bump: - description: 'Version bump type' - required: true - default: 'patch' - type: choice - options: - - patch - - minor - - major - -permissions: {} - -jobs: - create-release-pr: - runs-on: ubuntu-latest - permissions: - contents: write - pull-requests: write - steps: - - name: Checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - - name: Configure Git - run: | - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - - - name: Bump version and sync - id: sync - run: | - CURRENT=$(grep '^version = ' Cargo.toml | head -1 | sed 's/version = "\(.*\)"/\1/') - IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT" - case "${{ inputs.bump }}" in - major) MAJOR=$((MAJOR + 1)); MINOR=0; PATCH=0 ;; - minor) MINOR=$((MINOR + 1)); PATCH=0 ;; - patch) PATCH=$((PATCH + 1)) ;; - esac - VERSION="${MAJOR}.${MINOR}.${PATCH}" - echo "VERSION=$VERSION" >> "$GITHUB_OUTPUT" - bash scripts/version-sync.sh "$VERSION" - - - name: Create release branch and PR - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - VERSION="${{ steps.sync.outputs.VERSION }}" - BRANCH="release/v${VERSION}" - git checkout -b "$BRANCH" - git add Cargo.toml npm/ pypi/ - git commit -m "v${VERSION}: bump and sync package versions" - git push origin "$BRANCH" - gh pr create \ - --title "v${VERSION}: bump and sync package versions" \ - --body "## Release v${VERSION} - - Automated version bump (${{ inputs.bump }}). - - **Merge this PR to trigger the release workflow**, which will: - 1. Tag the merge commit as \`v${VERSION}\` - 2. Build binaries for all platforms - 3. Publish to npm, crates.io, PyPI, and GitHub Releases" \ - --base main \ - --head "$BRANCH" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d48d4b1..0beb42f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,30 +1,44 @@ name: Release on: - pull_request: - types: [closed] - branches: [main] + workflow_dispatch: + inputs: + dry-run: + description: 'Dry run (build only, skip publish)' + type: boolean + default: false permissions: {} jobs: - check-release: - if: github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'release/v') + version: runs-on: ubuntu-latest outputs: - version: ${{ steps.extract.outputs.VERSION }} + version: ${{ steps.read.outputs.VERSION }} steps: - - name: Extract version from branch name - id: extract - env: - HEAD_REF: ${{ github.event.pull_request.head.ref }} + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - name: Read version from Cargo.toml + id: read run: | - VERSION="${HEAD_REF#release/v}" + VERSION=$(grep '^version = ' Cargo.toml | head -1 | sed 's/version = "\(.*\)"/\1/') echo "VERSION=$VERSION" >> "$GITHUB_OUTPUT" - echo "Detected release version: $VERSION" + echo "Release version: $VERSION" + + - name: Check tag does not exist + run: | + VERSION="${{ steps.read.outputs.VERSION }}" + if git rev-parse "v${VERSION}" >/dev/null 2>&1; then + echo "::error::Tag v${VERSION} already exists. Bump the version in a PR first." + exit 1 + fi tag: - needs: check-release + needs: version + if: ${{ !inputs.dry-run }} runs-on: ubuntu-latest permissions: contents: write @@ -32,24 +46,15 @@ jobs: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - name: Configure Git - run: | - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - - name: Create and push tag run: | - VERSION="${{ needs.check-release.outputs.version }}" - TAG="v${VERSION}" - if git rev-parse "$TAG" >/dev/null 2>&1; then - echo "::error::Tag $TAG already exists." - exit 1 - fi + TAG="v${{ needs.version.outputs.version }}" git tag "$TAG" git push origin "$TAG" build: - needs: [check-release, tag] + needs: [version, tag] + if: ${{ always() && needs.version.result == 'success' && (needs.tag.result == 'success' || needs.tag.result == 'skipped') }} strategy: matrix: include: @@ -116,7 +121,6 @@ jobs: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: - ref: v${{ needs.check-release.outputs.version }} persist-credentials: false - name: Install Rust @@ -165,7 +169,8 @@ jobs: path: socket-patch-${{ matrix.target }}.zip github-release: - needs: [check-release, build] + needs: [version, build] + if: ${{ !inputs.dry-run }} runs-on: ubuntu-latest permissions: contents: write @@ -180,14 +185,15 @@ jobs: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - TAG="v${{ needs.check-release.outputs.version }}" + TAG="v${{ needs.version.outputs.version }}" gh release create "$TAG" \ --repo "$GITHUB_REPOSITORY" \ --generate-notes \ artifacts/* cargo-publish: - needs: [check-release, build] + needs: [version, build] + if: ${{ !inputs.dry-run }} runs-on: ubuntu-latest permissions: contents: read @@ -196,7 +202,6 @@ jobs: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: - ref: v${{ needs.check-release.outputs.version }} persist-credentials: false - name: Install Rust @@ -225,7 +230,8 @@ jobs: CARGO_REGISTRY_TOKEN: ${{ steps.crates-io-auth.outputs.token }} npm-publish: - needs: [check-release, build] + needs: [version, build] + if: ${{ !inputs.dry-run }} runs-on: ubuntu-latest permissions: contents: read @@ -234,7 +240,6 @@ jobs: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: - ref: v${{ needs.check-release.outputs.version }} persist-credentials: false - name: Configure git for HTTPS @@ -250,6 +255,7 @@ jobs: uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: node-version: '22' + registry-url: 'https://registry.npmjs.org' - name: Update npm for trusted publishing run: npm install -g npm@latest @@ -285,6 +291,8 @@ jobs: stage_win socket-patch-aarch64-pc-windows-msvc npm/socket-patch-win32-arm64 - name: Publish platform packages + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} run: | for pkg_dir in npm/socket-patch-*/; do echo "Publishing ${pkg_dir}..." @@ -298,10 +306,13 @@ jobs: run: cp README.md npm/socket-patch/README.md - name: Publish main package + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} run: npm publish ./npm/socket-patch --provenance --access public pypi-publish: - needs: [check-release, build] + needs: [version, build] + if: ${{ !inputs.dry-run }} runs-on: ubuntu-latest permissions: contents: read @@ -310,7 +321,6 @@ jobs: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: - ref: v${{ needs.check-release.outputs.version }} persist-credentials: false - name: Download all artifacts @@ -329,7 +339,7 @@ jobs: - name: Build platform wheels run: | - VERSION="${{ needs.check-release.outputs.version }}" + VERSION="${{ needs.version.outputs.version }}" python scripts/build-pypi-wheels.py --version "$VERSION" --artifacts artifacts --dist dist - name: Publish to PyPI From 98e404f2ae19d56178f73caec8db735dc3c26a55 Mon Sep 17 00:00:00 2001 From: wenxin-jiang Date: Wed, 1 Apr 2026 16:33:58 -0400 Subject: [PATCH 2/4] fix: remove NPM_TOKEN, use OIDC trusted publishing like socket-cli The original ENEEDAUTH failure was caused by missing registry-url in setup-node, not missing NPM_TOKEN. With registry-url set, OIDC trusted publishing works for both existing and new packages. Also fixes zizmor secrets-outside-env warnings. Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/release.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0beb42f..ccc7b50 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -291,8 +291,6 @@ jobs: stage_win socket-patch-aarch64-pc-windows-msvc npm/socket-patch-win32-arm64 - name: Publish platform packages - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} run: | for pkg_dir in npm/socket-patch-*/; do echo "Publishing ${pkg_dir}..." @@ -306,8 +304,6 @@ jobs: run: cp README.md npm/socket-patch/README.md - name: Publish main package - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} run: npm publish ./npm/socket-patch --provenance --access public pypi-publish: From bcbd0637b60b13bfd352a46891758177e60b18ec Mon Sep 17 00:00:00 2001 From: wenxin-jiang Date: Wed, 1 Apr 2026 16:35:00 -0400 Subject: [PATCH 3/4] fix: restore NPM_TOKEN with environment for new package publishing OIDC trusted publishing doesn't work for brand new packages that don't exist on the npm registry yet. The new -gnu/-musl packages need NPM_TOKEN for their first publish. Added `environment: npm-publish` to satisfy zizmor's secrets-outside-env audit. The environment needs to be created in the repo settings with the NPM_TOKEN secret. Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/release.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ccc7b50..21bcb7c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -233,6 +233,7 @@ jobs: needs: [version, build] if: ${{ !inputs.dry-run }} runs-on: ubuntu-latest + environment: npm-publish permissions: contents: read id-token: write @@ -291,6 +292,8 @@ jobs: stage_win socket-patch-aarch64-pc-windows-msvc npm/socket-patch-win32-arm64 - name: Publish platform packages + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} run: | for pkg_dir in npm/socket-patch-*/; do echo "Publishing ${pkg_dir}..." @@ -304,6 +307,8 @@ jobs: run: cp README.md npm/socket-patch/README.md - name: Publish main package + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} run: npm publish ./npm/socket-patch --provenance --access public pypi-publish: From d0c042b747b6f4827ef9eb63f313e43c05e3413c Mon Sep 17 00:00:00 2001 From: wenxin-jiang Date: Wed, 1 Apr 2026 16:40:34 -0400 Subject: [PATCH 4/4] fix: use pure OIDC trusted publishing, matching socket-cli/socket-mcp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove NPM_TOKEN and environment — use the same OIDC pattern as socket-cli and socket-mcp. The registry-url in setup-node enables the OIDC token exchange. Note: new packages that don't exist on npm yet must be pre-created manually before the first publish. Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/release.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 21bcb7c..ccc7b50 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -233,7 +233,6 @@ jobs: needs: [version, build] if: ${{ !inputs.dry-run }} runs-on: ubuntu-latest - environment: npm-publish permissions: contents: read id-token: write @@ -292,8 +291,6 @@ jobs: stage_win socket-patch-aarch64-pc-windows-msvc npm/socket-patch-win32-arm64 - name: Publish platform packages - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} run: | for pkg_dir in npm/socket-patch-*/; do echo "Publishing ${pkg_dir}..." @@ -307,8 +304,6 @@ jobs: run: cp README.md npm/socket-patch/README.md - name: Publish main package - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} run: npm publish ./npm/socket-patch --provenance --access public pypi-publish: