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..c0b37055 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,21 @@ file [H3Core.java](./src/main/java/com/uber/h3core/H3Core.java), and support for the Linux x64 and Darwin x64 platforms. ## Unreleased Changes +## 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 +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) diff --git a/build.gradle b/build.gradle index f28f054b..3fd731b5 100644 --- a/build.gradle +++ b/build.gradle @@ -18,8 +18,7 @@ plugins { id 'io.github.gradle-nexus.publish-plugin' version '1.3.0' } -group = 'com.uber' -version = '4.1.3-SNAPSHOT' +group = 'io.github.isaacbrodsky' description = 'Java bindings for H3, a hierarchical hexagonal geospatial indexing system.' java { @@ -124,7 +123,7 @@ publishing { from components.java pom { name = 'h3' - url = 'https://github.com/uber/h3-java' + url = 'https://github.com/isaacbrodsky/h3-java' description = project.description licenses { license { @@ -133,22 +132,20 @@ publishing { distribution = 'repo' } } - organization { - name = 'Uber Open Source' - url = 'https://github.com/uber/' - } + // organization { + // name = 'Uber Open Source' + // url = 'https://github.com/uber/' + // } scm { - connection = 'scm:git:git://github.com/uber/h3-java.git' - developerConnection = 'scm:git:ssh://git@github.com/uber/h3-java.git' - url = 'http://github.com/uber/h3-java/tree/master' + connection = 'scm:git:git://github.com/isaacbrodsky/h3-java.git' + developerConnection = 'scm:git:ssh://git@github.com/isaacbrodsky/h3-java.git' + url = 'http://github.com/isaacbrodsky/h3-java/tree/master' } developers { developer { id = 'isaacbrodsky' name = 'Isaac Brodsky' email = 'isaac@isaacbrodsky.com' - organization = 'Uber Technologies, Inc.' - organizationUrl = 'https://github.com/uber/' } } } @@ -181,12 +178,15 @@ 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": - nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/")) - snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")) + // nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/")) + // snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")) + nexusUrl.set(uri("https://ossrh-staging-api.central.sonatype.com/service/local/")) + snapshotRepositoryUrl.set(uri("https://central.sonatype.com/repository/maven-snapshots/")) } } } diff --git a/docs/releasing.md b/docs/releasing.md index 1f7013c3..83b0a72c 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -2,6 +2,10 @@ The H3-Java library is published to Maven Central via OSSRH. +The release is triggered via GitHub Actions, when a tag of the form `v1.2.3` is pushed, or via workflow dispatch. The release workflow handles all parts of the release. + +## 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..d1188b49 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.tml +version=4.3.0 +