From 4b3d1f98f9b62d3966385456b027c57e8ed0697d Mon Sep 17 00:00:00 2001 From: Joey Parrish Date: Wed, 4 Mar 2026 13:30:04 -0800 Subject: [PATCH] fix(ci): Update release for trusted publishing to NPM (#1544) This handles trusted publishing for Shaka Packager to NPM without tokens. This also updates upload/download actions, and adds a filter on specific artifacts downloaded to avoid conflicts that have arisen since the last release. Also updates the images used in the build matrix. Issue shaka-project/shaka-player#9132 --- .github/workflows/README.md | 4 -- .github/workflows/build.yaml | 2 +- .github/workflows/publish-docker.yaml | 4 +- .github/workflows/publish-npm.yaml | 76 ++++++++++++++++++--------- .github/workflows/release-please.yaml | 19 ++++++- build-matrix.json | 7 ++- 6 files changed, 73 insertions(+), 39 deletions(-) diff --git a/.github/workflows/README.md b/.github/workflows/README.md index acc2296fe6..6ddf8ec1e0 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -64,10 +64,6 @@ - `DOCKERHUB_PACKAGE_NAME`: Not a true "secret", but stored here to avoid someone pushing bogus packages to Docker Hub during CI testing from a fork - In a fork, set to a private name which differs from the production one - - `NPM_CI_TOKEN`: An "Automation"-type access token for NPM for the `shaka-bot` - account - - To generate, visit https://www.npmjs.com/settings/shaka-bot/tokens and - select the "Automation" type - `NPM_PACKAGE_NAME`: Not a true "secret", but stored here to avoid someone pushing bogus packages to NPM during CI testing from a fork - In a fork, set to a private name which differs from the production one diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index cfe84e3b0c..9dafe574f9 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -282,7 +282,7 @@ jobs: fi - name: Upload static release build artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 if: matrix.build_type == 'Release' && matrix.lib_type == 'static' with: name: artifacts-${{ matrix.os_name }}-${{ matrix.target_arch }} diff --git a/.github/workflows/publish-docker.yaml b/.github/workflows/publish-docker.yaml index dd6e1dfb6d..90b7d27ccd 100644 --- a/.github/workflows/publish-docker.yaml +++ b/.github/workflows/publish-docker.yaml @@ -92,7 +92,7 @@ jobs: touch "${{ runner.temp }}/digests/${digest#sha256:}" - name: Upload digest - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: digests-${{ matrix.docker_arch }} path: ${{ runner.temp }}/digests/* @@ -110,7 +110,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Download digests - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: path: ${{ runner.temp }}/digests pattern: digests-* diff --git a/.github/workflows/publish-npm.yaml b/.github/workflows/publish-npm.yaml index acf5741533..79c6119254 100644 --- a/.github/workflows/publish-npm.yaml +++ b/.github/workflows/publish-npm.yaml @@ -19,8 +19,6 @@ on: required: true type: boolean secrets: - NPM_CI_TOKEN: - required: true NPM_PACKAGE_NAME: required: true # For manual debugging: @@ -39,62 +37,88 @@ jobs: publish: name: Publish runs-on: ubuntu-latest + + permissions: + # Required for OIDC ("trusted publishing") + id-token: write + steps: - name: Checkout code uses: actions/checkout@v4 with: ref: ${{ inputs.tag }} persist-credentials: false + # Needed to view all tags and correctly compute the latest tag: + fetch-depth: 0 - uses: actions/setup-node@v4 with: - node-version: 22 + # NOTE: OIDC fails with node less than 24. + node-version: 24 registry-url: 'https://registry.npmjs.org' - - name: Compute tags + # NOTE: OIDC fails with npm less than 11.5.1. + - name: Update npm + run: sudo npm install -g npm@11.7 + + - name: Compute NPM tags run: | # NPM publish always sets a tag. If you don't provide an explicit # tag, you get the "latest" tag by default, but we want "latest" to # always point to the highest version number. So we set an explicit - # tag on every "publish" command, then follow up with a command to - # set "latest" only if this release was the highest version yet. + # tag on every "publish" command, either "latest" for the latest, or + # a dummy tag otherwise. - # The explicit tag is based on the branch. If the git tag is v4.4.1, - # the branch was v4.4.x, and the explicit NPM tag should be - # v4.4-latest. + # We only tag the NPM package as "latest" if this release is the + # highest version to date. GIT_TAG_NAME=${{ inputs.tag }} - NPM_TAG=$(echo "$GIT_TAG_NAME" | cut -f 1-2 -d .)-latest - echo "NPM_TAG=$NPM_TAG" >> $GITHUB_ENV + RELEASE_TAGS=$(git tag | grep ^v[0-9]) + LATEST_RELEASE=$(echo "$RELEASE_TAGS" | sort --version-sort | tail -1) # Since we also set the package version on-the-fly during publication, # compute that here. It's the tag without the leading "v". NPM_VERSION=$(echo "$GIT_TAG_NAME" | sed -e 's/^v//') echo "NPM_VERSION=$NPM_VERSION" >> $GITHUB_ENV + if [[ "$GIT_TAG_NAME" == "$LATEST_RELEASE" ]]; then + NPM_LATEST=true + else + NPM_LATEST=false + fi + echo NPM_LATEST=$NPM_LATEST >> $GITHUB_ENV + # Debug the decisions made here. + echo "Latest release: $LATEST_RELEASE" echo "This release: $GIT_TAG_NAME" - echo "NPM tag: $NPM_TAG" + echo "NPM latest: $NPM_LATEST" echo "NPM version: $NPM_VERSION" - - name: Set package name and version + - name: Set package name, version, and URL run: | - # These substitutions use | because the package name could contain - # both / and @, but | should not appear in package names. - sed npm/package.json -i \ - -e 's|"name": ""|"name": "${{ secrets.NPM_PACKAGE_NAME }}"|' \ - -e 's|"version": ""|"version": "${{ env.NPM_VERSION }}"|' + cd npm + + # NOTE: OIDC fails if the repository URL doesn't match package.json. + npm pkg set repository.url=https://github.com/${{ github.repository }} + npm pkg set name="${{ secrets.NPM_PACKAGE_NAME }}" + npm pkg set version="${{ env.NPM_VERSION }}" - name: Publish - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_CI_TOKEN }} run: | cd npm # Publish with an explicit tag. - # Also publish with explicit public access, to allow scoped packages. - npm publish --tag "$NPM_TAG" --access=public - - # Add the "latest" tag if needed. - if [[ "${{ inputs.latest }}" == "true" ]]; then - npm dist-tag add "${{ secrets.NPM_PACKAGE_NAME }}@$NPM_VERSION" latest + # NOTE: --access public is required for scoped forks. + if [[ "$NPM_LATEST" == "true" ]]; then + # The "latest" tag is implied and automatic. + npm publish --access public + else + # You can't **not** have a tag. So if we don't want to overwrite + # "latest" (implied default), we have to overwrite something else. + # Even with NPM 11, if you don't do this, instead of overwriting + # "latest", it will detect that it's inappropriate, and **fail**. + # See https://github.com/npm/npm/issues/10625 + # and https://github.com/npm/cli/issues/7553 + # See also https://github.com/npm/cli/issues/8547, which killed our + # system of branch-specific tags. + npm publish --access public --tag tag-required-see-npm-bug-10625 fi diff --git a/.github/workflows/release-please.yaml b/.github/workflows/release-please.yaml index 32469e2860..3f12c1adb3 100644 --- a/.github/workflows/release-please.yaml +++ b/.github/workflows/release-please.yaml @@ -20,9 +20,17 @@ jobs: release: runs-on: ubuntu-latest needs: settings + + permissions: + # Write to "contents" is needed to create a release + contents: write + # Write to pull-requests is needed to create and update the release PR + pull-requests: write + outputs: release_created: ${{ steps.release.outputs.release_created }} tag_name: ${{ steps.release.outputs.tag_name }} + steps: # Create/update release PR - uses: googleapis/release-please-action@v4 @@ -121,8 +129,13 @@ jobs: needs: [release, build] if: needs.release.outputs.release_created steps: - - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@v8 with: + # Avoid mixing in other artifacts (used temporarily for docker, etc). + # If we get those mixed in, the download may fail with "not a zip" in + # the debug logs. Our binary artifacts all follow the pattern + # artifacts-*. + pattern: artifacts-* path: artifacts merge-multiple: true @@ -143,10 +156,12 @@ jobs: name: Update NPM needs: [release, compute, artifacts] if: needs.release.outputs.release_created + permissions: + # Required for OIDC ("trusted publishing") + id-token: write uses: ./.github/workflows/publish-npm.yaml with: tag: ${{ needs.release.outputs.tag_name }} latest: ${{ needs.compute.outputs.latest == 'true' }} secrets: - NPM_CI_TOKEN: ${{ secrets.NPM_CI_TOKEN }} NPM_PACKAGE_NAME: ${{ secrets.NPM_PACKAGE_NAME }} diff --git a/build-matrix.json b/build-matrix.json index e7d5f36394..4626ca7b53 100644 --- a/build-matrix.json +++ b/build-matrix.json @@ -9,16 +9,15 @@ "generator": "Ninja" }, { - "comment": "Explicit macOS version 13 is required for explicit x64 CPU.", - "os": "macos-13", + "comment": "Intel mac images are supported until August 2027.", + "os": "macos-15-intel", "os_name": "osx", "target_arch": "x64", "exe_ext": "", "generator": "Ninja" }, { - "comment": "Explicit macOS version 14 is required for explicit arm64 CPU.", - "os": "macos-14", + "os": "macos-latest", "os_name": "osx", "target_arch": "arm64", "exe_ext": "",