diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index dcec603..b840a5a 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -13,6 +13,7 @@ permissions: jobs: integration: name: integration node v24 macos-15-intel + if: github.event.release.prerelease == false runs-on: macos-15-intel steps: @@ -29,6 +30,7 @@ jobs: publish: name: publish to npmjs + if: github.event.release.prerelease == false runs-on: ubuntu-latest needs: integration @@ -77,7 +79,36 @@ jobs: - name: verify cli runtime dependency tree run: npm ls --omit=dev --all --prefix packages/cli + - name: check appdmg npm package version + id: npm_appdmg + run: | + package_name="$(node -p "require('./package.json').name")" + package_version="$(node -p "require('./package.json').version")" + + if npm view "${package_name}@${package_version}" version --json >/dev/null 2>&1; then + echo "exists=true" >> "$GITHUB_OUTPUT" + else + echo "exists=false" >> "$GITHUB_OUTPUT" + fi + + echo "package=${package_name}@${package_version}" >> "$GITHUB_OUTPUT" + + - name: check cli npm package version + id: npm_cli + run: | + package_name="$(node -p "require('./packages/cli/package.json').name")" + package_version="$(node -p "require('./packages/cli/package.json').version")" + + if npm view "${package_name}@${package_version}" version --json >/dev/null 2>&1; then + echo "exists=true" >> "$GITHUB_OUTPUT" + else + echo "exists=false" >> "$GITHUB_OUTPUT" + fi + + echo "package=${package_name}@${package_version}" >> "$GITHUB_OUTPUT" + - name: pack appdmg package + if: steps.npm_appdmg.outputs.exists == 'false' id: pack_appdmg run: | mkdir -p dist/appdmg @@ -87,6 +118,7 @@ jobs: echo "tarball=$tarball" >> "$GITHUB_OUTPUT" - name: pack cli package + if: steps.npm_cli.outputs.exists == 'false' id: pack_cli run: | mkdir -p dist/cli @@ -99,11 +131,13 @@ jobs: echo "tarball=$tarball" >> "$GITHUB_OUTPUT" - name: attest npm package artifacts + if: steps.npm_appdmg.outputs.exists == 'false' || steps.npm_cli.outputs.exists == 'false' uses: actions/attest@v4 with: subject-path: dist/**/*.tgz - name: upload npm package artifacts + if: steps.npm_appdmg.outputs.exists == 'false' || steps.npm_cli.outputs.exists == 'false' uses: actions/upload-artifact@v4 with: name: npm-packages @@ -111,12 +145,14 @@ jobs: if-no-files-found: error - name: publish appdmg package + if: steps.npm_appdmg.outputs.exists == 'false' run: npm publish "$TARBALL" --provenance --access public env: TARBALL: ${{ steps.pack_appdmg.outputs.tarball }} NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - name: publish cli package + if: steps.npm_cli.outputs.exists == 'false' run: npm publish "$TARBALL" --provenance --access public env: TARBALL: ${{ steps.pack_cli.outputs.tarball }} diff --git a/docs/npm-publishing.md b/docs/npm-publishing.md index 5b1ac55..a2fa0fb 100644 --- a/docs/npm-publishing.md +++ b/docs/npm-publishing.md @@ -31,8 +31,13 @@ Trusted Publishing works. Each publish workflow: - runs on a GitHub-hosted runner with `id-token: write`; +- ignores GitHub prereleases so prerelease tags cannot publish the npm `latest` + dist-tag by accident; - installs with Node.js 24; - runs tests, audit, and runtime dependency checks; +- checks whether the exact package version already exists on npm so rerunning a + partially successful release can continue with the remaining unpublished + packages; - creates the exact npm package tarball with `npm pack`; - creates a GitHub artifact attestation for that `.tgz`; - uploads the `.tgz` as a workflow artifact;