Skip to content

workflows: replace softprops/action-gh-release with gh CLI (v22.21.1)#21

Draft
harshita-gupta wants to merge 1 commit intov22.21.1from
harshitagupta/migrate-gh-release-upload-v22.21.1
Draft

workflows: replace softprops/action-gh-release with gh CLI (v22.21.1)#21
harshita-gupta wants to merge 1 commit intov22.21.1from
harshitagupta/migrate-gh-release-upload-v22.21.1

Conversation

@harshita-gupta
Copy link
Copy Markdown
Member

DO NOT MERGE until canary PR #20 (main) is validated

This is part of the rollout of the softprops β†’ gh-CLI migration across all Asana/node branches. The canary PR on main (#20) must be merged and end-to-end validated first. Merging this PR before then risks landing a regression on a production release branch with no safety net.

Validation checklist to complete on main (#20) before touching this PR

Copy these into PR #20 when you work it:

  • PR workflows: replace softprops/action-gh-release with gh CLI (main)Β #20 is merged into main.
  • Manually trigger Build Node on main via workflow_dispatch. Both matrix arms (linux-x64, linux-arm64) succeed without a race failure on gh release create.
  • The resulting release node-vX.Y.Z-release exists (or continues to exist) with title node-vX.Y.Z-LATEST, and both architecture archives appear as assets.
  • Manually trigger Build Node-Packages on main. Assets appear; release title still correct.
  • Manually trigger Build node-fibers with prebuilt Node on main. Assets appear; release title still correct.
  • Manually trigger Build Node with options around OpenSSL dynamic linking and FIPS on main with appropriate BUILD_REF. Assets appear in the separate -fips-static-release release with the expected title.
  • Byte-identity spot-check: compare sha256sum of an asset uploaded post-migration against one uploaded pre-migration on another branch β€” should match.
  • No release-body or commitish drift observed in any of the above.

Only after all of those pass β€” mark this PR ready for review and merge.

Summary

Supply-chain hardening: softprops/action-gh-release is a single-maintainer third-party action pinned to the mutable @v1 tag. If that account is compromised or the tag is re-pointed, every workflow depending on it runs whatever the new code does. 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 four release-upload call-sites on v22.21.1:

  • .github/workflows/build-node.yml
  • .github/workflows/build-node-fibers.yml
  • .github/workflows/build-node-openssl-fips.yml
  • .github/workflows/build-node-packages.yml

After this PR: zero references to softprops/action-gh-release on v22.21.1.

Replacement shape

Each softprops step becomes:

- name: Upload <...> archive to release
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  run: |
    set -euo pipefail
    TAG="node-${NODE_VERSION}-release"
    RELEASE_NAME="node-${NODE_VERSION}-LATEST"
    FILE="<path-or-shell-expr>"
    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"

Each job gains REPO: ${{ github.repository }} in its job-level env:. The build-node-openssl-fips.yml job had no job-level env block previously; it gets a minimal one containing only REPO.

Divergence from main's post-migration shape

On main, build-node-packages.yml uses a simpler upload pattern (plain gh release upload --clobber, no view-or-create guard, no gh release edit --title), because it runs downstream of build-node.yml. On this branch the workflow is migrated with the full pattern (view-or-create + edit --title) to preserve the behavior softprops gave us: the release and title are re-asserted on every upload, including for standalone workflow_dispatch runs of packages. If you'd rather match main's simpler shape here, say so and I'll simplify.

Behavior deltas vs. softprops/action-gh-release@v1

Based on reading the source of both tools β€” softprops at the v1 tag SHA (de2c0eb8, src/main.ts + src/github.ts) and gh CLI at v2.90.0 (pkg/cmd/release/{upload,create}/*.go).

# delta class notes
1 softprops creates-if-missing in one call; gh release upload requires release to exist replaceable added view || create preamble
2 softprops has internal 3Γ— retry on create ("presume a race with competing matrix runs"); gh release create has no retry replaceable create || view idiom: losing racer falls through via view
3 softprops always deletes-then-uploads on same-name conflict; gh release upload default errors, --clobber matches softprops no-op we pass --clobber
4 softprops always sets name on upload (via updateRelease); gh release upload doesn't touch name preserved gh release edit --title after upload
5 softprops updateRelease resets body/draft/prerelease to existing values; gh release edit without those flags is a no-op for them no-op neither approach modifies body; both leave draft/prerelease false
6 softprops glob-expands files:; gh release upload also glob-expands via GlobPaths no-op all call-sites pass a single explicit filename
7 softprops logs warning on missing files (opt-in to fail); gh release upload fails on missing literal path via os.Stat stricter, beneficial no action required
8 tag auto-creation: both create lightweight tag from default-branch HEAD when missing no-op identical
9 retries on upload: softprops has Octokit throttling plugin (1 retry on rate-limit); gh release upload retries 3Γ— on 5xx or network error no-op gh is slightly more robust
10 step outputs url, id, upload_url, assets are not set by run: blocks no-op no consumers of these outputs anywhere in the repo
11 auth: softprops uses GITHUB_TOKEN; gh accepts either GH_TOKEN or GITHUB_TOKEN no-op we keep GITHUB_TOKEN

Post-merge test plan for this branch

  • Manually trigger Build Node (Standard) on v22.21.1 via workflow_dispatch. Assets appear in node-v22.21.1-release.
  • Build Node-Packages runs (via workflow_run) or is dispatched. Assets appear.
  • Build Custom Fibers runs or is dispatched. Assets appear.
  • Build Node (FIPS) dispatched with BUILD_REF=v22.21.1. Assets appear in node-v22.21.1-fips-release.
  • Spot-check asset sha256sum matches pre-migration.

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 four release-upload call-sites on v22.21.1:

  - build-node.yml
  - build-node-fibers.yml
  - build-node-openssl-fips.yml
  - build-node-packages.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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant