diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..032bb3ce --- /dev/null +++ b/.github/workflows/release.yml @@ -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] + 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/download-artifact@v4.1.7 + with: + pattern: docker-built-shared-objects-* + merge-multiple: true + path: src/main/resources/ + + - name: Download Mac binaries + uses: actions/download-artifact@v4.1.7 + 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 + 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 diff --git a/CHANGELOG.md b/CHANGELOG.md index 712db0b9..b076a3eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,3 @@ -# Change Log All notable changes to this project will be documented in this file. This project adheres to a [versioning policy](./docs/versioning.md). @@ -6,15 +5,28 @@ 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) diff --git a/build.gradle b/build.gradle index f28f054b..a6816ff3 100644 --- a/build.gradle +++ b/build.gradle @@ -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 { @@ -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": diff --git a/docs/releasing.md b/docs/releasing.md index 1f7013c3..926350de 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -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.) + +## 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. @@ -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`: diff --git a/gradle.properties b/gradle.properties index 3686b795..b280f956 100644 --- a/gradle.properties +++ b/gradle.properties @@ -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 +