From 307967d1113c6a3b4598a0d758119275f41677a0 Mon Sep 17 00:00:00 2001 From: naaiyy Date: Thu, 13 Aug 2026 16:36:28 +0200 Subject: [PATCH] Use npm trusted publishing --- .github/workflows/publish-viewers.yml | 69 ++++++++++++++++++++------- docs/VIEWER_PUBLISHING.md | 17 ++++++- 2 files changed, 68 insertions(+), 18 deletions(-) diff --git a/.github/workflows/publish-viewers.yml b/.github/workflows/publish-viewers.yml index d1265382..82918733 100644 --- a/.github/workflows/publish-viewers.yml +++ b/.github/workflows/publish-viewers.yml @@ -4,22 +4,58 @@ on: push: tags: ["viewer-v*"] workflow_dispatch: + inputs: + release_tag: + description: Existing viewer-v* tag to retry with the current workflow + required: false + type: string permissions: contents: read concurrency: - group: viewer-release-${{ github.ref }} + group: viewer-release-${{ inputs.release_tag || github.ref_name }} cancel-in-progress: false jobs: verify: + outputs: + release_tag: ${{ steps.release-context.outputs.release_tag }} + release_version: ${{ steps.release-context.outputs.release_version }} runs-on: ubuntu-latest steps: - name: Check out the tagged source without credentials uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false + ref: ${{ inputs.release_tag || github.ref }} + - name: Validate the release context + id: release-context + env: + REQUESTED_TAG: ${{ inputs.release_tag }} + run: | + release_tag="" + if test -n "$REQUESTED_TAG"; then + release_tag="$REQUESTED_TAG" + elif test "$GITHUB_REF_TYPE" = tag; then + release_tag="$GITHUB_REF_NAME" + fi + + if test -n "$release_tag"; then + if [[ ! "$release_tag" =~ ^viewer-v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z][0-9A-Za-z.-]*)?$ ]]; then + echo "Invalid viewer release tag: $release_tag" >&2 + exit 1 + fi + tag_commit="$(git rev-parse "refs/tags/$release_tag^{commit}")" + head_commit="$(git rev-parse 'HEAD^{commit}')" + if test "$tag_commit" != "$head_commit"; then + echo "Checked-out commit $head_commit does not match $release_tag ($tag_commit)." >&2 + exit 1 + fi + fi + + echo "release_tag=$release_tag" >> "$GITHUB_OUTPUT" + echo "release_version=${release_tag#viewer-v}" >> "$GITHUB_OUTPUT" - uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4.0.0 with: version: 11.9.0 @@ -41,12 +77,10 @@ jobs: - run: pnpm run closure:platform - run: pnpm audit --prod --audit-level high - name: Pack the exact verified release artifacts + env: + RELEASE_VERSION: ${{ steps.release-context.outputs.release_version }} run: | - expected="" - if test "$GITHUB_REF_TYPE" = tag; then - expected="${GITHUB_REF_NAME#viewer-v}" - fi - node scripts/pack-viewer-release.mjs release-artifacts "$expected" + node scripts/pack-viewer-release.mjs release-artifacts "$RELEASE_VERSION" - name: Upload verified release artifacts uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.0 with: @@ -56,7 +90,7 @@ jobs: retention-days: 1 release: - if: github.ref_type == 'tag' + if: needs.verify.outputs.release_tag != '' needs: verify runs-on: ubuntu-latest permissions: @@ -67,6 +101,9 @@ jobs: with: node-version: 24 registry-url: https://registry.npmjs.org + package-manager-cache: false + - name: Install an npm CLI with trusted publishing support + run: npm install --global npm@12.0.2 - name: Download the verified artifacts from this workflow run uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.0 with: @@ -77,9 +114,6 @@ jobs: run: sha256sum --check SHA256SUMS - name: Verify existing packages and publish only missing artifacts working-directory: release-artifacts - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - NPM_CONFIG_PROVENANCE: true run: | while IFS=$'\t' read -r name version tarball; do if npm view "$name@$version" version >/dev/null 2>&1; then @@ -87,23 +121,24 @@ jobs: else dist_tag="latest" case "$version" in *-*) dist_tag="next" ;; esac - npm publish "$tarball" --access public --provenance --tag "$dist_tag" + npm publish "$tarball" --access public --tag "$dist_tag" fi done < <(node -e 'const {packages}=require("./packages.json"); for (const item of packages) console.log([item.name,item.version,item.tarball].join("\t"))') - name: Create GitHub release metadata env: GH_TOKEN: ${{ github.token }} + RELEASE_TAG: ${{ needs.verify.outputs.release_tag }} + RELEASE_VERSION: ${{ needs.verify.outputs.release_version }} run: | - version="${GITHUB_REF_NAME#viewer-v}" prerelease="" - case "$version" in *-*) prerelease="--prerelease" ;; esac - if gh release view "$GITHUB_REF_NAME" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then - echo "GitHub release $GITHUB_REF_NAME already exists." + case "$RELEASE_VERSION" in *-*) prerelease="--prerelease" ;; esac + if gh release view "$RELEASE_TAG" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then + echo "GitHub release $RELEASE_TAG already exists." else - gh release create "$GITHUB_REF_NAME" release-artifacts/*.tgz release-artifacts/SHA256SUMS \ + gh release create "$RELEASE_TAG" release-artifacts/*.tgz release-artifacts/SHA256SUMS \ --repo "$GITHUB_REPOSITORY" \ --verify-tag \ - --title "AnyDoc viewer platform $version" \ + --title "AnyDoc viewer platform $RELEASE_VERSION" \ --generate-notes \ $prerelease fi diff --git a/docs/VIEWER_PUBLISHING.md b/docs/VIEWER_PUBLISHING.md index 8def26d3..3712ed5e 100644 --- a/docs/VIEWER_PUBLISHING.md +++ b/docs/VIEWER_PUBLISHING.md @@ -53,7 +53,22 @@ git push origin viewer-v0.1.0-alpha.14 The `Publish viewer platform` workflow verifies that every package manifest matches the tag, uploads the exact verified tarballs, publishes only missing packages, verifies any already-published artifacts, and creates the GitHub -release. Alpha versions publish under the npm `next` dist-tag. +release. Alpha versions publish under the npm `next` dist-tag. npm uses OpenID +Connect (OIDC) to authorize this workflow for each package, so the workflow does +not store or use an npm publishing token. npm creates provenance attestations +automatically. + +If a release fails after its tag exists, retry that immutable tag with the +current workflow definition: + +```sh +gh workflow run publish-viewers.yml --ref main \ + -f release_tag=viewer-v0.1.0-alpha.14 +``` + +The retry checks out the tag, confirms that `HEAD` is the tag commit, and runs +the same verification and publication gates. Do not move or replace a release +tag to retry a failed workflow. Do not use Changesets to version the `@firecrawl/anydoc` binding packages. Their cross-language `v*` workflow and version gate remain separate.