diff --git a/.github/workflows/build-node-fibers.yml b/.github/workflows/build-node-fibers.yml index 0d062421a568f4..e8ddd62f4db04a 100644 --- a/.github/workflows/build-node-fibers.yml +++ b/.github/workflows/build-node-fibers.yml @@ -25,6 +25,7 @@ jobs: env: NODE_VERSION: v22.21.1 + REPO: ${{ github.repository }} steps: - name: Checkout repository @@ -65,10 +66,33 @@ 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. + # + # Normally this workflow runs after Build Node via workflow_run, so the + # release already exists by the time we get here. But workflow_dispatch can + # fire it independently (release may not yet exist), and the matrix still + # runs both arms (linux-x64, linux-arm64) in parallel — so both arms 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-openssl-fips.yml b/.github/workflows/build-node-openssl-fips.yml index 1837722ce7204f..599729012f94a9 100644 --- a/.github/workflows/build-node-openssl-fips.yml +++ b/.github/workflows/build-node-openssl-fips.yml @@ -28,6 +28,9 @@ jobs: runs_on: ubuntu-22.04-arm runs-on: ${{ matrix.runs_on }} + env: + REPO: ${{ github.repository }} + steps: - name: Checkout Node fork uses: actions/checkout@v3 @@ -89,10 +92,35 @@ 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 }}-fips-LATEST - tag_name: node-${{ env.NODE_VERSION }}-fips-release - files: ./artifacts/${{ env.NODE_ARCHIVE_LATEST }} + # Publish the FIPS Node build to its own release tag + # (node-${NODE_VERSION}-fips-release), separate from the default Node + # release so consumers can select the FIPS variant explicitly rather than + # relying on filename conventions inside a shared release. + # + # This workflow is workflow_dispatch-only, and the matrix has two arms + # (linux-x64, linux-arm64) running in parallel — on the first invocation + # for a new NODE_VERSION both arms race to create the release. The + # view-or-create guard with the trailing `|| gh release view` tolerates + # "already exists" from the 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}-fips-release" + RELEASE_NAME="node-${NODE_VERSION}-fips-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" diff --git a/.github/workflows/build-node-packages.yml b/.github/workflows/build-node-packages.yml index e32ffb0310007d..085f81666291b0 100644 --- a/.github/workflows/build-node-packages.yml +++ b/.github/workflows/build-node-packages.yml @@ -25,6 +25,7 @@ jobs: env: NODE_VERSION: v22.21.1 + REPO: ${{ github.repository }} steps: - name: Checkout repository @@ -68,10 +69,34 @@ jobs: tar --hard-dereference -cvzf packages_${{matrix.arch}}.tar.gz bcrypt@5.1.0 cld@2.9.1 unix-dgram@2.0.6 "@datadog+pprof@5.8.0" - 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. + # + # Normally this workflow runs after Build Node via workflow_run, so the + # release already exists by the time we get here. But workflow_dispatch can + # fire it independently (release may not yet exist), and the matrix still + # runs both arms (linux-x64, linux-arm64) in parallel — so both arms 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 5d3e80fc193150..d3f03e7ab4c61d 100644 --- a/.github/workflows/build-node.yml +++ b/.github/workflows/build-node.yml @@ -20,6 +20,7 @@ jobs: env: S3_BUCKET: your-bucket-name AWS_REGION: us-east-1 + REPO: ${{ github.repository }} steps: - name: Checkout Node fork @@ -82,10 +83,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"