Merge pull request #81 from openjavaformat/plugin-descriptor-public-api #5
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| # Tags only, and the tag is the version: the build reads it from GITHUB_REF_NAME, and jreleaserDeploy and | |
| # publishPlugins refuse anything that is not a clean X.Y.Z or X.Y.Z.N. | |
| # | |
| # Two deployments per tag, because a published groupId:artifactId:version can never gain files | |
| # afterwards: the jars go up as one, and every platform's native binary as another. Each is uploaded and | |
| # validated first, and the publish job publishes both only once both are in. A version whose native build | |
| # fails publishes nothing, and its deployments can be dropped in the Portal. | |
| # | |
| # Once Maven Central serves both, the Gradle plugins go to the Gradle Plugin Portal, signed with the same | |
| # release key, and the IntelliJ plugin goes to the JetBrains Marketplace, verified against the IDEs it | |
| # supports first. After publishing, a draft GitHub release on the tag collects the runnable jar, the Gradle | |
| # and IDE plugins and the native binaries. | |
| # | |
| # Needs seven repository secrets: JRELEASER_MAVENCENTRAL_USERNAME and JRELEASER_MAVENCENTRAL_PASSWORD (the | |
| # Central Portal user token), JRELEASER_GPG_SECRET_KEY and JRELEASER_GPG_PASSPHRASE, GRADLE_PUBLISH_KEY and | |
| # GRADLE_PUBLISH_SECRET (the Gradle Plugin Portal key) and JETBRAINS_MARKETPLACE_TOKEN (a permanent token of | |
| # the Marketplace account that owns the plugin). The draft release uses the workflow's own GITHUB_TOKEN. | |
| on: | |
| push: | |
| tags: | |
| - '*' | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: release-${{ github.ref }} | |
| cancel-in-progress: false | |
| jobs: | |
| jars: | |
| name: jars | |
| runs-on: ubuntu-latest | |
| outputs: | |
| deployment-id: ${{ steps.deployment.outputs.id }} | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 | |
| - name: Install JDK 21 | |
| uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 | |
| with: | |
| distribution: temurin | |
| java-version: '21' | |
| - name: Stage, sign and upload the jars | |
| run: ./gradlew jreleaserDeploy | |
| env: | |
| JRELEASER_DEPLOY_MAVEN_MAVENCENTRAL_SONATYPE_USERNAME: ${{ secrets.JRELEASER_MAVENCENTRAL_USERNAME }} | |
| JRELEASER_DEPLOY_MAVEN_MAVENCENTRAL_SONATYPE_PASSWORD: ${{ secrets.JRELEASER_MAVENCENTRAL_PASSWORD }} | |
| JRELEASER_GPG_SECRET_KEY: ${{ secrets.JRELEASER_GPG_SECRET_KEY }} | |
| JRELEASER_GPG_PASSPHRASE: ${{ secrets.JRELEASER_GPG_PASSPHRASE }} | |
| - name: Hand the deployment to the publish job | |
| id: deployment | |
| run: | | |
| id="$(sed -n 's/^deployMavenCentralSonatypeDeploymentId=//p' build/jreleaser/output.properties)" | |
| if [ -z "$id" ]; then | |
| echo "No deployment ID in build/jreleaser/output.properties" | |
| exit 1 | |
| fi | |
| echo "id=$id" >> "$GITHUB_OUTPUT" | |
| - name: Keep JReleaser's log | |
| if: ${{ failure() }} | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: jreleaser-log-jars | |
| path: build/jreleaser/trace.log | |
| if-no-files-found: ignore | |
| retention-days: 7 | |
| # One job per platform, as in ci.yml, but here each one hands its binary to the deploy job below | |
| # instead of throwing it away. | |
| native-images: | |
| name: native image (${{ matrix.platform }}) | |
| runs-on: ${{ matrix.runner }} | |
| timeout-minutes: 90 | |
| # bash on Windows too, as in ci.yml. | |
| defaults: | |
| run: | |
| shell: bash | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - platform: linux-x86-64 | |
| runner: ubuntu-latest | |
| - platform: linux-aarch64 | |
| runner: ubuntu-24.04-arm | |
| - platform: macos-aarch64 | |
| runner: macos-15 | |
| - platform: macos-x86-64 | |
| runner: macos-15-intel | |
| - platform: windows-x86-64 | |
| runner: windows-latest | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| # The Java 21 toolchain for the jars, through JDK21_HOME, as in ci.yml: Gradle does not find the | |
| # runner's own JDK 21 on Windows. Installed before GraalVM, so that Gradle still runs on GraalVM. | |
| - name: Install JDK 21 for the jars | |
| id: jdk21 | |
| uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 | |
| with: | |
| distribution: temurin | |
| java-version: '21' | |
| - name: Install GraalVM 25 for the image | |
| uses: graalvm/setup-graalvm@0426e2e191540e8514dff98dc52a5f5146a2a276 # v1.6.6 | |
| with: | |
| java-version: '25' | |
| distribution: 'graalvm-community' | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Compile the native image | |
| run: ./gradlew -PnativeImage=true :open-java-format-native:nativeCompile | |
| env: | |
| JDK21_HOME: ${{ steps.jdk21.outputs.path }} | |
| - name: Hand the binary to the deploy job | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: native-image-${{ matrix.platform }} | |
| path: | | |
| open-java-format-native/build/native/nativeCompile/open-java-format-* | |
| !open-java-format-native/build/native/nativeCompile/*.txt | |
| if-no-files-found: error | |
| retention-days: 1 | |
| # Not `native`: ci.yml already has a job with that id, and `act --job native` could not tell them apart. | |
| native-deploy: | |
| name: native deploy | |
| needs: native-images | |
| runs-on: ubuntu-latest | |
| outputs: | |
| deployment-id: ${{ steps.deployment.outputs.id }} | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 | |
| - name: Install JDK 21 | |
| uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 | |
| with: | |
| distribution: temurin | |
| java-version: '21' | |
| # merge-multiple: every platform's binary lands in one directory under the name it was built | |
| # with, which is where its Maven classifier is read from. | |
| - name: Collect every platform's binary | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| path: native-images | |
| pattern: native-image-* | |
| merge-multiple: true | |
| - name: Show what was collected | |
| run: ls -l native-images | |
| # No GraalVM here: nothing is compiled, the binaries are uploaded exactly as they arrived. | |
| - name: Stage, sign and upload the native images | |
| run: ./gradlew -PreleaseTarget=native -PnativeImages=native-images jreleaserDeploy | |
| env: | |
| JRELEASER_DEPLOY_MAVEN_MAVENCENTRAL_SONATYPE_USERNAME: ${{ secrets.JRELEASER_MAVENCENTRAL_USERNAME }} | |
| JRELEASER_DEPLOY_MAVEN_MAVENCENTRAL_SONATYPE_PASSWORD: ${{ secrets.JRELEASER_MAVENCENTRAL_PASSWORD }} | |
| JRELEASER_GPG_SECRET_KEY: ${{ secrets.JRELEASER_GPG_SECRET_KEY }} | |
| JRELEASER_GPG_PASSPHRASE: ${{ secrets.JRELEASER_GPG_PASSPHRASE }} | |
| - name: Hand the deployment to the publish job | |
| id: deployment | |
| run: | | |
| id="$(sed -n 's/^deployMavenCentralSonatypeDeploymentId=//p' build/jreleaser/output.properties)" | |
| if [ -z "$id" ]; then | |
| echo "No deployment ID in build/jreleaser/output.properties" | |
| exit 1 | |
| fi | |
| echo "id=$id" >> "$GITHUB_OUTPUT" | |
| - name: Keep JReleaser's log | |
| if: ${{ failure() }} | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: jreleaser-log-native | |
| path: build/jreleaser/trace.log | |
| if-no-files-found: ignore | |
| retention-days: 7 | |
| # Both deployments are uploaded and validated by now. Publishing one is a JReleaser run given its ID, | |
| # which builds nothing. One leg per deployment, so that a re-run repeats only the leg that failed. | |
| publish: | |
| name: publish (${{ matrix.deployment }}) | |
| needs: [jars, native-deploy] | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| include: | |
| - deployment: jars | |
| id: ${{ needs.jars.outputs.deployment-id }} | |
| - deployment: native | |
| id: ${{ needs.native-deploy.outputs.deployment-id }} | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 | |
| - name: Install JDK 21 | |
| uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 | |
| with: | |
| distribution: temurin | |
| java-version: '21' | |
| - name: Publish the deployment | |
| run: ./gradlew jreleaserDeploy | |
| env: | |
| JRELEASER_MAVENCENTRAL_DEPLOYMENT_ID: ${{ matrix.id }} | |
| JRELEASER_DEPLOY_MAVEN_MAVENCENTRAL_SONATYPE_USERNAME: ${{ secrets.JRELEASER_MAVENCENTRAL_USERNAME }} | |
| JRELEASER_DEPLOY_MAVEN_MAVENCENTRAL_SONATYPE_PASSWORD: ${{ secrets.JRELEASER_MAVENCENTRAL_PASSWORD }} | |
| JRELEASER_GPG_SECRET_KEY: ${{ secrets.JRELEASER_GPG_SECRET_KEY }} | |
| JRELEASER_GPG_PASSPHRASE: ${{ secrets.JRELEASER_GPG_PASSPHRASE }} | |
| - name: Keep JReleaser's log | |
| if: ${{ failure() }} | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: jreleaser-log-publish-${{ matrix.deployment }} | |
| path: build/jreleaser/trace.log | |
| if-no-files-found: ignore | |
| retention-days: 7 | |
| # The plugins depend on the version's jars and native images, so they go up only once Maven Central | |
| # serves both, which takes some minutes after the publish job. The Gradle Plugin Portal never takes a | |
| # version back. | |
| gradle-plugins: | |
| name: Gradle plugins | |
| needs: publish | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 90 | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 | |
| - name: Install JDK 21 | |
| uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 | |
| with: | |
| distribution: temurin | |
| java-version: '21' | |
| - name: Wait for Maven Central to serve the version | |
| env: | |
| VERSION: ${{ github.ref_name }} | |
| run: | | |
| for artifact in open-java-format open-java-format-native; do | |
| url="https://repo1.maven.org/maven2/dev/openjavaformat/${artifact}/${VERSION}/${artifact}-${VERSION}.pom" | |
| until curl --silent --fail --head --output /dev/null "$url"; do | |
| echo "Waiting for ${url}" | |
| sleep 30 | |
| done | |
| done | |
| - name: Sign and publish the Gradle plugins | |
| run: ./gradlew :gradle-open-java-format:publishPlugins | |
| env: | |
| GRADLE_PUBLISH_KEY: ${{ secrets.GRADLE_PUBLISH_KEY }} | |
| GRADLE_PUBLISH_SECRET: ${{ secrets.GRADLE_PUBLISH_SECRET }} | |
| JRELEASER_GPG_SECRET_KEY: ${{ secrets.JRELEASER_GPG_SECRET_KEY }} | |
| JRELEASER_GPG_PASSPHRASE: ${{ secrets.JRELEASER_GPG_PASSPHRASE }} | |
| # The IntelliJ plugin carries the formatter jars inside its zip, so it does not wait for Maven Central. It | |
| # waits for the publish job like everything else, so that a version whose jars or native images failed | |
| # stays off the Marketplace too. The plugin is checked against the IDEs it declares support for before it | |
| # goes up; a plugin that fails there would fail JetBrains' own check after the upload anyway. The | |
| # Marketplace never takes a version back and rejects a version it already has, so a re-run of this job | |
| # fails once the upload went through. | |
| jetbrains-plugin: | |
| name: JetBrains Marketplace | |
| needs: publish | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 60 | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 | |
| - name: Install JDK 21 | |
| uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 | |
| with: | |
| distribution: temurin | |
| java-version: '21' | |
| - name: Verify the plugin against the IDEs it supports | |
| run: ./gradlew :open-java-format-idea-plugin:verifyPlugin | |
| - name: Keep the verifier's report | |
| if: ${{ failure() }} | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: plugin-verifier-report | |
| path: open-java-format-idea-plugin/build/reports/pluginVerifier | |
| if-no-files-found: ignore | |
| retention-days: 7 | |
| - name: Upload the plugin | |
| run: ./gradlew :open-java-format-idea-plugin:publishPlugin | |
| env: | |
| JETBRAINS_MARKETPLACE_TOKEN: ${{ secrets.JETBRAINS_MARKETPLACE_TOKEN }} | |
| # What Maven Central does not carry — the runnable formatter jar, the Gradle plugins' jar, the IntelliJ | |
| # plugin zip, the Eclipse plugin jar, and every platform's native binary as a plain download — goes into | |
| # a draft GitHub release on the tag, each file signed with the release key. Only once both deployments | |
| # are published; publishing the draft is a click on GitHub, and a re-run fails while a release for the | |
| # tag exists. | |
| github-release: | |
| name: draft GitHub release | |
| needs: publish | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 | |
| - name: Install JDK 21 | |
| uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 | |
| with: | |
| distribution: temurin | |
| java-version: '21' | |
| - name: Collect every platform's binary | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| path: native-images | |
| pattern: native-image-* | |
| merge-multiple: true | |
| - name: Build the plugins and open the draft release | |
| run: ./gradlew -PreleaseTarget=github -PnativeImages=native-images jreleaserRelease | |
| env: | |
| JRELEASER_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| JRELEASER_GPG_SECRET_KEY: ${{ secrets.JRELEASER_GPG_SECRET_KEY }} | |
| JRELEASER_GPG_PASSPHRASE: ${{ secrets.JRELEASER_GPG_PASSPHRASE }} | |
| - name: Keep JReleaser's log | |
| if: ${{ failure() }} | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: jreleaser-log-github | |
| path: build/jreleaser/trace.log | |
| if-no-files-found: ignore | |
| retention-days: 7 |