From a554d5db9fc4cc18756b710c8de7dc07b6b1116e Mon Sep 17 00:00:00 2001 From: SimonRastikian <43679791+SimonRastikian@users.noreply.github.com> Date: Fri, 20 Feb 2026 19:48:26 +0100 Subject: [PATCH 01/22] Automatic release tag creation on release branch merge --- .github/workflows/release_tag.yml | 57 +++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 .github/workflows/release_tag.yml diff --git a/.github/workflows/release_tag.yml b/.github/workflows/release_tag.yml new file mode 100644 index 000000000..a9da3950e --- /dev/null +++ b/.github/workflows/release_tag.yml @@ -0,0 +1,57 @@ +name: Create Release Tag + +# Prevent duplicate runs for the same workflow + branch combination. +# If a new run starts while one is in progress, the older run is cancelled. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +# Trigger this workflow when a pull request targeting main is closed. +# Note: "closed" fires for both merged and unmerged PRs — the job-level +# `if` condition below filters to only merged release PRs. +on: + pull_request: + branches: + - main + types: + - closed + +jobs: + create-tag: + name: "Create release tag" + # Only run when: + # 1. The PR was actually merged (not just closed/dismissed). + # 2. The source branch follows the release naming convention (release/v*). + if: github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'release/v') + runs-on: warp-ubuntu-2404-x64-2x + # Write permission on contents is required to push a new tag. + permissions: + contents: write + + steps: + # Extract the semver version from the branch name. + # e.g. "release/v3.6.0" -> version="3.6.0", tag="v3.6.0" + - name: Extract version from branch name + id: version + env: + BRANCH: ${{ github.event.pull_request.head.ref }} + run: | + VERSION="${BRANCH#release/v}" + echo "version=${VERSION}" >> "$GITHUB_OUTPUT" + echo "tag=v${VERSION}" >> "$GITHUB_OUTPUT" + + # Checkout the main branch so the tag points to the merge commit. + - name: Checkout + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + ref: main + + # Create a lightweight git tag and push it to origin. + # This tag can then be used by other workflows (e.g. Docker release) + # or to create a GitHub release. + - name: Create and push tag + env: + TAG: ${{ steps.version.outputs.tag }} + run: | + git tag "$TAG" + git push origin "$TAG" From bc3dff9ab6f33d33575ca586314741aa3b108862 Mon Sep 17 00:00:00 2001 From: SimonRastikian <43679791+SimonRastikian@users.noreply.github.com> Date: Fri, 20 Feb 2026 19:51:24 +0100 Subject: [PATCH 02/22] Renaming fil --- .github/workflows/{release_tag.yml => release.yml} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename .github/workflows/{release_tag.yml => release.yml} (98%) diff --git a/.github/workflows/release_tag.yml b/.github/workflows/release.yml similarity index 98% rename from .github/workflows/release_tag.yml rename to .github/workflows/release.yml index a9da3950e..9fd621ab0 100644 --- a/.github/workflows/release_tag.yml +++ b/.github/workflows/release.yml @@ -1,4 +1,4 @@ -name: Create Release Tag +name: Release # Prevent duplicate runs for the same workflow + branch combination. # If a new run starts while one is in progress, the older run is cancelled. From d52b961f6a35448534262b9a01c03b0ca1b962e9 Mon Sep 17 00:00:00 2001 From: SimonRastikian <43679791+SimonRastikian@users.noreply.github.com> Date: Fri, 20 Feb 2026 19:56:19 +0100 Subject: [PATCH 03/22] Adding automatic Running workflows --- .github/workflows/release.yml | 53 +++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9fd621ab0..9bfc24b37 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -28,17 +28,26 @@ jobs: permissions: contents: write + # Expose version and commit hash to downstream jobs. + outputs: + version: ${{ steps.version.outputs.version }} + tag: ${{ steps.version.outputs.tag }} + short-sha: ${{ steps.version.outputs.short-sha }} + steps: # Extract the semver version from the branch name. # e.g. "release/v3.6.0" -> version="3.6.0", tag="v3.6.0" + # Also compute the 7-char commit hash used as the Docker source tag. - name: Extract version from branch name id: version env: BRANCH: ${{ github.event.pull_request.head.ref }} + SHA: ${{ github.event.pull_request.merge_commit_sha }} run: | VERSION="${BRANCH#release/v}" echo "version=${VERSION}" >> "$GITHUB_OUTPUT" echo "tag=v${VERSION}" >> "$GITHUB_OUTPUT" + echo "short-sha=${SHA::7}" >> "$GITHUB_OUTPUT" # Checkout the main branch so the tag points to the merge commit. - name: Checkout @@ -47,11 +56,51 @@ jobs: ref: main # Create a lightweight git tag and push it to origin. - # This tag can then be used by other workflows (e.g. Docker release) - # or to create a GitHub release. - name: Create and push tag env: TAG: ${{ steps.version.outputs.tag }} run: | git tag "$TAG" git push origin "$TAG" + + # Trigger the existing Docker retag workflows for each image. + # These are the same workflows you'd normally trigger manually from the Actions UI. + retag-docker-images: + name: "Retag Docker images" + needs: create-tag + runs-on: warp-ubuntu-2404-x64-2x + permissions: + actions: write + + steps: + # Trigger the launcher retag workflow. + - name: Retag mpc-launcher + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh workflow run docker_launcher_release.yml \ + --repo "${{ github.repository }}" \ + -f source-tag="main-${{ needs.create-tag.outputs.short-sha }}" \ + -f release-tag="${{ needs.create-tag.outputs.version }}" + + # Trigger the node retag workflow for mpc-node-gcp. + - name: Retag mpc-node-gcp + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh workflow run docker_node_release.yml \ + --repo "${{ github.repository }}" \ + -f source-tag="main-${{ needs.create-tag.outputs.short-sha }}" \ + -f release-tag="${{ needs.create-tag.outputs.version }}" \ + -f repository="mpc-node-gcp" + + # Trigger the node retag workflow for mpc-node. + - name: Retag mpc-node + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh workflow run docker_node_release.yml \ + --repo "${{ github.repository }}" \ + -f source-tag="main-${{ needs.create-tag.outputs.short-sha }}" \ + -f release-tag="${{ needs.create-tag.outputs.version }}" \ + -f repository="mpc-node" From 0b010db67976dd598d36e33d1627844a43e2b8fc Mon Sep 17 00:00:00 2001 From: SimonRastikian <43679791+SimonRastikian@users.noreply.github.com> Date: Fri, 20 Feb 2026 20:07:46 +0100 Subject: [PATCH 04/22] Trigering workflows and storing the digest and image id --- .github/workflows/release.yml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9bfc24b37..00ee32220 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -104,3 +104,30 @@ jobs: -f source-tag="main-${{ needs.create-tag.outputs.short-sha }}" \ -f release-tag="${{ needs.create-tag.outputs.version }}" \ -f repository="mpc-node" + + # Wait for the retag workflows to complete before inspecting. + - name: Wait for retag workflows + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + echo "Waiting 60s for retag workflows to complete..." + sleep 60 + + - name: Install skopeo + run: | + sudo apt-get update + sudo apt-get install -y skopeo + + # Inspect each retagged image and store Manifest digest and Image ID as outputs. + - name: Get image digests + id: digests + env: + RELEASE_TAG: ${{ needs.create-tag.outputs.version }} + run: | + for REPO in mpc-launcher mpc-node-gcp mpc-node; do + SAFE_NAME="${REPO//-/_}" + MANIFEST_DIGEST=$(skopeo inspect docker://nearone/$REPO:$RELEASE_TAG | jq -r '.Digest') + IMAGE_ID=$(skopeo inspect --raw docker://nearone/$REPO:$RELEASE_TAG | jq -r '.config.digest') + echo "${SAFE_NAME}_manifest_digest=$MANIFEST_DIGEST" >> "$GITHUB_OUTPUT" + echo "${SAFE_NAME}_image_id=$IMAGE_ID" >> "$GITHUB_OUTPUT" + done From 7abcf95209ea7b7467ac25f111b9fc8d1e0ff6e6 Mon Sep 17 00:00:00 2001 From: SimonRastikian <43679791+SimonRastikian@users.noreply.github.com> Date: Fri, 20 Feb 2026 20:16:29 +0100 Subject: [PATCH 05/22] Building the contract --- .github/workflows/release.yml | 54 +++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 00ee32220..49f2f53f4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -131,3 +131,57 @@ jobs: echo "${SAFE_NAME}_manifest_digest=$MANIFEST_DIGEST" >> "$GITHUB_OUTPUT" echo "${SAFE_NAME}_image_id=$IMAGE_ID" >> "$GITHUB_OUTPUT" done + + # Build the smart contract using reproducible builds, rename the artifacts + # with the release version, and package them into a .tar.gz archive. + # This job runs in parallel with retag-docker-images since both only + # depend on create-tag. + build-contract: + name: "Build contract" + needs: create-tag + # Uses a 16x runner because the reproducible contract build is resource-intensive. + runs-on: warp-ubuntu-2404-x64-16x + permissions: + contents: read + + steps: + # Checkout main so we build the code that includes the version bump. + - name: Checkout + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + ref: main + + # Restore cached Rust dependencies to speed up the build. + # save-if: false because we only want to read from the cache, not update it + # (the main CI workflow handles saving). + - name: Cache Rust dependencies + uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2.8.1 + with: + save-if: false + cache-provider: "warpbuild" + + # Build the contract with reproducible-wasm to ensure deterministic output. + # This produces mpc_contract.wasm and mpc_contract_abi.json + # under target/near/mpc_contract/. + - name: Build contract + run: cargo near build reproducible-wasm --manifest-path crates/contract/Cargo.toml + + # Rename the build outputs to include the release version and + # compress them into a single .tar.gz archive for distribution. + # e.g. mpc-contract-v3.6.0.wasm, mpc-contract-v3.6.0-abi.json + - name: Package contract artifacts + env: + VERSION: ${{ needs.create-tag.outputs.version }} + run: | + cd target/near/mpc_contract/ + mv mpc_contract.wasm "mpc-contract-v${VERSION}.wasm" + mv mpc_contract_abi.json "mpc-contract-v${VERSION}-abi.json" + tar -czf "mpc-contract-v${VERSION}.tar.gz" "mpc-contract-v${VERSION}.wasm" "mpc-contract-v${VERSION}-abi.json" + + # Upload the .tar.gz as a GitHub Actions artifact so downstream jobs + # (e.g. creating the GitHub release) can download and attach it. + - name: Upload contract artifact + uses: actions/upload-artifact@ea165f8d65b6db9a6b7e75b195db6a7b2bcf4bac # v4.6.2 + with: + name: mpc-contract + path: target/near/mpc_contract/mpc-contract-v${{ needs.create-tag.outputs.version }}.tar.gz From f783bf0aa22bcb685c098099e111dfbc0a66f1a7 Mon Sep 17 00:00:00 2001 From: SimonRastikian <43679791+SimonRastikian@users.noreply.github.com> Date: Fri, 20 Feb 2026 20:18:50 +0100 Subject: [PATCH 06/22] Contract hash --- .github/workflows/release.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 49f2f53f4..67d571312 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -166,6 +166,13 @@ jobs: - name: Build contract run: cargo near build reproducible-wasm --manifest-path crates/contract/Cargo.toml + # Compute the SHA-256 hash of the compiled contract .wasm before renaming. + # Used later in the GitHub release notes so users can verify contract integrity. + - name: Compute contract hash + run: | + CONTRACT_HASH=$(sha256sum target/near/mpc_contract/mpc_contract.wasm | awk '{print $1}') + echo "CONTRACT_HASH=$CONTRACT_HASH" >> "$GITHUB_ENV" + # Rename the build outputs to include the release version and # compress them into a single .tar.gz archive for distribution. # e.g. mpc-contract-v3.6.0.wasm, mpc-contract-v3.6.0-abi.json From ca7fe4eb9d5f6d051d6ddd779bfe84606e280a58 Mon Sep 17 00:00:00 2001 From: SimonRastikian <43679791+SimonRastikian@users.noreply.github.com> Date: Fri, 20 Feb 2026 20:24:42 +0100 Subject: [PATCH 07/22] create the draft release --- .github/workflows/release.yml | 95 +++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 67d571312..4c0d5957c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -72,6 +72,15 @@ jobs: permissions: actions: write + # Expose image digests to downstream jobs. + outputs: + mpc_node_manifest_digest: ${{ steps.digests.outputs.mpc_node_manifest_digest }} + mpc_node_image_id: ${{ steps.digests.outputs.mpc_node_image_id }} + mpc_node_gcp_manifest_digest: ${{ steps.digests.outputs.mpc_node_gcp_manifest_digest }} + mpc_node_gcp_image_id: ${{ steps.digests.outputs.mpc_node_gcp_image_id }} + mpc_launcher_manifest_digest: ${{ steps.digests.outputs.mpc_launcher_manifest_digest }} + mpc_launcher_image_id: ${{ steps.digests.outputs.mpc_launcher_image_id }} + steps: # Trigger the launcher retag workflow. - name: Retag mpc-launcher @@ -144,6 +153,10 @@ jobs: permissions: contents: read + # Expose contract hash to downstream jobs. + outputs: + contract-hash: ${{ steps.contract-hash.outputs.sha256 }} + steps: # Checkout main so we build the code that includes the version bump. - name: Checkout @@ -169,9 +182,11 @@ jobs: # Compute the SHA-256 hash of the compiled contract .wasm before renaming. # Used later in the GitHub release notes so users can verify contract integrity. - name: Compute contract hash + id: contract-hash run: | CONTRACT_HASH=$(sha256sum target/near/mpc_contract/mpc_contract.wasm | awk '{print $1}') echo "CONTRACT_HASH=$CONTRACT_HASH" >> "$GITHUB_ENV" + echo "sha256=$CONTRACT_HASH" >> "$GITHUB_OUTPUT" # Rename the build outputs to include the release version and # compress them into a single .tar.gz archive for distribution. @@ -192,3 +207,83 @@ jobs: with: name: mpc-contract path: target/near/mpc_contract/mpc-contract-v${{ needs.create-tag.outputs.version }}.tar.gz + + # Create a draft GitHub release with the changelog, Docker image info, + # and the contract artifact attached. + # Runs after both retag-docker-images and build-contract complete. + create-release: + name: "Create draft GitHub release" + needs: [create-tag, retag-docker-images, build-contract] + runs-on: warp-ubuntu-2404-x64-2x + permissions: + contents: write + + steps: + # Checkout is needed for git-cliff to generate the changelog. + - name: Checkout + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + ref: main + fetch-depth: 0 + + # Generate the changelog entries for this release only. + - name: Generate changelog + id: changelog + env: + VERSION: ${{ needs.create-tag.outputs.version }} + run: | + git-cliff -t "$VERSION" --latest > release-notes-raw.md + + # Download the contract .tar.gz uploaded by the build-contract job. + - name: Download contract artifact + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + name: mpc-contract + + # Compose the full release body: changelog + Docker images + contract hash. + - name: Compose release body + env: + VERSION: ${{ needs.create-tag.outputs.version }} + NODE_MANIFEST: ${{ needs.retag-docker-images.outputs.mpc_node_manifest_digest }} + NODE_IMAGE_ID: ${{ needs.retag-docker-images.outputs.mpc_node_image_id }} + NODE_GCP_MANIFEST: ${{ needs.retag-docker-images.outputs.mpc_node_gcp_manifest_digest }} + NODE_GCP_IMAGE_ID: ${{ needs.retag-docker-images.outputs.mpc_node_gcp_image_id }} + LAUNCHER_MANIFEST: ${{ needs.retag-docker-images.outputs.mpc_launcher_manifest_digest }} + LAUNCHER_IMAGE_ID: ${{ needs.retag-docker-images.outputs.mpc_launcher_image_id }} + CONTRACT_HASH: ${{ needs.build-contract.outputs.contract-hash }} + run: | + cat > release-notes.md < Date: Fri, 20 Feb 2026 20:25:40 +0100 Subject: [PATCH 08/22] Change the title of the draft --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4c0d5957c..bcf735e55 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -283,7 +283,7 @@ jobs: run: | gh release create "$TAG" \ --repo "${{ github.repository }}" \ - --title "v${VERSION}" \ + --title "MPC ${VERSION}" \ --notes-file release-notes.md \ --draft \ "mpc-contract-v${VERSION}.tar.gz" From d1bbd5b975795bc36490f65b12deb62763771cdb Mon Sep 17 00:00:00 2001 From: SimonRastikian <43679791+SimonRastikian@users.noreply.github.com> Date: Fri, 20 Feb 2026 20:28:11 +0100 Subject: [PATCH 09/22] tabs issues --- .github/workflows/release.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bcf735e55..abacc5c01 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -257,21 +257,21 @@ jobs: ## Docker images - nearone/mpc-node:${VERSION} - Manifest digest: ${NODE_MANIFEST} - Image ID: ${NODE_IMAGE_ID} + nearone/mpc-node:${VERSION} + Manifest digest: ${NODE_MANIFEST} + Image ID: ${NODE_IMAGE_ID} - nearone/mpc-node-gcp:${VERSION} - Manifest digest: ${NODE_GCP_MANIFEST} - Image ID: ${NODE_GCP_IMAGE_ID} + nearone/mpc-node-gcp:${VERSION} + Manifest digest: ${NODE_GCP_MANIFEST} + Image ID: ${NODE_GCP_IMAGE_ID} - nearone/mpc-launcher:${VERSION} - Manifest digest: ${LAUNCHER_MANIFEST} - Image ID: ${LAUNCHER_IMAGE_ID} + nearone/mpc-launcher:${VERSION} + Manifest digest: ${LAUNCHER_MANIFEST} + Image ID: ${LAUNCHER_IMAGE_ID} ## MPC contract - digest: sha256:${CONTRACT_HASH} + digest: sha256:${CONTRACT_HASH} EOF # Create the draft release on GitHub, attaching the contract archive. From b69168adba78321d3682e6a9e6c5aa5c7e089b36 Mon Sep 17 00:00:00 2001 From: SimonRastikian <43679791+SimonRastikian@users.noreply.github.com> Date: Fri, 20 Feb 2026 20:32:53 +0100 Subject: [PATCH 10/22] Cleaning up --- .github/workflows/release.yml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index abacc5c01..5d824f4c5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -116,8 +116,6 @@ jobs: # Wait for the retag workflows to complete before inspecting. - name: Wait for retag workflows - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | echo "Waiting 60s for retag workflows to complete..." sleep 60 @@ -185,7 +183,6 @@ jobs: id: contract-hash run: | CONTRACT_HASH=$(sha256sum target/near/mpc_contract/mpc_contract.wasm | awk '{print $1}') - echo "CONTRACT_HASH=$CONTRACT_HASH" >> "$GITHUB_ENV" echo "sha256=$CONTRACT_HASH" >> "$GITHUB_OUTPUT" # Rename the build outputs to include the release version and @@ -228,7 +225,6 @@ jobs: # Generate the changelog entries for this release only. - name: Generate changelog - id: changelog env: VERSION: ${{ needs.create-tag.outputs.version }} run: | @@ -252,8 +248,8 @@ jobs: LAUNCHER_IMAGE_ID: ${{ needs.retag-docker-images.outputs.mpc_launcher_image_id }} CONTRACT_HASH: ${{ needs.build-contract.outputs.contract-hash }} run: | - cat > release-notes.md <> release-notes.md < Date: Fri, 20 Feb 2026 20:41:03 +0100 Subject: [PATCH 11/22] Do not use cliff for changelog --- .github/workflows/release.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5d824f4c5..a01129a7c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -223,12 +223,14 @@ jobs: ref: main fetch-depth: 0 - # Generate the changelog entries for this release only. - - name: Generate changelog + # Extract the changelog section for this version from CHANGELOG.md. + # Sections are delimited by "## []" headers, so we print + # everything between the current version's header and the next one. + - name: Extract changelog env: VERSION: ${{ needs.create-tag.outputs.version }} run: | - git-cliff -t "$VERSION" --latest > release-notes-raw.md + awk "/^## \\[${VERSION}\\]/{found=1; next} /^## \\[/{if(found) exit} found" CHANGELOG.md > release-notes-raw.md # Download the contract .tar.gz uploaded by the build-contract job. - name: Download contract artifact From 1c0c5ebf5f0e585b7067b94a252b6a585163c99c Mon Sep 17 00:00:00 2001 From: SimonRastikian <43679791+SimonRastikian@users.noreply.github.com> Date: Fri, 20 Feb 2026 20:47:32 +0100 Subject: [PATCH 12/22] No arbitrary sleep instead use gh watch --- .github/workflows/release.yml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a01129a7c..4c20b53c6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -114,11 +114,19 @@ jobs: -f release-tag="${{ needs.create-tag.outputs.version }}" \ -f repository="mpc-node" - # Wait for the retag workflows to complete before inspecting. + # Wait for all three dispatched retag workflows to complete. + # A brief pause lets the runs appear in the API, then gh run watch + # polls until each one finishes (with --exit-status to fail if the + # workflow itself fails). - name: Wait for retag workflows + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - echo "Waiting 60s for retag workflows to complete..." - sleep 60 + sleep 5 + for WORKFLOW in docker_launcher_release.yml docker_node_release.yml docker_node_release.yml; do + RUN_ID=$(gh run list --workflow="$WORKFLOW" --repo "${{ github.repository }}" --limit=1 --json databaseId -q '.[0].databaseId') + gh run watch "$RUN_ID" --repo "${{ github.repository }}" --exit-status + done - name: Install skopeo run: | From 072c4f6eb923491d8b9471c9b3a25a667082b5ad Mon Sep 17 00:00:00 2001 From: SimonRastikian <43679791+SimonRastikian@users.noreply.github.com> Date: Fri, 20 Feb 2026 20:52:13 +0100 Subject: [PATCH 13/22] Better waiting --- .github/workflows/release.yml | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4c20b53c6..b7f880f17 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -82,8 +82,11 @@ jobs: mpc_launcher_image_id: ${{ steps.digests.outputs.mpc_launcher_image_id }} steps: - # Trigger the launcher retag workflow. + # Dispatch each retag workflow and immediately capture its run ID. + # A brief sleep after each dispatch lets the run appear in the API + # before we query for it. - name: Retag mpc-launcher + id: launcher env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | @@ -91,9 +94,12 @@ jobs: --repo "${{ github.repository }}" \ -f source-tag="main-${{ needs.create-tag.outputs.short-sha }}" \ -f release-tag="${{ needs.create-tag.outputs.version }}" + sleep 5 + RUN_ID=$(gh run list --workflow=docker_launcher_release.yml --repo "${{ github.repository }}" --limit=1 --json databaseId -q '.[0].databaseId') + echo "run_id=$RUN_ID" >> "$GITHUB_OUTPUT" - # Trigger the node retag workflow for mpc-node-gcp. - name: Retag mpc-node-gcp + id: node-gcp env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | @@ -102,9 +108,12 @@ jobs: -f source-tag="main-${{ needs.create-tag.outputs.short-sha }}" \ -f release-tag="${{ needs.create-tag.outputs.version }}" \ -f repository="mpc-node-gcp" + sleep 5 + RUN_ID=$(gh run list --workflow=docker_node_release.yml --repo "${{ github.repository }}" --limit=1 --json databaseId -q '.[0].databaseId') + echo "run_id=$RUN_ID" >> "$GITHUB_OUTPUT" - # Trigger the node retag workflow for mpc-node. - name: Retag mpc-node + id: node env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | @@ -113,18 +122,17 @@ jobs: -f source-tag="main-${{ needs.create-tag.outputs.short-sha }}" \ -f release-tag="${{ needs.create-tag.outputs.version }}" \ -f repository="mpc-node" + sleep 5 + RUN_ID=$(gh run list --workflow=docker_node_release.yml --repo "${{ github.repository }}" --limit=1 --json databaseId -q '.[0].databaseId') + echo "run_id=$RUN_ID" >> "$GITHUB_OUTPUT" - # Wait for all three dispatched retag workflows to complete. - # A brief pause lets the runs appear in the API, then gh run watch - # polls until each one finishes (with --exit-status to fail if the - # workflow itself fails). + # Wait for all three dispatched runs to complete. + # --exit-status makes gh run watch fail if the workflow itself fails. - name: Wait for retag workflows env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - sleep 5 - for WORKFLOW in docker_launcher_release.yml docker_node_release.yml docker_node_release.yml; do - RUN_ID=$(gh run list --workflow="$WORKFLOW" --repo "${{ github.repository }}" --limit=1 --json databaseId -q '.[0].databaseId') + for RUN_ID in ${{ steps.launcher.outputs.run_id }} ${{ steps.node-gcp.outputs.run_id }} ${{ steps.node.outputs.run_id }}; do gh run watch "$RUN_ID" --repo "${{ github.repository }}" --exit-status done From 25037f401aeb7251e58146954dd5b57e64104f50 Mon Sep 17 00:00:00 2001 From: SimonRastikian <43679791+SimonRastikian@users.noreply.github.com> Date: Fri, 20 Feb 2026 20:55:17 +0100 Subject: [PATCH 14/22] Checking versioning and no inspect --raw for skopeo --- .github/workflows/release.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b7f880f17..ebcc4c20c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -45,6 +45,10 @@ jobs: SHA: ${{ github.event.pull_request.merge_commit_sha }} run: | VERSION="${BRANCH#release/v}" + if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$ ]]; then + echo "::error::Invalid semver: $VERSION" + exit 1 + fi echo "version=${VERSION}" >> "$GITHUB_OUTPUT" echo "tag=v${VERSION}" >> "$GITHUB_OUTPUT" echo "short-sha=${SHA::7}" >> "$GITHUB_OUTPUT" @@ -150,7 +154,9 @@ jobs: for REPO in mpc-launcher mpc-node-gcp mpc-node; do SAFE_NAME="${REPO//-/_}" MANIFEST_DIGEST=$(skopeo inspect docker://nearone/$REPO:$RELEASE_TAG | jq -r '.Digest') - IMAGE_ID=$(skopeo inspect --raw docker://nearone/$REPO:$RELEASE_TAG | jq -r '.config.digest') + # Use --override-os/--override-arch to resolve multi-arch manifest lists + # to the platform-specific image manifest, where .config.digest is the Image ID. + IMAGE_ID=$(skopeo inspect --raw --override-os linux --override-arch amd64 docker://nearone/$REPO:$RELEASE_TAG | jq -r '.config.digest') echo "${SAFE_NAME}_manifest_digest=$MANIFEST_DIGEST" >> "$GITHUB_OUTPUT" echo "${SAFE_NAME}_image_id=$IMAGE_ID" >> "$GITHUB_OUTPUT" done From 5e5c3568ba8d1891b07c2182467c6647957cddee Mon Sep 17 00:00:00 2001 From: SimonRastikian <43679791+SimonRastikian@users.noreply.github.com> Date: Fri, 20 Feb 2026 20:56:32 +0100 Subject: [PATCH 15/22] Release notes is not empty --- .github/workflows/release.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ebcc4c20c..a94d77e58 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -253,6 +253,10 @@ jobs: VERSION: ${{ needs.create-tag.outputs.version }} run: | awk "/^## \\[${VERSION}\\]/{found=1; next} /^## \\[/{if(found) exit} found" CHANGELOG.md > release-notes-raw.md + if [ ! -s release-notes-raw.md ]; then + echo "::error::No changelog found for version ${VERSION} in CHANGELOG.md" + exit 1 + fi # Download the contract .tar.gz uploaded by the build-contract job. - name: Download contract artifact From 64c47d6625631a30cb5bd3045f27d76bb29646f2 Mon Sep 17 00:00:00 2001 From: SimonRastikian <43679791+SimonRastikian@users.noreply.github.com> Date: Fri, 20 Feb 2026 21:02:35 +0100 Subject: [PATCH 16/22] Making zizmor pass --- .github/workflows/release.yml | 49 +++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a94d77e58..0dafc05c9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -54,6 +54,7 @@ jobs: echo "short-sha=${SHA::7}" >> "$GITHUB_OUTPUT" # Checkout the main branch so the tag points to the merge commit. + # persist-credentials is needed for git push in the next step. - name: Checkout uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: @@ -93,41 +94,50 @@ jobs: id: launcher env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + REPO: ${{ github.repository }} + SHORT_SHA: ${{ needs.create-tag.outputs.short-sha }} + VERSION: ${{ needs.create-tag.outputs.version }} run: | gh workflow run docker_launcher_release.yml \ - --repo "${{ github.repository }}" \ - -f source-tag="main-${{ needs.create-tag.outputs.short-sha }}" \ - -f release-tag="${{ needs.create-tag.outputs.version }}" + --repo "$REPO" \ + -f source-tag="main-${SHORT_SHA}" \ + -f release-tag="${VERSION}" sleep 5 - RUN_ID=$(gh run list --workflow=docker_launcher_release.yml --repo "${{ github.repository }}" --limit=1 --json databaseId -q '.[0].databaseId') + RUN_ID=$(gh run list --workflow=docker_launcher_release.yml --repo "$REPO" --limit=1 --json databaseId -q '.[0].databaseId') echo "run_id=$RUN_ID" >> "$GITHUB_OUTPUT" - name: Retag mpc-node-gcp id: node-gcp env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + REPO: ${{ github.repository }} + SHORT_SHA: ${{ needs.create-tag.outputs.short-sha }} + VERSION: ${{ needs.create-tag.outputs.version }} run: | gh workflow run docker_node_release.yml \ - --repo "${{ github.repository }}" \ - -f source-tag="main-${{ needs.create-tag.outputs.short-sha }}" \ - -f release-tag="${{ needs.create-tag.outputs.version }}" \ + --repo "$REPO" \ + -f source-tag="main-${SHORT_SHA}" \ + -f release-tag="${VERSION}" \ -f repository="mpc-node-gcp" sleep 5 - RUN_ID=$(gh run list --workflow=docker_node_release.yml --repo "${{ github.repository }}" --limit=1 --json databaseId -q '.[0].databaseId') + RUN_ID=$(gh run list --workflow=docker_node_release.yml --repo "$REPO" --limit=1 --json databaseId -q '.[0].databaseId') echo "run_id=$RUN_ID" >> "$GITHUB_OUTPUT" - name: Retag mpc-node id: node env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + REPO: ${{ github.repository }} + SHORT_SHA: ${{ needs.create-tag.outputs.short-sha }} + VERSION: ${{ needs.create-tag.outputs.version }} run: | gh workflow run docker_node_release.yml \ - --repo "${{ github.repository }}" \ - -f source-tag="main-${{ needs.create-tag.outputs.short-sha }}" \ - -f release-tag="${{ needs.create-tag.outputs.version }}" \ + --repo "$REPO" \ + -f source-tag="main-${SHORT_SHA}" \ + -f release-tag="${VERSION}" \ -f repository="mpc-node" sleep 5 - RUN_ID=$(gh run list --workflow=docker_node_release.yml --repo "${{ github.repository }}" --limit=1 --json databaseId -q '.[0].databaseId') + RUN_ID=$(gh run list --workflow=docker_node_release.yml --repo "$REPO" --limit=1 --json databaseId -q '.[0].databaseId') echo "run_id=$RUN_ID" >> "$GITHUB_OUTPUT" # Wait for all three dispatched runs to complete. @@ -135,9 +145,13 @@ jobs: - name: Wait for retag workflows env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + REPO: ${{ github.repository }} + LAUNCHER_RUN: ${{ steps.launcher.outputs.run_id }} + NODE_GCP_RUN: ${{ steps.node-gcp.outputs.run_id }} + NODE_RUN: ${{ steps.node.outputs.run_id }} run: | - for RUN_ID in ${{ steps.launcher.outputs.run_id }} ${{ steps.node-gcp.outputs.run_id }} ${{ steps.node.outputs.run_id }}; do - gh run watch "$RUN_ID" --repo "${{ github.repository }}" --exit-status + for RUN_ID in $LAUNCHER_RUN $NODE_GCP_RUN $NODE_RUN; do + gh run watch "$RUN_ID" --repo "$REPO" --exit-status done - name: Install skopeo @@ -183,6 +197,7 @@ jobs: uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: ref: main + persist-credentials: false # Restore cached Rust dependencies to speed up the build. # save-if: false because we only want to read from the cache, not update it @@ -238,12 +253,12 @@ jobs: contents: write steps: - # Checkout is needed for git-cliff to generate the changelog. + # Checkout is needed to read CHANGELOG.md. - name: Checkout uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: ref: main - fetch-depth: 0 + persist-credentials: false # Extract the changelog section for this version from CHANGELOG.md. # Sections are delimited by "## []" headers, so we print @@ -309,7 +324,7 @@ jobs: VERSION: ${{ needs.create-tag.outputs.version }} run: | gh release create "$TAG" \ - --repo "${{ github.repository }}" \ + --repo "$GITHUB_REPOSITORY" \ --title "MPC ${VERSION}" \ --notes-file release-notes.md \ --draft \ From 44a66cd1304380bc6241249fa6c602a0b7107135 Mon Sep 17 00:00:00 2001 From: SimonRastikian <43679791+SimonRastikian@users.noreply.github.com> Date: Fri, 20 Feb 2026 21:06:06 +0100 Subject: [PATCH 17/22] Avoid creating the tag via the GitHub API --- .github/workflows/release.yml | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0dafc05c9..a91d79c69 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -53,20 +53,18 @@ jobs: echo "tag=v${VERSION}" >> "$GITHUB_OUTPUT" echo "short-sha=${SHA::7}" >> "$GITHUB_OUTPUT" - # Checkout the main branch so the tag points to the merge commit. - # persist-credentials is needed for git push in the next step. - - name: Checkout - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - with: - ref: main - - # Create a lightweight git tag and push it to origin. - - name: Create and push tag + # Create the tag via the GitHub API so we don't need git credentials. + # Points the tag at the PR's merge commit SHA. + - name: Create tag env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} TAG: ${{ steps.version.outputs.tag }} + SHA: ${{ github.event.pull_request.merge_commit_sha }} run: | - git tag "$TAG" - git push origin "$TAG" + gh api "repos/$GITHUB_REPOSITORY/git/refs" \ + --method POST \ + -f ref="refs/tags/$TAG" \ + -f sha="$SHA" # Trigger the existing Docker retag workflows for each image. # These are the same workflows you'd normally trigger manually from the Actions UI. From 1b35dce3662aeb574ed38d1c2d430682f6b3ee74 Mon Sep 17 00:00:00 2001 From: SimonRastikian <43679791+SimonRastikian@users.noreply.github.com> Date: Fri, 20 Feb 2026 21:07:28 +0100 Subject: [PATCH 18/22] Fix critical issue --- .github/workflows/docker_node_release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker_node_release.yml b/.github/workflows/docker_node_release.yml index eeb60a941..16891b58b 100644 --- a/.github/workflows/docker_node_release.yml +++ b/.github/workflows/docker_node_release.yml @@ -1,7 +1,7 @@ name: Release Node Docker Image concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event.inputs.repository }} cancel-in-progress: true on: From 6632cffc90145acfc8ca6657e1572bedf54dcf19 Mon Sep 17 00:00:00 2001 From: SimonRastikian <43679791+SimonRastikian@users.noreply.github.com> Date: Mon, 2 Mar 2026 09:41:38 +0100 Subject: [PATCH 19/22] Trigger on creation of tag or on merge PR --- .github/workflows/release.yml | 88 +++++++++++++++++++++-------------- 1 file changed, 52 insertions(+), 36 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a91d79c69..c2ac13719 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,10 +6,13 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true -# Trigger this workflow when a pull request targeting main is closed. -# Note: "closed" fires for both merged and unmerged PRs — the job-level -# `if` condition below filters to only merged release PRs. +# Trigger this workflow when: +# 1. A pull request targeting main is closed (filters to merged release PRs via job `if`). +# 2. A version tag (v*) is pushed directly (e.g. `git push origin v3.6.0`). on: + push: + tags: + - 'v*' pull_request: branches: - main @@ -17,14 +20,15 @@ on: - closed jobs: - create-tag: - name: "Create release tag" - # Only run when: - # 1. The PR was actually merged (not just closed/dismissed). - # 2. The source branch follows the release naming convention (release/v*). - if: github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'release/v') + release-info: + name: "Extract release info" + # Run when a version tag is pushed OR a merged release/v* PR is closed. + if: >- + github.event_name == 'push' + || (github.event.pull_request.merged == true + && startsWith(github.event.pull_request.head.ref, 'release/v')) runs-on: warp-ubuntu-2404-x64-2x - # Write permission on contents is required to push a new tag. + # Write permission on contents is required to push a new tag (PR path). permissions: contents: write @@ -35,16 +39,26 @@ jobs: short-sha: ${{ steps.version.outputs.short-sha }} steps: - # Extract the semver version from the branch name. - # e.g. "release/v3.6.0" -> version="3.6.0", tag="v3.6.0" + # Extract the semver version from the tag ref or branch name. + # Tag push: refs/tags/v3.6.0 -> version="3.6.0", tag="v3.6.0" + # PR merge: release/v3.6.0 -> version="3.6.0", tag="v3.6.0" # Also compute the 7-char commit hash used as the Docker source tag. - - name: Extract version from branch name + - name: Extract version id: version env: + EVENT: ${{ github.event_name }} + TAG_REF: ${{ github.ref }} + TAG_SHA: ${{ github.sha }} BRANCH: ${{ github.event.pull_request.head.ref }} - SHA: ${{ github.event.pull_request.merge_commit_sha }} + PR_SHA: ${{ github.event.pull_request.merge_commit_sha }} run: | - VERSION="${BRANCH#release/v}" + if [[ "$EVENT" == "push" ]]; then + VERSION="${TAG_REF#refs/tags/v}" + SHA="$TAG_SHA" + else + VERSION="${BRANCH#release/v}" + SHA="$PR_SHA" + fi if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$ ]]; then echo "::error::Invalid semver: $VERSION" exit 1 @@ -55,7 +69,9 @@ jobs: # Create the tag via the GitHub API so we don't need git credentials. # Points the tag at the PR's merge commit SHA. + # Skipped on tag push since the tag already exists. - name: Create tag + if: github.event_name == 'pull_request' env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} TAG: ${{ steps.version.outputs.tag }} @@ -70,7 +86,7 @@ jobs: # These are the same workflows you'd normally trigger manually from the Actions UI. retag-docker-images: name: "Retag Docker images" - needs: create-tag + needs: release-info runs-on: warp-ubuntu-2404-x64-2x permissions: actions: write @@ -93,8 +109,8 @@ jobs: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} REPO: ${{ github.repository }} - SHORT_SHA: ${{ needs.create-tag.outputs.short-sha }} - VERSION: ${{ needs.create-tag.outputs.version }} + SHORT_SHA: ${{ needs.release-info.outputs.short-sha }} + VERSION: ${{ needs.release-info.outputs.version }} run: | gh workflow run docker_launcher_release.yml \ --repo "$REPO" \ @@ -109,8 +125,8 @@ jobs: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} REPO: ${{ github.repository }} - SHORT_SHA: ${{ needs.create-tag.outputs.short-sha }} - VERSION: ${{ needs.create-tag.outputs.version }} + SHORT_SHA: ${{ needs.release-info.outputs.short-sha }} + VERSION: ${{ needs.release-info.outputs.version }} run: | gh workflow run docker_node_release.yml \ --repo "$REPO" \ @@ -126,8 +142,8 @@ jobs: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} REPO: ${{ github.repository }} - SHORT_SHA: ${{ needs.create-tag.outputs.short-sha }} - VERSION: ${{ needs.create-tag.outputs.version }} + SHORT_SHA: ${{ needs.release-info.outputs.short-sha }} + VERSION: ${{ needs.release-info.outputs.version }} run: | gh workflow run docker_node_release.yml \ --repo "$REPO" \ @@ -161,7 +177,7 @@ jobs: - name: Get image digests id: digests env: - RELEASE_TAG: ${{ needs.create-tag.outputs.version }} + RELEASE_TAG: ${{ needs.release-info.outputs.version }} run: | for REPO in mpc-launcher mpc-node-gcp mpc-node; do SAFE_NAME="${REPO//-/_}" @@ -176,10 +192,10 @@ jobs: # Build the smart contract using reproducible builds, rename the artifacts # with the release version, and package them into a .tar.gz archive. # This job runs in parallel with retag-docker-images since both only - # depend on create-tag. + # depend on release-info. build-contract: name: "Build contract" - needs: create-tag + needs: release-info # Uses a 16x runner because the reproducible contract build is resource-intensive. runs-on: warp-ubuntu-2404-x64-16x permissions: @@ -190,11 +206,11 @@ jobs: contract-hash: ${{ steps.contract-hash.outputs.sha256 }} steps: - # Checkout main so we build the code that includes the version bump. + # Checkout the release tag so we build the correct code in both trigger paths. - name: Checkout uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: - ref: main + ref: ${{ needs.release-info.outputs.tag }} persist-credentials: false # Restore cached Rust dependencies to speed up the build. @@ -225,7 +241,7 @@ jobs: # e.g. mpc-contract-v3.6.0.wasm, mpc-contract-v3.6.0-abi.json - name: Package contract artifacts env: - VERSION: ${{ needs.create-tag.outputs.version }} + VERSION: ${{ needs.release-info.outputs.version }} run: | cd target/near/mpc_contract/ mv mpc_contract.wasm "mpc-contract-v${VERSION}.wasm" @@ -238,24 +254,24 @@ jobs: uses: actions/upload-artifact@ea165f8d65b6db9a6b7e75b195db6a7b2bcf4bac # v4.6.2 with: name: mpc-contract - path: target/near/mpc_contract/mpc-contract-v${{ needs.create-tag.outputs.version }}.tar.gz + path: target/near/mpc_contract/mpc-contract-v${{ needs.release-info.outputs.version }}.tar.gz # Create a draft GitHub release with the changelog, Docker image info, # and the contract artifact attached. # Runs after both retag-docker-images and build-contract complete. create-release: name: "Create draft GitHub release" - needs: [create-tag, retag-docker-images, build-contract] + needs: [release-info, retag-docker-images, build-contract] runs-on: warp-ubuntu-2404-x64-2x permissions: contents: write steps: - # Checkout is needed to read CHANGELOG.md. + # Checkout the release tag to read the correct CHANGELOG.md. - name: Checkout uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: - ref: main + ref: ${{ needs.release-info.outputs.tag }} persist-credentials: false # Extract the changelog section for this version from CHANGELOG.md. @@ -263,7 +279,7 @@ jobs: # everything between the current version's header and the next one. - name: Extract changelog env: - VERSION: ${{ needs.create-tag.outputs.version }} + VERSION: ${{ needs.release-info.outputs.version }} run: | awk "/^## \\[${VERSION}\\]/{found=1; next} /^## \\[/{if(found) exit} found" CHANGELOG.md > release-notes-raw.md if [ ! -s release-notes-raw.md ]; then @@ -280,7 +296,7 @@ jobs: # Compose the full release body: changelog + Docker images + contract hash. - name: Compose release body env: - VERSION: ${{ needs.create-tag.outputs.version }} + VERSION: ${{ needs.release-info.outputs.version }} NODE_MANIFEST: ${{ needs.retag-docker-images.outputs.mpc_node_manifest_digest }} NODE_IMAGE_ID: ${{ needs.retag-docker-images.outputs.mpc_node_image_id }} NODE_GCP_MANIFEST: ${{ needs.retag-docker-images.outputs.mpc_node_gcp_manifest_digest }} @@ -318,8 +334,8 @@ jobs: - name: Create draft release env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - TAG: ${{ needs.create-tag.outputs.tag }} - VERSION: ${{ needs.create-tag.outputs.version }} + TAG: ${{ needs.release-info.outputs.tag }} + VERSION: ${{ needs.release-info.outputs.version }} run: | gh release create "$TAG" \ --repo "$GITHUB_REPOSITORY" \ From e07d28af28ef84e97a83164943ad19784101e1ab Mon Sep 17 00:00:00 2001 From: SimonRastikian <43679791+SimonRastikian@users.noreply.github.com> Date: Mon, 2 Mar 2026 10:15:36 +0100 Subject: [PATCH 20/22] lookup only --- .github/workflows/release.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c2ac13719..f5257b4cd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -213,14 +213,16 @@ jobs: ref: ${{ needs.release-info.outputs.tag }} persist-credentials: false - # Restore cached Rust dependencies to speed up the build. - # save-if: false because we only want to read from the cache, not update it - # (the main CI workflow handles saving). + # Rust cache: lookup-only + save-if:false keeps this step inert so that + # no poisoned cache content can influence release artifacts (zizmor cache-poisoning). + # The actual build happens inside a Docker container (reproducible-wasm) + # so host caching provides limited benefit here anyway. - name: Cache Rust dependencies uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2.8.1 with: save-if: false cache-provider: "warpbuild" + lookup-only: true # Build the contract with reproducible-wasm to ensure deterministic output. # This produces mpc_contract.wasm and mpc_contract_abi.json From d7ebef282c58f748165735e8ffa5b8f7f859c9e8 Mon Sep 17 00:00:00 2001 From: Simon Rastikian <43679791+SimonRastikian@users.noreply.github.com> Date: Thu, 5 Mar 2026 17:04:26 +0100 Subject: [PATCH 21/22] Update .github/workflows/release.yml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Mårten Blankfors --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f5257b4cd..bafcb8963 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ concurrency: on: push: tags: - - 'v*' + - '*.*.*' pull_request: branches: - main From 8475664acc67099c02dd0c7c44ef76d0de4dd05a Mon Sep 17 00:00:00 2001 From: SimonRastikian <43679791+SimonRastikian@users.noreply.github.com> Date: Mon, 9 Mar 2026 11:06:21 +0100 Subject: [PATCH 22/22] Install cargo near --- .github/workflows/release.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bafcb8963..4c8619a4d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -224,6 +224,25 @@ jobs: cache-provider: "warpbuild" lookup-only: true + - name: Install cargo-binstall + uses: taiki-e/install-action@d4422f254e595ee762a758628fe4f16ce050fa2e # v2.67.28 + with: + tool: cargo-binstall + + - name: Install cargo-near + run: | + sudo apt-get update && sudo apt-get install --assume-yes libudev-dev + cargo binstall --force --no-confirm --locked cargo-near@0.19.1 --pkg-url="{ repo }/releases/download/{ name }-v{ version }/{ name }-{ target }.{ archive-format }" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Install wasm-opt + run: | + cargo binstall --force --no-confirm --locked wasm-opt@0.116.1 + echo "${HOME}/.cargo/bin" >> $GITHUB_PATH + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # Build the contract with reproducible-wasm to ensure deterministic output. # This produces mpc_contract.wasm and mpc_contract_abi.json # under target/near/mpc_contract/.