diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fa1ed41e8..d91eeb983 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,12 +1,10 @@ # Continuous release pipeline for Data Machine. # -# Triggers on push to main (immediate release) and manual dispatch. -# Checks for releasable conventional commits since the last tag. If found: -# 1. Version bump + changelog generation -# 2. Tag + push + GitHub Release creation -# 3. WordPress release.package builds the vendor-bundled ZIP -# 4. WordPress release.publish uploads the ZIP to the Release and -# mirrors the tree to the release-latest branch (Playground CORS path) +# Triggers on push to main (immediate release) and manual dispatch. The whole +# pipeline — releasable-commit detection, dry-run version prediction, +# failed-SHA retry protection, GitHub App token, version bump, changelog, +# tag, GitHub Release, and the WordPress release.package / release.publish +# steps — is owned by the reusable Homeboy Action release workflow. # # No human input needed — version is computed from commit types: # fix: → patch, feat: → minor, BREAKING CHANGE → major @@ -29,157 +27,14 @@ on: type: boolean default: false -jobs: - # ── Step 1: Check for releasable commits ── - check: - name: Check for releasable commits - if: ${{ github.event_name != 'push' || !startsWith(github.event.head_commit.message, 'release:') }} - runs-on: ubuntu-latest - outputs: - should-release: ${{ steps.check.outputs.should-release }} - steps: - - uses: actions/checkout@v6 - with: - fetch-depth: 0 - - - name: Restore failure cache - id: failure-cache - uses: actions/cache/restore@v5 - with: - path: ${{ runner.temp }}/homeboy-release-last-failed - key: release-last-failed-${{ github.ref_name }}-${{ github.sha }} - restore-keys: | - release-last-failed-${{ github.ref_name }}- - - - name: Check failed release marker - id: failed-release - run: | - HEAD_SHA="$(git rev-parse HEAD)" - FAILURE_MARKER="${RUNNER_TEMP}/homeboy-release-last-failed" - if [ -f "${FAILURE_MARKER}" ]; then - LAST_FAILED="$(tr -d '[:space:]' < "${FAILURE_MARKER}")" - if [ "${HEAD_SHA}" = "${LAST_FAILED}" ]; then - echo "::notice::HEAD ${HEAD_SHA:0:8} matches last failed release attempt — skipping until new commits" - echo "blocked=true" >> "$GITHUB_OUTPUT" - exit 0 - fi - fi - - echo "blocked=false" >> "$GITHUB_OUTPUT" - - - name: Check for releasable commit messages - id: commit-check - if: steps.failed-release.outputs.blocked != 'true' - run: | - LAST_TAG="$(git describe --tags --match 'v[0-9]*' --abbrev=0 2>/dev/null || true)" - if [ -n "${LAST_TAG}" ]; then - RANGE="${LAST_TAG}..HEAD" - else - RANGE="HEAD" - fi - - if git log --format=%B "${RANGE}" | grep -Eq '^(feat|fix)(\([^)]+\))?!?:|^BREAKING CHANGE:'; then - echo "could-release=true" >> "$GITHUB_OUTPUT" - else - echo "::notice::No releasable conventional commits in ${RANGE}" - echo "could-release=false" >> "$GITHUB_OUTPUT" - fi - - - name: Dry-run release check - id: release-check - if: steps.commit-check.outputs.could-release == 'true' - uses: Extra-Chill/homeboy-action@v2 - with: - commands: release - args: '--setting database_type=mysql --setting wp_codebox_phpunit_config=/wordpress/wp-content/plugins/data-machine/phpunit.xml.dist' - release-dry-run: 'true' - - - name: Decide whether to release - id: check - run: | - HEAD_SHA="$(git rev-parse HEAD)" - if [ "${{ steps.failed-release.outputs.blocked }}" = "true" ]; then - echo "should-release=false" >> "$GITHUB_OUTPUT" - exit 0 - fi - - if [ "${{ steps.commit-check.outputs.could-release }}" != "true" ]; then - echo "should-release=false" >> "$GITHUB_OUTPUT" - echo "::notice::No releasable commits at HEAD ${HEAD_SHA:0:8}" - exit 0 - fi +concurrency: + group: release + cancel-in-progress: false - RELEASE_VERSION="${{ steps.release-check.outputs.release-version }}" - BUMP_TYPE="${{ steps.release-check.outputs.release-bump-type }}" - - if [ -z "${RELEASE_VERSION}" ]; then - echo "should-release=false" >> "$GITHUB_OUTPUT" - echo "::notice::No releasable commits at HEAD ${HEAD_SHA:0:8}" - else - echo "should-release=true" >> "$GITHUB_OUTPUT" - echo "::notice::Release dry-run predicts v${RELEASE_VERSION} (${BUMP_TYPE})" - fi - - # ── Step 2: Release ── +jobs: release: - name: Release - needs: check - if: needs.check.outputs.should-release == 'true' - runs-on: ubuntu-latest - steps: - - name: Generate GitHub App token - id: app-token - uses: actions/create-github-app-token@v3 - continue-on-error: true - with: - app-id: ${{ secrets.HOMEBOY_APP_ID }} - private-key: ${{ secrets.HOMEBOY_APP_PRIVATE_KEY }} - - - uses: actions/checkout@v6 - with: - fetch-depth: 0 - persist-credentials: false - token: ${{ steps.app-token.outputs.token || secrets.GITHUB_TOKEN }} - - - uses: Extra-Chill/homeboy-action@v2 - id: release - with: - commands: release - args: '--setting database_type=mysql --setting wp_codebox_phpunit_config=/wordpress/wp-content/plugins/data-machine/phpunit.xml.dist' - release-dry-run: ${{ inputs.dry-run || 'false' }} - app-token: ${{ steps.app-token.outputs.token || '' }} - - # ── Record failed SHA to prevent retry loops ── - record-failure: - name: Record failure - needs: - - check - - release - if: ${{ always() && needs.check.outputs.should-release == 'true' && needs.release.result == 'failure' }} - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - - - name: Save failed SHA - run: git rev-parse HEAD > "${RUNNER_TEMP}/homeboy-release-last-failed" - - - name: Cache failed SHA - uses: actions/cache/save@v5 - with: - path: ${{ runner.temp }}/homeboy-release-last-failed - key: release-last-failed-${{ github.ref_name }}-${{ github.sha }} - - # ── Clear failure cache on success ── - clear-failure: - name: Clear failure cache - needs: release - if: ${{ needs.release.result == 'success' }} - runs-on: ubuntu-latest - steps: - - name: Clear failure cache - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - gh cache list --json id,key --jq '.[] | select(.key | startswith("release-last-failed-${{ github.ref_name }}-")) | .id' | while read -r id; do - gh cache delete "$id" 2>/dev/null || true - done + uses: Extra-Chill/homeboy-action/.github/workflows/release.yml@v2 + with: + dry-run: ${{ inputs.dry-run || false }} + args: '--setting database_type=mysql --setting wp_codebox_phpunit_config=/wordpress/wp-content/plugins/data-machine/phpunit.xml.dist' + secrets: inherit