From bafe4512c428b683531a26a2feb82ebcfa812910 Mon Sep 17 00:00:00 2001 From: Nhan Phan Date: Mon, 30 Dec 2024 15:34:14 -0800 Subject: [PATCH] CI release management (#206) * update release tagging and deploy * unused config * use right name, set right tag * use ref --- .github/workflows/benchmark-summary.yml | 8 +- .github/workflows/benchmark.yml | 6 +- .github/workflows/build-programs.yml | 6 +- .github/workflows/build-rust-client.yml | 6 +- .github/workflows/create-release.yml | 123 ++++++++++++ .github/workflows/deploy-program.yml | 223 ++++++++++++++++------ .github/workflows/main.yml | 4 +- .github/workflows/publish-js-client.yml | 4 +- .github/workflows/publish-rust-client.yml | 2 +- .github/workflows/test-js-client.yml | 10 +- .github/workflows/test-programs.yml | 6 +- .github/workflows/test-rust-client.yml | 8 +- 12 files changed, 330 insertions(+), 76 deletions(-) create mode 100644 .github/workflows/create-release.yml diff --git a/.github/workflows/benchmark-summary.yml b/.github/workflows/benchmark-summary.yml index b897b043..a94094f2 100644 --- a/.github/workflows/benchmark-summary.yml +++ b/.github/workflows/benchmark-summary.yml @@ -1,6 +1,9 @@ name: Benchmark on: workflow_call: + inputs: + git_ref: + type: string permissions: # deployments permission to deploy GitHub pages website @@ -19,7 +22,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Git checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 + with: + ref: ${{ inputs.git_ref }} - name: Load environment variables run: cat .github/.env >> $GITHUB_ENV @@ -30,6 +35,7 @@ jobs: node: 18.x solana: ${{ env.SOLANA_VERSION }} cache: ${{ env.CACHE }} + artifacts: program-builds-${{ inputs.git_ref }} - name: Install dependencies uses: metaplex-foundation/actions/install-node-dependencies@v1 diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index aaa9a3d6..2e244100 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -1,6 +1,9 @@ name: Benchmark on: workflow_call: + inputs: + git_ref: + type: string permissions: # deployments permission to deploy GitHub pages website @@ -17,7 +20,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Git checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Load environment variables run: cat .github/.env >> $GITHUB_ENV @@ -28,6 +31,7 @@ jobs: node: 18.x solana: ${{ env.SOLANA_VERSION }} cache: ${{ env.CACHE }} + artifacts: program-builds-${{ inputs.git_ref }} - name: Install dependencies uses: metaplex-foundation/actions/install-node-dependencies@v1 diff --git a/.github/workflows/build-programs.yml b/.github/workflows/build-programs.yml index b245c0a6..b1a0045c 100644 --- a/.github/workflows/build-programs.yml +++ b/.github/workflows/build-programs.yml @@ -7,6 +7,8 @@ on: type: string solana: type: string + git_ref: + type: string workflow_dispatch: inputs: rust: @@ -29,7 +31,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Git checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Load environment variables run: cat .github/.env >> $GITHUB_ENV @@ -59,7 +61,7 @@ jobs: - name: Upload program builds uses: actions/upload-artifact@v4 with: - name: program-builds + name: program-builds-${{ inputs.git_ref }} # First wildcard ensures exported paths are consistently under the programs folder. path: ./program*/.bin/*.so include-hidden-files: true diff --git a/.github/workflows/build-rust-client.yml b/.github/workflows/build-rust-client.yml index e94ea054..d3e001bc 100644 --- a/.github/workflows/build-rust-client.yml +++ b/.github/workflows/build-rust-client.yml @@ -7,6 +7,8 @@ on: type: string solana: type: string + git_ref: + type: string workflow_dispatch: inputs: rust: @@ -29,7 +31,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Git checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 + with: + ref: ${{ inputs.git_ref }} - name: Load environment variables run: cat .github/.env >> $GITHUB_ENV diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml new file mode 100644 index 00000000..11d0e415 --- /dev/null +++ b/.github/workflows/create-release.yml @@ -0,0 +1,123 @@ +name: Create release + +on: + workflow_dispatch: + inputs: + program: + description: Program + required: true + default: core + type: choice + options: + - core + bump: + description: Version bump + required: true + default: patch + type: choice + options: + - patch + - minor + - major + git_ref: + description: Commit hash or branch to create release + required: false + type: string + default: main + + +env: + CACHE: true + +jobs: + build_programs: + name: Programs + uses: ./.github/workflows/build-programs.yml + secrets: inherit + with: + git_ref: ${{ inputs.git_ref }} + + test_js: + name: JS client + needs: build_programs + uses: ./.github/workflows/test-js-client.yml + secrets: inherit + with: + git_ref: ${{ inputs.git_ref }} + + create_release: + name: Create program release + runs-on: ubuntu-latest + needs: test_js + permissions: + contents: write + steps: + - name: Git checkout + uses: actions/checkout@v4 + with: + ref: ${{ inputs.git_ref }} + - name: Bump Program Version + run: | + git fetch --tags --all + VERSION=`git tag -l --sort -version:refname "release/${{ inputs.program }}@*" | head -n 1 | sed 's|release/${{ inputs.program }}@||'` + MAJOR=`echo ${VERSION} | cut -d. -f1` + MINOR=`echo ${VERSION} | cut -d. -f2` + PATCH=`echo ${VERSION} | cut -d. -f3` + + if [ "${{ inputs.bump }}" == "major" ]; then + MAJOR=$((MAJOR + 1)) + MINOR=0 + PATCH=0 + elif [ "${{ inputs.bump }}" == "minor" ]; then + MINOR=$((MINOR + 1)) + PATCH=0 + else + PATCH=$((PATCH + 1)) + fi + + PROGRAM_VERSION="${MAJOR}.${MINOR}.${PATCH}" + + echo PROGRAM_VERSION="${PROGRAM_VERSION}" >> $GITHUB_ENV + + - name: Download Program Builds + uses: actions/download-artifact@v4 + with: + name: program-builds-${{ inputs.git_ref }} + + - name: Identify Program + run: | + PROGRAM_NAME="mpl_core" >> $GITHUB_ENV + + - name: Create Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: release/${{ inputs.program }}@${{ env.PROGRAM_VERSION }} + release_name: ${{ inputs.program }} v${{ env.PROGRAM_VERSION }} + body: | + Release ${{ inputs.program }} v${{ env.PROGRAM_VERSION }} + draft: false + prerelease: false + + - name: Upload Release Asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./programs/.bin/${{ env.PROGRAM_NAME }}.so + asset_name: ${{ env.PROGRAM_NAME }}.so + asset_content_type: application/octet-stream + + # - name: Update latest tag + # uses: actions/github-script@v5 + # with: + # script: | + # github.rest.git.createRef({ + # owner: context.repo.owner, + # repo: context.repo.repo, + # ref: 'refs/tags/release/${{ inputs.program }}@latest', + # sha: '${{ github.sha }}' + # }); \ No newline at end of file diff --git a/.github/workflows/deploy-program.yml b/.github/workflows/deploy-program.yml index 812c3108..d879afea 100644 --- a/.github/workflows/deploy-program.yml +++ b/.github/workflows/deploy-program.yml @@ -3,6 +3,11 @@ name: Deploy Program on: workflow_dispatch: inputs: + git_ref: + description: Release tag (release/core@0.2.2) or commit to deploy + required: true + type: string + default: release/core@0.2.2 program: description: Program required: true @@ -18,29 +23,44 @@ on: options: - devnet - mainnet-beta - version_program: - description: Version program - required: true - default: false + - sonic-devnet + - sonic-testnet + - eclipse-mainnet + - eclipse-devnet + dry_run: + description: Dry run + required: false type: boolean - level: - description: Level - required: true - default: patch - type: choice - options: - - patch - - minor - - major + default: false env: CACHE: true jobs: + check_tag: + name: 'Check tag' + runs-on: ubuntu-latest + outputs: + program: ${{ steps.set_program.outputs.program }} + type: ${{ steps.set_program.outputs.type }} + steps: + - name: Check tag + id: set_program + run: | + echo program="core" >> $GITHUB_OUTPUT + if [[ "${{ inputs.git_ref }}" =~ ^release/core@* ]]; then + echo type="release" >> $GITHUB_OUTPUT + else + echo type="ref" >> $GITHUB_OUTPUT + fi build_programs: name: Programs uses: ./.github/workflows/build-programs.yml secrets: inherit + needs: check_tag + if: needs.check_tag.outputs.type == 'ref' + with: + git_ref: ${{ inputs.git_ref }} test_programs: name: Programs @@ -54,24 +74,29 @@ jobs: needs: build_programs uses: ./.github/workflows/test-js-client.yml secrets: inherit + with: + git_ref: ${{ inputs.git_ref }} test_rust: name: Rust client needs: build_programs uses: ./.github/workflows/test-rust-client.yml secrets: inherit + with: + git_ref: ${{ inputs.git_ref }} deploy_program: name: Program / Deploy runs-on: ubuntu-latest-16-cores - needs: [test_programs, test_js, test_rust] + needs: [test_js, test_programs, test_rust, check_tag] permissions: contents: write steps: - name: Git checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: token: ${{ secrets.SVC_TOKEN }} + ref: ${{ inputs.git_ref }} - name: Load environment variables run: cat .github/.env >> $GITHUB_ENV @@ -95,52 +120,97 @@ jobs: - name: Set RPC run: | + # We do this if waterfall because github actions does not allow dynamic access to secrets if [ "${{ inputs.cluster }}" == "devnet" ]; then echo RPC=${{ secrets.DEVNET_RPC }} >> $GITHUB_ENV - else + elif [ "${{ inputs.cluster }}" == "mainnet-beta" ]; then echo RPC=${{ secrets.MAINNET_RPC }} >> $GITHUB_ENV + elif [ "${{ inputs.cluster }}" == "sonic-devnet" ]; then + echo RPC=${{ secrets.SONIC_DEVNET_RPC }} >> $GITHUB_ENV + elif [ "${{ inputs.cluster }}" == "sonic-testnet" ]; then + echo RPC=${{ secrets.SONIC_TESTNET_RPC }} >> $GITHUB_ENV + elif [ "${{ inputs.cluster }}" == "eclipse-devnet" ]; then + echo RPC=${{ secrets.ECLIPSE_DEVNET_RPC }} >> $GITHUB_ENV + elif [ "${{ inputs.cluster }}" == "eclipse-testnet" ]; then + echo RPC=${{ secrets.ECLIPSE_TESTNET_RPC }} >> $GITHUB_ENV + elif [ "${{ inputs.cluster }}" == "eclipse-mainnet" ]; then + echo RPC=${{ secrets.ECLIPSE_MAINNET_RPC }} >> $GITHUB_ENV fi - - name: Determine program version + - name: Identify Program run: | - IDL_NAME="mpl_${{ inputs.program }}" - VERSION=`jq '.version' ./idls/${IDL_NAME}.json | sed 's/"//g'` - MAJOR=`echo ${VERSION} | cut -d. -f1` - MINOR=`echo ${VERSION} | cut -d. -f2` - PATCH=`echo ${VERSION} | cut -d. -f3` - - if [ "${{ inputs.level }}" == "major" ]; then - MAJOR=$((MAJOR + 1))E - MINOR=0 - PATCH=0 - elif [ "${{ inputs.level }}" == "minor" ]; then - MINOR=$((MINOR + 1)) - PATCH=0 + echo PROGRAM_NAME="mpl_core" >> $GITHUB_ENV + echo ${{ secrets.CORE_ID }} > ./program-id.json + + if [[ "${{ inputs.cluster }}" == "sonic"* ]]; then + echo ${{ secrets.CORE_SONIC_DEPLOY_KEY }} > ./deploy-key.json + echo DEPLOY_TYPE="direct" >> $GITHUB_ENV + elif [[ "${{ inputs.cluster }}" == "eclipse"* ]]; then + echo ${{ secrets.CORE_ECLIPSE_DEPLOY_KEY }} > ./deploy-key.json + echo DEPLOY_TYPE="direct" >> $GITHUB_ENV + elif [[ "${{ inputs.cluster }}" == "devnet" ]]; then + echo ${{ secrets.CORE_DEPLOYER_KEY }} > ./deployer-key.json + echo DEPLOY_TYPE="squads" >> $GITHUB_ENV + echo SQUADS_MULTISIG="Gs6jZWxXFvmZtBcyYr6fBXX5ikwRTemBDS4f6kFuB31U" >> $GITHUB_ENV + echo SQUADS_VAULT="Fsxr5WVKZZoeb7xgwTWRHymSRVGY9vk7m5B5GPu1KU59" >> $GITHUB_ENV + elif [[ "${{ inputs.cluster }}" == "mainnet-beta" ]]; then + echo ${{ secrets.CORE_DEPLOYER_KEY }} > ./deployer-key.json + echo DEPLOY_TYPE="squads" >> $GITHUB_ENV + echo SQUADS_MULTISIG="Gs6jZWxXFvmZtBcyYr6fBXX5ikwRTemBDS4f6kFuB31U" >> $GITHUB_ENV + echo SQUADS_VAULT="Fsxr5WVKZZoeb7xgwTWRHymSRVGY9vk7m5B5GPu1KU59" >> $GITHUB_ENV else - PATCH=$((PATCH + 1)) - fi - - PROGRAM_VERSION="${MAJOR}.${MINOR}.${PATCH}" - - cp ./idls/${IDL_NAME}.json ./idls/${IDL_NAME}-previous.json - jq ".version = \"${PROGRAM_VERSION}\"" ./idls/${IDL_NAME}-previous.json > ./idls/${IDL_NAME}.json - rm ./idls/${IDL_NAME}-previous.json - - echo PROGRAM_VERSION="${PROGRAM_VERSION}" >> $GITHUB_ENV + echo "Invalid cluster: ${{ inputs.cluster }}" + exit 1 + fi - name: Download program builds uses: actions/download-artifact@v4 + if: needs.check_tag.outputs.type == 'ref' + with: + name: program-builds-${{ inputs.git_ref }} + + - name: Download release asset + uses: actions/github-script@v5 + id: get_release + if: needs.check_tag.outputs.type == 'release' with: - name: program-builds + script: | + const tag = "${{ inputs.git_ref }}"; + const assetName = "${{ env.PROGRAM_NAME }}.so"; - - name: Deploy Program + // Fetch the release associated with the tag + const release = await github.rest.repos.getReleaseByTag({ + owner: context.repo.owner, + repo: context.repo.repo, + tag: tag + }); + + if (release.status !== 200) { + throw new Error(`Failed to fetch release for tag ${tag}`); + } + + const asset = release.data.assets.find(asset => asset.name === assetName); + if (!asset) { + throw new Error(`Asset ${assetName} not found in release tagged ${tag}`); + } + + core.setOutput("url", asset.url); + + - name: Download the Selected Asset + if: needs.check_tag.outputs.type == 'release' run: | - echo "Deploying ${{ inputs.program }} to ${{ inputs.cluster }}" + mkdir -p ${{ github.workspace }}/programs/.bin + curl -L -o ${{ github.workspace }}/programs/.bin/${{ env.PROGRAM_NAME }}.so \ + -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ + -H "Accept: application/octet-stream" \ + "${{ steps.get_release.outputs.url }}" - echo ${{ secrets.CORE_DEPLOYER_KEY }} > ./deployer-key.json - echo ${{ secrets.CORE_ID }} > ./program-id.json + - name: Deploy Program + if: github.event.inputs.dry_run == 'false' && env.DEPLOY_TYPE == 'direct' + run: | + echo "Deploying ${{ needs.check_tag.outputs.program }} to ${{ inputs.cluster }}" - solana -v program deploy ./programs/.bin/mpl_${{ inputs.program }}_program.so \ + solana -v program deploy ./programs/.bin/mpl_${{ env.PROGRAM_NAME }}_program.so \ -u ${{ env.RPC }} \ --program-id ./program-id.json \ -k ./deployer-key.json \ @@ -150,23 +220,54 @@ jobs: rm ./deployer-key.json rm ./program-id.json - - name: Version program - working-directory: ./programs/mpl-${{ inputs.program }}/program - if: github.event.inputs.version_program == 'true' + - name: Deploy squads buffer + if: github.event.inputs.dry_run == 'false' && env.DEPLOY_TYPE == 'squads' run: | - git stash - git config user.name "${{ env.COMMIT_USER_NAME }}" - git config user.email "${{ env.COMMIT_USER_EMAIL }}" + echo "Deploying buffer for ${{ inputs.program }} on ${{ inputs.cluster }}" + echo ${{ secrets.SQUADS_BOT_KEY }} > ./submitter-key.json + + BUFFER=$(solana program write-buffer -u ${{ env.RPC }} -k ./submitter-key.json --max-sign-attempts 100 --use-rpc ./programs/.bin/mpl_${{ env.PROGRAM_NAME }}_program.so | awk '{print $2}') + echo "Buffer: $BUFFER" - cargo login ${{ secrets.CRATES_TOKEN }} - cargo release ${{ env.PROGRAM_VERSION }} --no-confirm --no-push --no-tag --no-publish --execute + solana program set-buffer-authority $BUFFER \ + --new-buffer-authority ${{ env.SQUADS_VAULT }} \ + -k ./submitter-key.json \ + -u ${{ env.RPC }} - git reset --soft HEAD~1 - git stash pop + rm ./submitter-key.json + + echo "BUFFER=$BUFFER" >> $GITHUB_ENV + + + - name: Create Squads proposal + if: github.event.inputs.dry_run == 'false' && env.DEPLOY_TYPE == 'squads' + uses: metaplex-foundation/squads-program-upgrade + with: + network-url: ${{ env.RPC }} + program-multisig: ${{ env.SQUADS_MULTISIG }} + program-id: 'CoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d' + program-index: '1' + buffer: ${{ env.BUFFER }} + spill-address: 'botTxAkJhuCtNNn9xsH8fHJjzTkcN6XD4dR3R5hkzV2' + authority: 'botTxAkJhuCtNNn9xsH8fHJjzTkcN6XD4dR3R5hkzV2' + name: 'Deploy ${{ inputs.git_ref }}}' + keypair: ${{ env.SQUADS_BOT_KEY }} - - name: Commit and tag new version - uses: stefanzweifel/git-auto-commit-action@v4 - if: github.event.inputs.version_program == 'true' && github.event.inputs.cluster == 'mainnet-beta' + - name: Create env tag + uses: actions/github-script@v5 with: - commit_message: Deploy mpl-${{ inputs.program }} program v${{ env.PROGRAM_VERSION }} - tagging_message: mpl-${{ inputs.program }}@v${{ env.PROGRAM_VERSION }} + script: | + const refData = await github.rest.git.getRef({ + owner: context.repo.owner, + repo: context.repo.repo, + ref: 'tags/${{ inputs.git_ref }}' + }); + if (refData.status !== 200) { + throw new Error('Failed to fetch existing tag'); + } + github.rest.git.createRef({ + owner: context.repo.owner, + repo: context.repo.repo, + ref: 'refs/tags/${{ needs.check_tag.outputs.program }}-${{ inputs.cluster }}', + sha: refData.data.object.sha + }); diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7af1b6b0..83d3fdd4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -21,7 +21,7 @@ jobs: rust_client: ${{ steps.changes.outputs.rust_client }} steps: - name: Git checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Load environment variables run: cat .github/.env >> $GITHUB_ENV @@ -63,7 +63,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Git checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Load environment variables run: cat .github/.env >> $GITHUB_ENV diff --git a/.github/workflows/publish-js-client.yml b/.github/workflows/publish-js-client.yml index b8123664..fa53b190 100644 --- a/.github/workflows/publish-js-client.yml +++ b/.github/workflows/publish-js-client.yml @@ -50,7 +50,7 @@ jobs: contents: write steps: - name: Git checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Load environment variables run: cat .github/.env >> $GITHUB_ENV @@ -113,7 +113,7 @@ jobs: url: ${{ steps.deploy.outputs.url }} steps: - name: Git checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ github.ref }} diff --git a/.github/workflows/publish-rust-client.yml b/.github/workflows/publish-rust-client.yml index eb3a049e..07e6190d 100644 --- a/.github/workflows/publish-rust-client.yml +++ b/.github/workflows/publish-rust-client.yml @@ -55,7 +55,7 @@ jobs: contents: write steps: - name: Git checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Load environment variables run: cat .github/.env >> $GITHUB_ENV diff --git a/.github/workflows/test-js-client.yml b/.github/workflows/test-js-client.yml index 5b0f891b..b2fad173 100644 --- a/.github/workflows/test-js-client.yml +++ b/.github/workflows/test-js-client.yml @@ -2,6 +2,9 @@ name: Test JS client on: workflow_call: + inputs: + git_ref: + type: string env: CACHE: true @@ -15,7 +18,9 @@ jobs: node: ["16.x", "18.x"] steps: - name: Git checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 + with: + ref: ${{ inputs.git_ref }} - name: Load environment variables run: cat .github/.env >> $GITHUB_ENV @@ -26,6 +31,7 @@ jobs: node: ${{ matrix.node }} solana: ${{ env.SOLANA_VERSION }} cache: ${{ env.CACHE }} + artifacts: program-builds-${{ inputs.git_ref }} - name: Install dependencies uses: metaplex-foundation/actions/install-node-dependencies@v1 @@ -47,7 +53,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Git checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Load environment variables run: cat .github/.env >> $GITHUB_ENV diff --git a/.github/workflows/test-programs.yml b/.github/workflows/test-programs.yml index d9d24efc..ea5d880d 100644 --- a/.github/workflows/test-programs.yml +++ b/.github/workflows/test-programs.yml @@ -5,6 +5,8 @@ on: inputs: program_matrix: type: string + git_ref: + type: string env: CACHE: true @@ -18,7 +20,9 @@ jobs: program: ${{ fromJson(inputs.program_matrix) }} steps: - name: Git checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 + with: + ref: ${{ inputs.git_ref }} - name: Load environment variables run: cat .github/.env >> $GITHUB_ENV diff --git a/.github/workflows/test-rust-client.yml b/.github/workflows/test-rust-client.yml index 677c8194..7334b9d0 100644 --- a/.github/workflows/test-rust-client.yml +++ b/.github/workflows/test-rust-client.yml @@ -5,6 +5,8 @@ on: inputs: program_matrix: type: string + git_ref: + type: string env: CACHE: true @@ -15,7 +17,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Git checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 + with: + ref: ${{ inputs.git_ref }} - name: Load environment variables run: cat .github/.env >> $GITHUB_ENV @@ -40,7 +44,7 @@ jobs: - name: Download program builds uses: actions/download-artifact@v4 with: - name: program-builds + name: program-builds-${{ inputs.git_ref }} - name: Run tests shell: bash