Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 80 additions & 3 deletions .github/workflows/publish-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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
Comment on lines +34 to +35

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need any new secrets access for this? And if the maven publish step fails after this, do we end up in a weird state?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why it would require any secrets. If ./gradlew assemble above works, then this should too. But I don't know a good way to test other than landing this and trying it out.

If Maven publish fails, then that's fine - everything is local up to that point. The somewhat weird state is if Maven publish succeeds, but then Github release fails.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait, so does that mean anyone can just check out this repo, make changes, and publish the stoic plugin?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I see what you're saying. You're asking if gh release requires secrets. Yes, it does - that's the GH_TOKEN, and that's why I had to add the

permissions:
  # Required so GH_TOKEN can create the GitHub Release and upload the artifact.
  contents: write

./gradlew :stoic-plugin:dist does not publish anything - it just builds stoic-plugin locally.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, so that's just a verification step?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

./gradlew :stoic-plugin:dist builds stoic-plugin/build/distributions/radiography-stoic-plugin-*.tar.gz, which then gets used by gh release


- 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"
4 changes: 1 addition & 3 deletions RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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} && \
Expand All @@ -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/).
Expand Down