From 3e24830689f648a5614bdbd6216e2eb5a0b33861 Mon Sep 17 00:00:00 2001 From: geobelsky Date: Fri, 10 Apr 2026 16:20:37 +0000 Subject: [PATCH] fix(ci): chain npm publish + plugin sync into release-binary workflow The previous setup had two separate workflows: - release-binary.yml: triggered on `push: tags: v*`, builds binaries and creates a GitHub Release via softprops/action-gh-release using GITHUB_TOKEN - npm-publish.yml: triggered on `release: published`, publishes to npm and syncs the plugin repo The chain was broken by a documented GitHub Actions safety: events fired by GITHUB_TOKEN (anti-recursion protection) do NOT trigger downstream workflows. So when release-binary created the release, npm-publish.yml never ran for v0.2.7. Releases v0.2.3-v0.2.6 worked because the user manually created the GitHub Release after the binary build, which counts as a non-bot event and triggered the chain. Fix: collapse npm-publish.yml into release-binary.yml as two `needs:`-chained jobs in the same workflow run. Same workflow = same run = no cross-workflow trigger needed. The result is identical user-facing behavior (binaries on GitHub releases + npm publish + plugin repo sync) but with a single trigger: push tag. - release-binary.yml: added publish-npm and sync-plugin-repo jobs - npm-publish.yml: deleted Verified by inspecting the new workflow YAML; will be validated end-to-end on the next release tag push. Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/npm-publish.yml | 48 ---------------- .github/workflows/release-binary.yml | 83 ++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 48 deletions(-) delete mode 100644 .github/workflows/npm-publish.yml diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml deleted file mode 100644 index f6eb7e4..0000000 --- a/.github/workflows/npm-publish.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: Publish to npm - -on: - release: - types: [published] - -jobs: - publish: - runs-on: ubuntu-latest - permissions: - contents: read - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-node@v4 - with: - node-version: '20' - registry-url: 'https://registry.npmjs.org' - - - run: npm ci - - run: npm run build - - run: npm run lint - - run: npm test - - run: npm publish --access public - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - - # Sync plugin bundle to axme-code-plugin repo - - name: Sync plugin repo - env: - PLUGIN_REPO_TOKEN: ${{ secrets.PLUGIN_REPO_TOKEN }} - run: | - git clone https://x-access-token:${PLUGIN_REPO_TOKEN}@github.com/AxmeAI/axme-code-plugin.git /tmp/plugin-repo - cd /tmp/plugin-repo - # Remove old files (except .git and .gitignore) - ls -A | grep -v '^\.\(git\|gitignore\)$' | xargs rm -rf - # Copy new plugin bundle - cp -r ${GITHUB_WORKSPACE}/dist/plugin/. . - cp ${GITHUB_WORKSPACE}/dist/plugin/.mcp.json . - cp -r ${GITHUB_WORKSPACE}/dist/plugin/.claude-plugin . - # Remove sourcemaps and node_modules (not needed in repo) - rm -f *.map - rm -rf node_modules package-lock.json - git config user.name "github-actions" - git config user.email "github-actions@github.com" - git add -A - git commit -m "sync: ${GITHUB_REF_NAME} from axme-code" || echo "No changes to commit" - git push diff --git a/.github/workflows/release-binary.yml b/.github/workflows/release-binary.yml index 6f79fd0..52c811c 100644 --- a/.github/workflows/release-binary.yml +++ b/.github/workflows/release-binary.yml @@ -75,3 +75,86 @@ jobs: with: files: artifacts/*/axme-code-* generate_release_notes: true + + publish-npm: + # Publish @axme/code to npm. We do this in the same workflow as release-binary + # (chained via `needs: release`) instead of a separate `release: published` + # trigger workflow because GitHub Actions does NOT fire workflow events from + # actions taken by GITHUB_TOKEN (anti-recursion safety). When release-binary + # creates the GitHub release via softprops/action-gh-release, no downstream + # workflow listening on `release: published` will run. Chaining via `needs:` + # in the same workflow run avoids that limitation entirely. + needs: release + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: "20" + registry-url: "https://registry.npmjs.org" + + - name: Install dependencies + run: npm ci + + - name: Build + run: npm run build + + - name: Lint + run: npm run lint + + - name: Test + run: npm test + + - name: Publish to npm + run: npm publish --access public + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + sync-plugin-repo: + # Sync plugin bundle to AxmeAI/axme-code-plugin. Same anti-recursion reason: + # if we wait for `release: published` we never run, so we chain on `needs: publish-npm` + # to keep the previous behavior (sync after npm publish succeeds). + needs: publish-npm + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: "20" + + - name: Install dependencies + run: npm ci + + - name: Build + run: npm run build + + - name: Sync plugin repo + env: + PLUGIN_REPO_TOKEN: ${{ secrets.PLUGIN_REPO_TOKEN }} + run: | + git clone https://x-access-token:${PLUGIN_REPO_TOKEN}@github.com/AxmeAI/axme-code-plugin.git /tmp/plugin-repo + cd /tmp/plugin-repo + # Remove old files (except .git and .gitignore) + ls -A | grep -v '^\.\(git\|gitignore\)$' | xargs rm -rf + # Copy new plugin bundle + cp -r ${GITHUB_WORKSPACE}/dist/plugin/. . + cp ${GITHUB_WORKSPACE}/dist/plugin/.mcp.json . + cp -r ${GITHUB_WORKSPACE}/dist/plugin/.claude-plugin . + # Remove sourcemaps and node_modules (not needed in repo) + rm -f *.map + rm -rf node_modules package-lock.json + git config user.name "github-actions" + git config user.email "github-actions@github.com" + git add -A + git commit -m "sync: ${GITHUB_REF_NAME} from axme-code" || echo "No changes to commit" + git push