From 4c5a6f9d16f584ec07ec17c3b61027a446d0f5d4 Mon Sep 17 00:00:00 2001 From: Harshita Gupta Date: Mon, 27 Apr 2026 12:21:49 -0700 Subject: [PATCH] workflows: replace softprops/action-gh-release with gh CLI Supply-chain hardening: softprops/action-gh-release is a single-maintainer third-party action pinned to the mutable @v1 tag. Replacing it with the first-party `gh` CLI (pre-installed on GitHub-hosted runners, maintained by GitHub) removes that dependency from the release-upload path. Migrates all three release-upload call-sites on v24.13.0: - build-node.yml - build-node-fibers.yml - build-node-packages.yml (v24.13.0 has no build-node-openssl-fips.yml.) Each Upload step becomes: - view-or-create guard so the first matrix arm creates the release (and the second arm tolerates the race); - `gh release upload --clobber` for the asset (matches softprops's always-delete-then-upload behavior on name collision); - `gh release edit --title` to preserve softprops's behavior of always re-setting the release name on every upload. Each job also picks up `REPO: ${{ github.repository }}` in its env block. --- .github/workflows/build-node-fibers.yml | 33 +++++++++++++++++--- .github/workflows/build-node-packages.yml | 34 ++++++++++++++++++--- .github/workflows/build-node.yml | 37 ++++++++++++++++++++--- 3 files changed, 89 insertions(+), 15 deletions(-) diff --git a/.github/workflows/build-node-fibers.yml b/.github/workflows/build-node-fibers.yml index 7ec8965174fdaa..5ea23d68bbb41c 100644 --- a/.github/workflows/build-node-fibers.yml +++ b/.github/workflows/build-node-fibers.yml @@ -21,6 +21,7 @@ jobs: env: NODE_VERSION: v20.18.3 + REPO: ${{ github.repository }} steps: - name: Debug Matrix Values @@ -67,10 +68,32 @@ jobs: tar -czf "$ARCHIVE_NAME" -C "$(dirname "$FIBERS_DIR")" "$(basename "$FIBERS_DIR")" - name: Upload archive to release - uses: softprops/action-gh-release@v1 - with: - name: node-${{ env.NODE_VERSION }}-LATEST - tag_name: node-${{ env.NODE_VERSION }}-release - files: ${{ env.ARCHIVE_NAME }} + # Attach the built node-fibers archive to the same node-${NODE_VERSION}-release + # release that hosts the corresponding Node binaries. + # + # This workflow is fired by `push` to v24.13.0 and by workflow_dispatch — it + # is not chained off Build Node, so the release may not yet exist. The + # matrix runs both arms (linux-x64, linux-arm64) in parallel, so both can + # race to create the release. The view-or-create guard with the trailing + # `|| gh release view` tolerates "already exists" from a losing racer and + # propagates any other create failure through the final view. + # + # `--clobber` makes re-uploads idempotent on asset name collisions by + # deleting the existing asset before uploading. If the new upload fails + # after the delete, just re-run the job to rebuild. + # + # `gh release edit --title` after upload keeps the release title + # deterministically derived from NODE_VERSION, overriding any manual rename + # in the GitHub UI. env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -euo pipefail + TAG="node-${NODE_VERSION}-release" + RELEASE_NAME="node-${NODE_VERSION}-LATEST" + if ! gh release view "$TAG" --repo "$REPO" >/dev/null 2>&1; then + gh release create "$TAG" --title "$RELEASE_NAME" --notes "" --repo "$REPO" \ + || gh release view "$TAG" --repo "$REPO" >/dev/null + fi + gh release upload "$TAG" "$ARCHIVE_NAME" --clobber --repo "$REPO" + gh release edit "$TAG" --title "$RELEASE_NAME" --repo "$REPO" diff --git a/.github/workflows/build-node-packages.yml b/.github/workflows/build-node-packages.yml index 25c80d728cf4af..a9c9722e2b3549 100644 --- a/.github/workflows/build-node-packages.yml +++ b/.github/workflows/build-node-packages.yml @@ -21,6 +21,7 @@ jobs: env: NODE_VERSION: v20.18.3 + REPO: ${{ github.repository }} steps: - name: Debug Matrix Values @@ -68,10 +69,33 @@ jobs: tar --hard-dereference -cvzf packages_${{matrix.arch}}.tar.gz bcrypt@5.1.0 cld@2.9.1 unix-dgram@2.0.6 - name: Upload archive to release - uses: softprops/action-gh-release@v1 - with: - name: node-${{ env.NODE_VERSION }}-LATEST - tag_name: node-${{ env.NODE_VERSION }}-release - files: packages_${{matrix.arch}}.tar.gz + # Attach the built gyp-package bundle to the same node-${NODE_VERSION}-release + # release that hosts the corresponding Node binaries. + # + # This workflow is fired by `push` to v24.13.0 and by workflow_dispatch — it + # is not chained off Build Node, so the release may not yet exist. The + # matrix runs both arms (linux-x64, linux-arm64) in parallel, so both can + # race to create the release. The view-or-create guard with the trailing + # `|| gh release view` tolerates "already exists" from a losing racer and + # propagates any other create failure through the final view. + # + # `--clobber` makes re-uploads idempotent on asset name collisions by + # deleting the existing asset before uploading. If the new upload fails + # after the delete, just re-run the job. + # + # `gh release edit --title` after upload keeps the release title + # deterministically derived from NODE_VERSION, overriding any manual rename + # in the GitHub UI. env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -euo pipefail + TAG="node-${NODE_VERSION}-release" + RELEASE_NAME="node-${NODE_VERSION}-LATEST" + FILE="packages_${{matrix.arch}}.tar.gz" + if ! gh release view "$TAG" --repo "$REPO" >/dev/null 2>&1; then + gh release create "$TAG" --title "$RELEASE_NAME" --notes "" --repo "$REPO" \ + || gh release view "$TAG" --repo "$REPO" >/dev/null + fi + gh release upload "$TAG" "$FILE" --clobber --repo "$REPO" + gh release edit "$TAG" --title "$RELEASE_NAME" --repo "$REPO" diff --git a/.github/workflows/build-node.yml b/.github/workflows/build-node.yml index 97b6b700376a1a..58003b6d05c271 100644 --- a/.github/workflows/build-node.yml +++ b/.github/workflows/build-node.yml @@ -23,6 +23,7 @@ jobs: env: S3_BUCKET: your-bucket-name AWS_REGION: us-east-1 + REPO: ${{ github.repository }} steps: - name: Checkout Node fork @@ -106,10 +107,36 @@ jobs: path: artifacts/${{ env.NODE_ARCHIVE_LATEST }} - name: Upload Node archive to release - uses: softprops/action-gh-release@v1 - with: - name: node-${{ env.NODE_VERSION }}-LATEST - tag_name: node-${{ env.NODE_VERSION }}-release - files: ./artifacts/${{ env.NODE_ARCHIVE_LATEST }} + # Publish the built Node archive to the node-${NODE_VERSION}-release release. + # This is the first uploader in the pipeline; build-node-packages and + # build-node-fibers attach additional artifacts to the same release later. + # + # Matrix concurrency: both matrix arms (linux-x64, linux-arm64) hit this step + # in parallel. On the first run for a new NODE_VERSION the release does not + # yet exist, so both arms race to create it. The view-or-create guard with + # the trailing `|| gh release view` tolerates "already exists" from the + # losing arm (as long as the release now exists); any other create failure + # propagates through that second view. + # + # `--clobber` makes re-uploads idempotent on asset name collisions: an + # existing asset with the same name is deleted before the new one uploads. + # Acceptable here because the -LATEST assets are always reproducible from + # the build inputs; if the upload fails after the delete, just re-run the + # job. + # + # `gh release edit --title` after upload keeps the release title + # deterministically derived from NODE_VERSION even if someone renames the + # release in the GitHub UI. env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -euo pipefail + TAG="node-${NODE_VERSION}-release" + RELEASE_NAME="node-${NODE_VERSION}-LATEST" + FILE="./artifacts/${NODE_ARCHIVE_LATEST}" + if ! gh release view "$TAG" --repo "$REPO" >/dev/null 2>&1; then + gh release create "$TAG" --title "$RELEASE_NAME" --notes "" --repo "$REPO" \ + || gh release view "$TAG" --repo "$REPO" >/dev/null + fi + gh release upload "$TAG" "$FILE" --clobber --repo "$REPO" + gh release edit "$TAG" --title "$RELEASE_NAME" --repo "$REPO"