From 8ba68048a30918c8d49dab56a201662bba1318b2 Mon Sep 17 00:00:00 2001 From: Dustin Byrne Date: Thu, 23 Apr 2026 18:04:05 -0400 Subject: [PATCH] chore(ci): trigger release workflow from pushes to main --- .github/workflows/release.yml | 81 +++++++++++++++++++++++++++++++---- 1 file changed, 72 insertions(+), 9 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 805998b..a217a6d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,9 +1,10 @@ name: "Release" on: - pull_request: - types: [closed] + push: branches: [main] + paths: + - '.changeset/**' workflow_dispatch: permissions: @@ -16,14 +17,76 @@ concurrency: cancel-in-progress: false jobs: + resolve-release-context: + name: Resolve release context + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read + outputs: + should-release: ${{ steps.resolve.outputs.should-release }} + bump-type: ${{ steps.resolve.outputs.bump-type }} + steps: + - name: Resolve release request + id: resolve + env: + GH_TOKEN: ${{ github.token }} + EVENT_NAME: ${{ github.event_name }} + CURRENT_REF: ${{ github.ref }} + DEFAULT_BRANCH: main + PUSH_SHA: ${{ github.sha }} + PUSH_HEAD_COMMIT_MESSAGE: ${{ github.event.head_commit.message }} + run: | + set -euo pipefail + + SHOULD_RELEASE=false + BUMP_TYPE="" + + if [ "$EVENT_NAME" = "workflow_dispatch" ]; then + if [ "$CURRENT_REF" != "refs/heads/$DEFAULT_BRANCH" ]; then + echo "::notice::Skipping release because workflow_dispatch must be run on $DEFAULT_BRANCH, got $CURRENT_REF." + else + SHOULD_RELEASE=true + echo "✓ Manual release requested on $DEFAULT_BRANCH" + fi + + echo "should-release=$SHOULD_RELEASE" >> "$GITHUB_OUTPUT" + echo "bump-type=$BUMP_TYPE" >> "$GITHUB_OUTPUT" + exit 0 + fi + + if [[ "${PUSH_HEAD_COMMIT_MESSAGE:-}" == *"[version bump]"* || "${PUSH_HEAD_COMMIT_MESSAGE:-}" == "Bump version to "* || "${PUSH_HEAD_COMMIT_MESSAGE:-}" == "chore: Release v"* || "${PUSH_HEAD_COMMIT_MESSAGE:-}" == "chore: release "* ]]; then + echo "::notice::Skipping release for the automated version bump commit." + echo "should-release=false" >> "$GITHUB_OUTPUT" + echo "bump-type=" >> "$GITHUB_OUTPUT" + exit 0 + fi + + PRS_JSON=$(gh api "repos/${{ github.repository }}/commits/$PUSH_SHA/pulls") + MATCHING_PR_COUNT=$(echo "$PRS_JSON" | jq --arg branch "$DEFAULT_BRANCH" '[.[] | select(.merged_at != null and .base.ref == $branch and (.labels | map(.name) | index("release")))] | length') + + if [ "$MATCHING_PR_COUNT" -eq 0 ]; then + ASSOCIATED_PRS=$(echo "$PRS_JSON" | jq -r '[.[].number | tostring] | join(", ")') + if [ -n "$ASSOCIATED_PRS" ]; then + echo "::notice::Skipping release because push $PUSH_SHA is associated with PR(s) [$ASSOCIATED_PRS], but none currently have the release label." + else + echo "::notice::Skipping release because push $PUSH_SHA is not associated with a merged PR to $DEFAULT_BRANCH that has the release label." + fi + echo "should-release=false" >> "$GITHUB_OUTPUT" + echo "bump-type=" >> "$GITHUB_OUTPUT" + exit 0 + fi + + RELEASE_PRS=$(echo "$PRS_JSON" | jq -r --arg branch "$DEFAULT_BRANCH" '[.[] | select(.merged_at != null and .base.ref == $branch and (.labels | map(.name) | index("release"))) | "#\(.number)"] | join(", ")') + echo "✓ Release requested by push $PUSH_SHA via $RELEASE_PRS" + echo "should-release=true" >> "$GITHUB_OUTPUT" + echo "bump-type=" >> "$GITHUB_OUTPUT" + check-changesets: name: Check for changesets + needs: resolve-release-context runs-on: ubuntu-latest - if: | - github.event_name == 'workflow_dispatch' || - (github.event_name == 'pull_request' && - github.event.pull_request.merged == true && - contains(github.event.pull_request.labels.*.name, 'release')) + if: needs.resolve-release-context.outputs.should-release == 'true' outputs: has-changesets: ${{ steps.check.outputs.has-changesets }} steps: @@ -59,9 +122,9 @@ jobs: version-bump: name: Bump version and commit to main - needs: [check-changesets, notify-approval-needed] + needs: [resolve-release-context, check-changesets, notify-approval-needed] runs-on: ubuntu-latest - if: always() && needs.check-changesets.outputs.has-changesets == 'true' + if: always() && needs.resolve-release-context.outputs.should-release == 'true' && needs.check-changesets.outputs.has-changesets == 'true' environment: "Release" permissions: contents: write