Skip to content

Add release workflow #168

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 20 commits into from
Jun 26, 2025
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
224 changes: 224 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
name: Release to Maven Central

on:
# Manual trigger
workflow_dispatch:
inputs:
release_version:
description: "Version to release (if empty, derive from project version)"
required: false
# Automatic trigger on pushing a version tag (e.g., "v1.2.3")
push:
tags:
- "v*"

jobs:
# Corresponds to tests in tests.yml
build-with-docker:
name: Build ${{ matrix.dockcross-only }} (Dockcross)
runs-on: ${{ matrix.os }}

strategy:
matrix:
os: [ubuntu-latest]
java-distribution: [adopt]
java-version: [8]
Copy link
Member

Choose a reason for hiding this comment

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

8 is EOL, right? Should we move this higher?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I've seen different things about Java 8. It seems Oracle has very long term support for it, but it does seem practically EOL. I'm not sure how much the open source ecosystem is still supporting it as I haven't done as much Java work recently.

My plan was to leave the baseline at Java 8 for now (since that is what we previously built) and then in a follow up PR re-enable some code quality tools and bump the baseline to a newer LTS release.

dockcross-only:
[
"android-arm",
"android-arm64",
"linux-arm64",
"linux-armv5",
"linux-armv7",
"linux-s390x",
"linux-ppc64le",
"linux-x64",
"linux-x86",
"windows-static-x64",
"windows-static-x86",
]

steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- uses: actions/setup-java@v2
with:
distribution: "${{ matrix.java-distribution }}"
java-version: "${{ matrix.java-version }}"

- uses: gradle/actions/setup-gradle@v3
with:
gradle-version: wrapper

- uses: actions/cache@v4
id: gradle-cache
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-

- name: Tests
run: ./gradlew clean test -Ph3SystemPrune=true "-Ph3DockcrossOnly=${{ matrix.dockcross-only }}"
env:
OCI_EXE: docker

- uses: actions/upload-artifact@v4
name: Upload artifacts
with:
name: docker-built-shared-objects-${{ matrix.dockcross-only }}
path: |
src/main/resources/*/*.so
src/main/resources/*/*.dll
if-no-files-found: error

# Corresponsd to tests-no-docker in tests.yml
build:
name: Build ${{ matrix.os }}
runs-on: ${{ matrix.os }}

strategy:
matrix:
os: [macos-latest]
java-distribution: [adopt]
java-version: [8]

steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- uses: actions/setup-java@v2
with:
distribution: "${{ matrix.java-distribution }}"
java-version: "${{ matrix.java-version }}"

- uses: gradle/actions/setup-gradle@v3
with:
gradle-version: wrapper

- uses: actions/cache@v4
id: gradle-cache
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-

- name: Tests
run: ./gradlew clean test

- uses: actions/upload-artifact@v4
name: Upload Mac OS Artifacts
with:
name: macos-built-shared-objects
path: src/main/resources/*/*.dylib
if-no-files-found: error

release:
runs-on: ubuntu-latest
permissions:
contents: write # allow pushing commits/tags

needs:
- build-with-docker
- build

steps:
- name: Check out code
uses: actions/checkout@v3

- name: Set up JDK
uses: actions/setup-java@v3
with:
distribution: "temurin"
java-version: "21"

- name: Determine release version
id: vars
run: |
# Derive the release version (drop "-SNAPSHOT") from Gradle project or input
VERSION_INPUT="${{ github.event.inputs.release_version || '' }}"
if [ -n "$VERSION_INPUT" ]; then
RELEASE_VERSION="$VERSION_INPUT"
else
RELEASE_VERSION=$(grep -E 'version=' gradle.properties | sed -E 's/version=//')
fi
echo "RELEASE_VERSION=$RELEASE_VERSION" >> $GITHUB_ENV

- name: Remove -SNAPSHOT suffix (prepare release version)
if: ${{ github.event_name == 'workflow_dispatch' }}
run: |
sed -i -E "s/${RELEASE_VERSION}-SNAPSHOT/$RELEASE_VERSION/" gradle.properties || true
git config user.name "github-actions"
git config user.email "[email protected]"
git commit -am "chore: release $RELEASE_VERSION [skip ci]"

- name: Create Git tag for release
if: ${{ github.event_name == 'workflow_dispatch' }}
run: |
git tag -a "v${RELEASE_VERSION}" -m "Release $RELEASE_VERSION"
git push origin HEAD:master --follow-tags

- name: Download Docker binaries
uses: actions/[email protected]
with:
pattern: docker-built-shared-objects-*
merge-multiple: true
path: src/main/resources/

- name: Download Mac binaries
uses: actions/[email protected]
with:
name: macos-built-shared-objects
path: src/main/resources/

- name: Download and test
run: |
./gradlew clean test assemble -Ph3GithubArtifactsUse=true -Ph3GithubArtifactsByRun=true

- name: List files in jars
run: |
ls -lh build/libs
for f in build/libs/*.jar; do
echo "File: $f"
unzip -l "$f"
done

- name: Publish to Sonatype OSSRH (Maven Central)
env:
SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }}
SIGNING_KEY_ID: ${{ secrets.SIGNING_KEY_ID }}
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
OSSRH_STAGING_PROFILE_ID: ${{ secrets.OSSRH_STAGING_PROFILE_ID }}
run: ./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository -Ph3GithubArtifactsUse=true -Ph3GithubArtifactsByRun=true

- name: Create GitHub Release (with changelog notes)
# This uses an action to create a release on GitHub
uses: softprops/action-gh-release@v1
with:
tag_name: "v${{ env.RELEASE_VERSION }}"
name: "${{ env.RELEASE_VERSION }}"
body_path: CHANGELOG.md # assumes changelog contains latest release notes at top
Copy link
Member

Choose a reason for hiding this comment

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

Will this include the entire changelog per release? Or just the latest release?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Based on the repo https://github.com/softprops/action-gh-release I think it is set up to take the first markdown section, the generated release should be very easy to manually modify after the fact if the detected changelog is not right.

env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Bump to next snapshot version
if: ${{ github.event_name != 'workflow_dispatch' }}
run: |
# Bump minor version (for example) and append -SNAPSHOT for continued development
NEXT_VERSION=$(echo $RELEASE_VERSION | awk -F. -v OFS="." '{$NF += 1; print $0}') # increment last segment
NEXT_VERSION="$NEXT_VERSION-SNAPSHOT"
sed -i -E "s/$RELEASE_VERSION/$NEXT_VERSION/" gradle.properties || true
git config user.name "github-actions"
git config user.email "[email protected]"
git commit -am "chore: start next development cycle $NEXT_VERSION [skip ci]"
git push origin HEAD:master
20 changes: 16 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,32 @@
# Change Log
All notable changes to this project will be documented in this file.
This project adheres to a [versioning policy](./docs/versioning.md).

The public API of this library consists of the public functions declared in
file [H3Core.java](./src/main/java/com/uber/h3core/H3Core.java), and support
for the Linux x64 and Darwin x64 platforms.

## Unreleased Changes
## [4.3.0] - 2025-06-26
### Added
- `polygonToCellsExperimental` functions from H3 v4.2.0. (#163)
- `gridRing` function from H3 v4.3.0. (#169)

### Fixed
- Corrected order of `polygonToCellsExperimental` arguments. (#166)
- Fixed build on ARM Linux. (#162)

### Changed
- Converted build system to Gradle and automated deploys. Added separate build steps for mac OS on M1 (ARM) and x64. (#167, #168)
- Upgraded the core library to v4.2.1. (#165)

## [4.1.2] - 2024-11-01
## Fixed
Note: This release is not available in Maven Central.

### Fixed
- Fixed a memory leak in `polygonToCells` and optimize JNI calls. (#150)
- Use `Files.createTempFile` so temporary file permissions are more restrictive. (#141)
- Fixed a potential segfault in `cellsToMultiPolygon` on error. (#129)

## Changed
### Changed
- Optimize JNI calls. (#154)
- Added JNI config and tests for native image. (#153, #155)
- Bumped dockcross versions (#151, #152)
Expand Down
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ plugins {
}

group = 'com.uber'
version = '4.1.3-SNAPSHOT'
description = 'Java bindings for H3, a hierarchical hexagonal geospatial indexing system.'

java {
Expand Down Expand Up @@ -181,7 +180,8 @@ signing {
nexusPublishing {
repositories {
sonatype {
stagingProfileId.set(System.getenv("OSSRH_STAGING_PROFILE_ID"))
// Performance optimization, not needed:
// stagingProfileId.set(System.getenv("OSSRH_STAGING_PROFILE_ID"))
username.set(System.getenv("OSSRH_USERNAME"))
password.set(System.getenv("OSSRH_PASSWORD"))
// For newer Sonatype accounts (after Feb 2021) use "s01.oss.sonatype.org":
Expand Down
10 changes: 7 additions & 3 deletions docs/releasing.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

The H3-Java library is published to Maven Central via OSSRH.

Before releasing, make sure the version of the project is in the form `1.2.3-SNAPSHOT` where `1.2.3` is the version you wish to release. The release is triggered via GitHub Actions, when a tag of the form `v1.2.3` is pushed. (Workflow dispatch can be used but is not tested.)

Choose a reason for hiding this comment

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

Should this be:

when a tag of the form `1.2.3-SNAPSHOT` is pushed

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

No, the tag should be the release version with v prefixed. Cf. successful run here: https://github.com/isaacbrodsky/h3-java/actions/runs/15884738203


## Old instructions for manual releasing

You must be a member of the `com.uber` group to release the library via OSSRH. You must have a [signing key](http://central.sonatype.org/pages/working-with-pgp-signatures.html) setup, and you must have your OSSRH username and password in the appropriate [Maven settings file](http://central.sonatype.org/pages/apache-maven.html).

Release builds pull artifacts from Github Actions. This is needed so that the deployed artifact contains all supported operating system/architecture combinations. (In particular, Mac OS artifacts must be built natively.) In order to release, there must be a completed build of the Git commit to release on Github. The build must be less than 30 days old, as artifacts are only kept for that time.
Expand All @@ -13,14 +17,14 @@ Release builds pull artifacts from Github Actions. This is needed so that the de
5. If this looks good, close and release the build in [Sonatype Nexus Manager](https://oss.sonatype.org/).
6. Update `CHANGELOG.md` to have an Unreleased section, and commit. The release is now done and development can resume from this point.

## Troubleshooting
### Troubleshooting

### Dependencies for `pull-from-github.sh`
#### Dependencies for `pull-from-github.sh`

* You should install the [Github CLI](https://cli.github.com) and authenticate with it first. You may need to use a personal access token (classic) with workflows scope.
* `jq`

### gpg: signing failed: Inappropriate ioctl for device
#### gpg: signing failed: Inappropriate ioctl for device

Per [StackOverflow](https://stackoverflow.com/questions/57591432/gpg-signing-failed-inappropriate-ioctl-for-device-on-macos-with-maven), run the following before `mvn release:perform`:

Expand Down
3 changes: 3 additions & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@
# Blocked on https://github.com/nbaztec/coveralls-jacoco-gradle-plugin/issues/66
org.gradle.configuration-cache=false

# No spaces on the following line, needed by release.yml:
version=4.3.0-SNAPSHOT

Loading