From a4ec64e7da7495df5a922714ff4b8af8badff7ad Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Mon, 20 Apr 2026 16:50:06 -0700 Subject: [PATCH 1/8] ci: automate release workflow for snapshots and stable versions --- .github/maintainers_guide.md | 67 +++++------------------------------ .github/workflows/release.yml | 47 ++++++++++++++++++++++++ AGENTS.md | 4 +-- scripts/release.sh | 41 --------------------- 4 files changed, 57 insertions(+), 102 deletions(-) create mode 100644 .github/workflows/release.yml delete mode 100755 scripts/release.sh diff --git a/.github/maintainers_guide.md b/.github/maintainers_guide.md index 82ba9dae0..b378dab3e 100644 --- a/.github/maintainers_guide.md +++ b/.github/maintainers_guide.md @@ -106,58 +106,11 @@ Refer to the [README](https://github.com/slackapi/java-slack-sdk/blob/main/docs/ ### Releasing -#### Prerequisites - -* If you don't have `gnu-sed`, run `brew install gnu-sed` & `brew install gnupg` -* Make sure you've set up your key https://central.sonatype.org/publish/requirements/gpg/ -* Make sure the account you are using has the permission to make releases [under com.slack groupId](https://central.sonatype.com/publishing/com.slack/users) - -Place `$HOME/.m2/settings.xml` with your Sonatype account information. -* Generate user token: https://central.sonatype.org/publish/generate-portal-token/ -* Set the user token id/password: https://central.sonatype.org/publish/publish-portal-maven/#credentials - -```xml - - /${your-home-dir}/.m2/repository - - - central - ${your-username} - ${your-password} - - - central-snapshots - ${your-username} - ${your-password} - - - - org.apache.maven.plugins - org.codehaus.mojo - - -``` - #### Snapshot Release -Snapshot releases are intended for developers to make pre-release versions of their projects available for testing. -To learn more about snapshot releases in maven central repository check out [publish-portal-snapshots](https://central.sonatype.org/publish/publish-portal-snapshots/) +Snapshot releases are automatically published when the version ends with `-SNAPSHOT` for either each push to `main` or manual `workflow_dispatch` event for another branch using the [release workflow](.github/workflows/release.yml). -* From the upstream repository -* Preparation - * `git switch main && git pull origin main` (or the branch you want to release from) - * Make sure there are no build failures at https://github.com/slackapi/java-slack-sdk/actions -* Set a new version - * It is **critical** that the version ends with `-SNAPSHOT`. This is how [central-publishing-maven-plugin](https://central.sonatype.org/publish/publish-portal-snapshots/#publishing-with-the-central-publishing-maven-plugin) automatically recognizes snapshot releases and uploads them the right location. - * If you don't have `gnu-sed`, check out [Prerequisites](#prerequisites) - * Run `scripts/set_version.sh (the version)` (e.g., `scripts/set_version.sh 1.0.0-SNAPSHOT`) -* Ship the libraries - * Switch to **JDK 17** to publish all modules (on macOS, you can run `export JAVA_HOME=$(/usr/libexec/java_home -v 17)` for it) - * Run `scripts/release.sh` (it takes a bit long) - * (If you encounter an error, log in https://oss.sonatype.org/ to check detailed information) -* No need to create a GitHub Release, since this is intended for developers to make pre-release versions of their projects. -* `-SNAPSHOT` versions are intended to be overwritten. - * This enables developers to work with the latest version of a library without needing to update their dependencies repeatedly. +These `-SNAPSHOT` versions are intended to be overwritten. This enables developers to work with the latest version of a library without needing to update their dependencies repeatedly. To learn more about snapshot releases in maven central repository check out [publish-portal-snapshots](https://central.sonatype.org/publish/publish-portal-snapshots/). #### Stable Release @@ -166,19 +119,15 @@ To learn more about snapshot releases in maven central repository check out [pub * `git switch main && git pull origin main` * Make sure there are no build failures at https://github.com/slackapi/java-slack-sdk/actions * Set a new version - * If you don't have `gnu-sed`, check out [Prerequisites](#prerequisites) - * Run `scripts/set_version.sh (the version)` (e.g., `scripts/set_version.sh 1.0.0`) -* Ship the libraries - * Switch to **JDK 17** to publish all modules (on macOS, you can run `export JAVA_HOME=$(/usr/libexec/java_home -v 17)` for it) - * Run `scripts/release.sh` (it takes a bit long) - * (If you encounter an error, log in https://oss.sonatype.org/ to check detailed information) -* Create GitHub Release(s) and add release notes - * [Look at previous releases](https://github.com/slackapi/java-slack-sdk/releases) and follow their layouts - * Prepare a release note by `git log --pretty=format:'%h %s by %an' --abbrev-commit | grep -v "Merge pull request " | head -50` + * Run `scripts/set_version.sh (the version)` (e.g., `scripts/set_version.sh 1.0.0`) — requires `gnu-sed` on macOS (`brew install gnu-sed`) * `git add . -v && git commit -m'version (your version here)'` * `git tag v(your version here)` - * `git push & git push --tags` + * `git push && git push --tags` + * The push to `main` automatically triggers the [release workflow](.github/workflows/release.yml) which publishes to Maven Central +* Create a GitHub Release * Open https://github.com/slackapi/java-slack-sdk/releases/new?tag=v${version} + * [Look at previous releases](https://github.com/slackapi/java-slack-sdk/releases) and follow their layouts + * Prepare a release note by `git log --pretty=format:'%h %s by %an' --abbrev-commit | grep -v "Merge pull request " | head -50` * (Slack Internal) Communicate the release internally. Include a link to the GitHub Release(s). * (Slack Internal) Tweet? Not necessary for patch updates, might be needed for minor updates, definitely needed for major updates. Include a link to the GitHub Release(s). diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..73af6b129 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,47 @@ +name: Release + +on: + push: + branches: + - main + workflow_dispatch: + +jobs: + publish: + name: Publish + if: github.repository == 'slackapi/java-slack-sdk' + runs-on: ubuntu-latest + environment: central + permissions: + contents: read + steps: + - name: Checkout the repo + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + persist-credentials: false + + - name: Set up JDK 17 + uses: actions/setup-java@c1e323688fd81a25caa38c78aa6df2d33d3e20d9 # v4.8.0 + with: + java-version: "17" + distribution: "adopt" + server-id: central + server-username: MAVEN_USERNAME + server-password: MAVEN_PASSWORD + gpg-private-key: ${{ secrets.GPG_KEY }} + gpg-passphrase: MAVEN_GPG_PASSPHRASE + + - name: Publish to Maven Central + run: | + ./mvnw clean deploy \ + -P production-releases \ + -D maven.test.skip=true \ + -pl !bolt-kotlin-examples \ + -pl !bolt-quarkus-examples \ + --batch-mode \ + --no-transfer-progress + env: + MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }} + MAVEN_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} + MAVEN_OPTS: "--add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.lang.reflect=ALL-UNNAMED --add-opens=java.base/java.text=ALL-UNNAMED --add-opens=java.desktop/java.awt.font=ALL-UNNAMED" diff --git a/AGENTS.md b/AGENTS.md index 204e4de22..6a7f0bce3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -608,8 +608,8 @@ Documentation: https://docs.slack.dev/tools/java-slack-sdk/guides/bolt-basics Releases publish all modules simultaneously to Maven Central via Sonatype. -- **Snapshot**: Version must end with `-SNAPSHOT`. Run `scripts/set_version.sh 1.x.y-SNAPSHOT` then `scripts/release.sh` -- **Stable**: Run `scripts/set_version.sh 1.x.y` then `scripts/release.sh`. Requires JDK 17, GPG signing, and Sonatype credentials in `~/.m2/settings.xml` +- **Snapshot**: Automatically published on every push to `main`. Can also be triggered manually via `workflow_dispatch` on any branch with a `-SNAPSHOT` version. +- **Stable**: Run `scripts/set_version.sh 1.x.y`, commit, tag `v1.x.y`, push to `main` — the [release workflow](.github/workflows/release.yml) publishes to Maven Central automatically. Can be re-triggered via `workflow_dispatch` if needed. - Version is set across all `pom.xml` files AND three generated version classes (generated by `scripts/set_version.sh`): - `slack-api-model/src/main/java/com/slack/api/meta/SlackApiModelLibraryVersion.java` - `slack-api-client/src/main/java/com/slack/api/meta/SlackApiClientLibraryVersion.java` diff --git a/scripts/release.sh b/scripts/release.sh deleted file mode 100755 index 008d9e163..000000000 --- a/scripts/release.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/bash - -is_jdk_8=$(echo "$JAVA_HOME" | grep 8.) -if [[ "${is_jdk_8}" != "" ]]; -then - echo "Please use OpenJDK 11 for releasing these libraries." - exit 1 -fi - -exclusion="-pl !bolt-kotlin-examples -pl !bolt-quarkus-examples" - -dir=$(dirname "$0")/.. -release_version=$(sed -n 's/^[[:space:]]*\([^\$]\..*\)<\/version>[[:space:]]*$/\1/p' < "${dir}"/pom.xml) - -export MAVEN_OPTS="--add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.lang.reflect=ALL-UNNAMED --add-opens=java.base/java.text=ALL-UNNAMED --add-opens=java.desktop/java.awt.font=ALL-UNNAMED" - -if [[ "${release_version}" =~ ^.+-SNAPSHOT$ ]]; then - echo "🚀 Releasing a SNAPSHOT version ($release_version) of the project." - profile=production-releases - mvn clean \ - deploy \ - -P production-releases \ - -D maven.test.skip=true \ - ${exclusion} -else - echo "You are releasing a stable version ($release_version) of the project." - read -r -p "This will be available publicly. Is this correct? (y/N): " confirmation - - if [[ ! "$confirmation" =~ ^[Yy]$ ]]; then - echo "Release cancelled by user!" - exit 0 - fi - echo "Confirmed. Proceeding with the stable release." - - profile=production-releases - mvn clean \ - deploy \ - -P production-releases \ - -D maven.test.skip=true \ - ${exclusion} -fi From 073d44d091de7036c3b723ed783b784557c12c63 Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Mon, 20 Apr 2026 16:54:50 -0700 Subject: [PATCH 2/8] test: publish snapshot --- .github/workflows/release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 73af6b129..4fa4c73be 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,6 +1,7 @@ name: Release on: + pull_request: push: branches: - main From 8671ad9a7c709dce87760a0e87a7d9e5124c5538 Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Mon, 20 Apr 2026 16:59:01 -0700 Subject: [PATCH 3/8] fix: configure gpg passphrase --- .github/workflows/release.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4fa4c73be..21ea20611 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -32,11 +32,18 @@ jobs: gpg-private-key: ${{ secrets.GPG_KEY }} gpg-passphrase: MAVEN_GPG_PASSPHRASE + - name: Configure GPG + run: | + echo "allow-loopback-pinentry" >> ~/.gnupg/gpg-agent.conf + gpgconf --reload gpg-agent + - name: Publish to Maven Central run: | ./mvnw clean deploy \ -P production-releases \ -D maven.test.skip=true \ + -D gpg.passphrase="${MAVEN_GPG_PASSPHRASE}" \ + -D gpg.args="--pinentry-mode=loopback" \ -pl !bolt-kotlin-examples \ -pl !bolt-quarkus-examples \ --batch-mode \ From 0ff27401426b3daf75687a1f0356e966c4de898b Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Mon, 20 Apr 2026 18:24:18 -0700 Subject: [PATCH 4/8] fix: attempt gpg reload --- .github/workflows/release.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 21ea20611..e195f0db0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -34,8 +34,10 @@ jobs: - name: Configure GPG run: | + echo "use-agent" >> ~/.gnupg/gpg.conf + echo "pinentry-mode loopback" >> ~/.gnupg/gpg.conf echo "allow-loopback-pinentry" >> ~/.gnupg/gpg-agent.conf - gpgconf --reload gpg-agent + echo RELOADAGENT | gpg-connect-agent - name: Publish to Maven Central run: | @@ -43,7 +45,6 @@ jobs: -P production-releases \ -D maven.test.skip=true \ -D gpg.passphrase="${MAVEN_GPG_PASSPHRASE}" \ - -D gpg.args="--pinentry-mode=loopback" \ -pl !bolt-kotlin-examples \ -pl !bolt-quarkus-examples \ --batch-mode \ From a18baa640e321fa9e7f0978ee166b5a7d83de63b Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Mon, 20 Apr 2026 19:17:46 -0700 Subject: [PATCH 5/8] ci: add snapshot server credentials --- .github/workflows/release.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e195f0db0..6a13f0551 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -32,6 +32,15 @@ jobs: gpg-private-key: ${{ secrets.GPG_KEY }} gpg-passphrase: MAVEN_GPG_PASSPHRASE + - name: Add snapshot server credentials + run: | + sed -i '/<\/servers>/i \ + \ + central-snapshots\ + ${env.MAVEN_USERNAME}\ + ${env.MAVEN_PASSWORD}\ + ' ~/.m2/settings.xml + - name: Configure GPG run: | echo "use-agent" >> ~/.gnupg/gpg.conf From 1558a92c5cc8e5d6bc0860f6dce30bbab7067f98 Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Mon, 20 Apr 2026 21:03:12 -0700 Subject: [PATCH 6/8] ci: require approval --- .github/maintainers_guide.md | 5 +++-- .github/workflows/release.yml | 4 ---- AGENTS.md | 4 ++-- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/.github/maintainers_guide.md b/.github/maintainers_guide.md index b378dab3e..3a7f14ad2 100644 --- a/.github/maintainers_guide.md +++ b/.github/maintainers_guide.md @@ -108,7 +108,7 @@ Refer to the [README](https://github.com/slackapi/java-slack-sdk/blob/main/docs/ #### Snapshot Release -Snapshot releases are automatically published when the version ends with `-SNAPSHOT` for either each push to `main` or manual `workflow_dispatch` event for another branch using the [release workflow](.github/workflows/release.yml). +Snapshot releases are published by starting and approving the [release workflow](https://github.com/slackapi/java-slack-sdk/actions/workflows/release.yml) with `workflow_dispatch` for any branch with a `-SNAPSHOT` version, including the `main` branch. These `-SNAPSHOT` versions are intended to be overwritten. This enables developers to work with the latest version of a library without needing to update their dependencies repeatedly. To learn more about snapshot releases in maven central repository check out [publish-portal-snapshots](https://central.sonatype.org/publish/publish-portal-snapshots/). @@ -123,7 +123,8 @@ These `-SNAPSHOT` versions are intended to be overwritten. This enables develope * `git add . -v && git commit -m'version (your version here)'` * `git tag v(your version here)` * `git push && git push --tags` - * The push to `main` automatically triggers the [release workflow](.github/workflows/release.yml) which publishes to Maven Central +* Publish to Maven Central + * Start and approve the [release workflow](https://github.com/slackapi/java-slack-sdk/actions/workflows/release.yml) using `workflow_dispatch` on `main` * Create a GitHub Release * Open https://github.com/slackapi/java-slack-sdk/releases/new?tag=v${version} * [Look at previous releases](https://github.com/slackapi/java-slack-sdk/releases) and follow their layouts diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6a13f0551..d09765896 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,10 +1,6 @@ name: Release on: - pull_request: - push: - branches: - - main workflow_dispatch: jobs: diff --git a/AGENTS.md b/AGENTS.md index 6a7f0bce3..220570548 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -608,8 +608,8 @@ Documentation: https://docs.slack.dev/tools/java-slack-sdk/guides/bolt-basics Releases publish all modules simultaneously to Maven Central via Sonatype. -- **Snapshot**: Automatically published on every push to `main`. Can also be triggered manually via `workflow_dispatch` on any branch with a `-SNAPSHOT` version. -- **Stable**: Run `scripts/set_version.sh 1.x.y`, commit, tag `v1.x.y`, push to `main` — the [release workflow](.github/workflows/release.yml) publishes to Maven Central automatically. Can be re-triggered via `workflow_dispatch` if needed. +- **Snapshot**: Trigger the [release workflow](.github/workflows/release.yml) via `workflow_dispatch` on any branch with a `-SNAPSHOT` version. +- **Stable**: Run `scripts/set_version.sh 1.x.y`, commit, tag `v1.x.y`, push to `main`, then trigger the [release workflow](.github/workflows/release.yml) via `workflow_dispatch`. - Version is set across all `pom.xml` files AND three generated version classes (generated by `scripts/set_version.sh`): - `slack-api-model/src/main/java/com/slack/api/meta/SlackApiModelLibraryVersion.java` - `slack-api-client/src/main/java/com/slack/api/meta/SlackApiClientLibraryVersion.java` From 453c6a73d9fc8983030d4efd1b14628b7ed0658f Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Mon, 20 Apr 2026 21:32:21 -0700 Subject: [PATCH 7/8] test: confirm approval requirement --- .github/workflows/release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d09765896..122cd9f59 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,6 +1,7 @@ name: Release on: + pull_request: workflow_dispatch: jobs: From 36765046dd415f6af63e041194ca54322c8c986c Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Mon, 20 Apr 2026 21:34:26 -0700 Subject: [PATCH 8/8] revert: approval requirement --- .github/workflows/release.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 122cd9f59..d09765896 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,7 +1,6 @@ name: Release on: - pull_request: workflow_dispatch: jobs: