From 534253840e5fc8279493016127e9b0d1e2398d86 Mon Sep 17 00:00:00 2001 From: Umesh Date: Sat, 19 Sep 2026 04:09:55 +0530 Subject: [PATCH] ci(release): split release workflow into gate-ci-and-verify and publish with CI check-run gate --- .github/workflows/release.yml | 64 +++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6a67ef7..69a93ad 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -17,10 +17,9 @@ env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true jobs: - release: + gate-ci-and-verify: runs-on: ubuntu-latest - permissions: - contents: write + permissions: read-all steps: - name: Resolve release tag id: release @@ -40,6 +39,21 @@ jobs: fetch-depth: 0 ref: ${{ steps.release.outputs.tag }} + - name: Verify CI Check-Runs on Commit + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + echo "Verifying that commit ${{ github.sha }} has no failed CI check-runs..." + # Query GitHub API check-runs for this commit + FAILED_CHECKS=$(gh api "repos/${{ github.repository }}/commits/${{ github.sha }}/check-runs" \ + --jq '.check_runs[] | select(.conclusion == "failure" and (.name | test("release|Release|gate-ci") | not)) | .name' || true) + if [ -n "$FAILED_CHECKS" ]; then + echo "❌ Cannot release: One or more CI check-runs failed on commit ${{ github.sha }}:" >&2 + echo "$FAILED_CHECKS" >&2 + exit 1 + fi + echo "✅ No failed CI check-runs found on commit ${{ github.sha }}." + - name: Set up Go uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: @@ -65,9 +79,38 @@ jobs: with: name: release-manifest-${{ steps.release.outputs.tag || github.run_id }} path: release-manifest.json - if-no-files-found: warn retention-days: 90 + publish: + needs: [gate-ci-and-verify] + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Resolve release tag + id: release + env: + INPUT_TAG: ${{ inputs.tag }} + run: | + TAG="${INPUT_TAG:-${GITHUB_REF_NAME}}" + if ! [[ "$TAG" =~ ^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$ ]]; then + echo "Release tag must use vMAJOR.MINOR.PATCH[-PRERELEASE]: $TAG" >&2 + exit 1 + fi + echo "tag=$TAG" >> "$GITHUB_OUTPUT" + + - name: Checkout repository + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + fetch-depth: 0 + ref: ${{ steps.release.outputs.tag }} + + - name: Download release verification manifest + uses: actions/download-artifact@cc203385981b70ca67e1cc392babf9cc229d5806 # v4.1.9 + with: + name: release-manifest-${{ steps.release.outputs.tag || github.run_id }} + path: . + - name: Create release or replace only its manifest asset env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -79,5 +122,14 @@ jobs: gh release upload "$TAG" release-manifest.json --clobber exit 0 fi - gh release create "$TAG" release-manifest.json --verify-tag --title "$TAG" \ - --notes-file <(awk -v ver="${TAG#v}" 'index($0, "## [" ver "]") == 1 { found=1; print; next } found && /^## \[/ { exit } found { print }' CHANGELOG.md) + NOTES=$(mktemp) + awk -v ver="${TAG#v}" ' + index($0, "## [" ver "]") == 1 { found=1; print; next } + found && /^## \[/ { exit } + found { print } + ' CHANGELOG.md > "$NOTES" + test -s "$NOTES" || { + echo "No CHANGELOG section found for $TAG" >&2 + exit 1 + } + gh release create "$TAG" release-manifest.json --verify-tag --title "$TAG" --notes-file "$NOTES"