From 880b94311f4588f1825f32cd7a93a68d8f5f30f7 Mon Sep 17 00:00:00 2001 From: Tom Mulcahy Date: Tue, 24 Feb 2026 16:51:25 -0800 Subject: [PATCH] Release stoic-plugin via workflow --- .github/workflows/publish-release.yml | 83 ++++++++++++++++++++++++++- RELEASING.md | 4 +- 2 files changed, 81 insertions(+), 6 deletions(-) diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index 862bf54..03283bc 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -3,10 +3,16 @@ name: Publish Release on: workflow_dispatch: +permissions: + # Required so GH_TOKEN can create the GitHub Release and upload the artifact. + contents: write + jobs: - publish-release: + # This job is the irreversible boundary. Once Maven Central publish succeeds, + # we do not want retries for downstream GitHub operations to re-run it. + build-and-publish-to-maven: runs-on: macos-latest - if: github.repository == 'block/radiography' + if: github.repository == 'block/radiography' && startsWith(github.ref, 'refs/tags/v') timeout-minutes: 35 steps: @@ -23,10 +29,81 @@ jobs: - name: Assemble run: ./gradlew assemble - - name: Publish Release + # Build and hand off the release asset in the same build context as Maven + # publish, so the release uses artifacts from the same pipeline run. + - name: Build Stoic Plugin Distribution + run: ./gradlew :stoic-plugin:dist + + - name: Upload Stoic Plugin Distribution + uses: actions/upload-artifact@v4 + with: + # Include tag + commit to avoid any ambiguity about which artifact this is. + name: stoic-plugin-dist-${{ github.ref_name }}-${{ github.sha }} + path: stoic-plugin/build/distributions/radiography-stoic-plugin-*.tar.gz + if-no-files-found: error + # Keep the upload for 7 days so we have time to retry publishing the + # Github release + retention-days: 7 + + # Maven publish must be the final step in this job because it's + # irreversible: if we attempt to republish it will fail. + - name: Publish To Maven run: ./gradlew publish env: ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.SONATYPE_CENTRAL_USERNAME }} ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.SONATYPE_CENTRAL_PASSWORD }} ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.GPG_SECRET_KEY }} ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.GPG_SECRET_PASSPHRASE }} + + # Keep release publication in a separate job so "Re-run failed jobs" can retry + # GitHub release operations without re-running Maven publish. + publish-to-github-release: + runs-on: ubuntu-latest + needs: build-and-publish-to-maven + timeout-minutes: 10 + + steps: + - name: Download Stoic Plugin Distribution + uses: actions/download-artifact@v4 + with: + # Download the exact artifact produced by build-and-publish-to-maven. + name: stoic-plugin-dist-${{ github.ref_name }}-${{ github.sha }} + path: dist + + - name: Create Draft GitHub Release, Upload Asset, and Publish + env: + GH_TOKEN: ${{ github.token }} + run: | + set -euo pipefail + + artifact_path="$(ls dist/radiography-stoic-plugin-*.tar.gz)" + release_notes='See [Change Log](https://github.com/square/radiography/blob/main/CHANGELOG.md)' + + if gh release view "$GITHUB_REF_NAME" >/dev/null 2>&1; then + # We only auto-recover if the existing release is still a draft. + # A published immutable release may reject asset modifications. + is_draft="$(gh release view "$GITHUB_REF_NAME" --json isDraft --jq .isDraft)" + if [ "$is_draft" != "true" ]; then + echo "Release $GITHUB_REF_NAME is already published and cannot be safely finalized as draft-first." + echo "If immutable releases are enabled, published release assets cannot be modified:" + echo "https://docs.github.com/en/code-security/concepts/supply-chain-security/immutable-releases" + exit 1 + fi + else + gh release create "$GITHUB_REF_NAME" \ + --draft \ + --title "$GITHUB_REF_NAME" \ + --notes "$release_notes" + fi + + # Draft-first follows GitHub immutable release guidance: + # https://docs.github.com/en/code-security/concepts/supply-chain-security/immutable-releases + # --clobber makes retries idempotent if an earlier attempt uploaded assets. + gh release upload "$GITHUB_REF_NAME" "$artifact_path" --clobber + + # Publish only after assets are uploaded to avoid partially published + # immutable releases missing artifacts. + gh release edit "$GITHUB_REF_NAME" \ + --draft=false \ + --title "$GITHUB_REF_NAME" \ + --notes "$release_notes" diff --git a/RELEASING.md b/RELEASING.md index 2f00e10..baa4414 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -27,7 +27,6 @@ git commit -am "Prepare {NEW_VERSION} release" && \ ./gradlew clean && \ ./gradlew build && \ ./gradlew connectedCheck && \ -./gradlew :stoic-plugin:dist && \ git tag v{NEW_VERSION} && \ git push origin v{NEW_VERSION} && \ gh workflow run publish-release.yml --ref v{NEW_VERSION} && \ @@ -37,8 +36,7 @@ git pull && \ git merge --no-ff --no-edit release_{NEW_VERSION} && \ sed -i '' 's/VERSION_NAME={NEW_VERSION}/VERSION_NAME={NEXT_VERSION}-SNAPSHOT/' gradle.properties && \ git commit -am "Prepare for next development iteration" && \ -git push && \ -gh release create v{NEW_VERSION} --title v{NEW_VERSION} --notes 'See [Change Log](https://github.com/square/radiography/blob/main/CHANGELOG.md)' stoic-plugin/build/distributions/radiography-stoic-plugin-{NEW_VERSION}.tar.gz +git push ``` * Wait for the release to be available [on Maven Central](https://repo1.maven.org/maven2/com/squareup/radiography/radiography/).