From f3c56277c40dcd74be72c01812ab1c123ff259f1 Mon Sep 17 00:00:00 2001 From: Ahmed Metwally Date: Fri, 16 Oct 2026 11:41:53 -0700 Subject: [PATCH 1/5] Release to Maven Central with publishAndReleaseToMavenCentral Match h3-java: upload, validate, and promote in CI instead of staging-only publishToMavenCentral. Wait for PUBLISHED before the workflow completes. --- .github/workflows/publish-release.yml | 33 +++++++++++++++++++-------- RELEASING.md | 4 ++-- gradle.properties | 2 ++ 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index 0d922ef..52dc6e0 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -1,6 +1,11 @@ -name: Publish release to Maven Central +name: Release to Maven Central on: + workflow_dispatch: + inputs: + release_version: + description: 'Version to release (must match VERSION_NAME in gradle.properties if empty)' + required: false push: tags: - 'v[0-9]+.[0-9]+.[0-9]+' @@ -13,7 +18,7 @@ concurrency: cancel-in-progress: false jobs: - publish-release: + release: if: github.repository == 'uber/ussi' runs-on: ubuntu-latest steps: @@ -25,17 +30,27 @@ jobs: - name: Verify release tag and version env: RELEASE_TAG: ${{ github.ref_name }} + RELEASE_VERSION_INPUT: ${{ github.event.inputs.release_version }} run: | - if [[ ! "$RELEASE_TAG" =~ ^v([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then - echo "Release tag must have the form vX.Y.Z: $RELEASE_TAG" >&2 - exit 1 + if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then + if [[ -n "$RELEASE_VERSION_INPUT" ]]; then + release_version="$RELEASE_VERSION_INPUT" + else + release_version="$(sed -n 's/^VERSION_NAME=//p' gradle.properties)" + fi + else + if [[ ! "$RELEASE_TAG" =~ ^v([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then + echo "Release tag must have the form vX.Y.Z: $RELEASE_TAG" >&2 + exit 1 + fi + release_version="${BASH_REMATCH[1]}.${BASH_REMATCH[2]}.${BASH_REMATCH[3]}" fi - release_version="${BASH_REMATCH[1]}.${BASH_REMATCH[2]}.${BASH_REMATCH[3]}" configured_version="$(sed -n 's/^VERSION_NAME=//p' gradle.properties)" if [[ "$configured_version" != "$release_version" ]]; then - echo "VERSION_NAME ($configured_version) must match the release tag ($RELEASE_TAG)" >&2 + echo "VERSION_NAME ($configured_version) must match the release version ($release_version)" >&2 exit 1 fi + echo "RELEASE_VERSION=$release_version" >> "$GITHUB_ENV" - name: Set up JDK uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v4.7.0 @@ -51,7 +66,7 @@ jobs: - name: Test with Gradle run: ./gradlew test --no-daemon - - name: Upload signed release + - name: Publish and release to Maven Central env: ORG_GRADLE_PROJECT_RELEASE_SIGNING_ENABLED: 'true' ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.MAVEN_CENTRAL_USER_TOKEN_USERNAME }} @@ -59,4 +74,4 @@ jobs: ORG_GRADLE_PROJECT_signingInMemoryKeyId: ${{ secrets.PGP_PRIVATE_KEY_ID }} ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.PGP_SIGNING_KEY_PRIVATE_KEY }} ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.PGP_SIGNING_KEY_PASSWORD }} - run: ./gradlew publishToMavenCentral --no-daemon + run: ./gradlew publishAndReleaseToMavenCentral --no-daemon diff --git a/RELEASING.md b/RELEASING.md index f641951..e4e64cf 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -7,7 +7,7 @@ Published artifacts use **`com.uber.ussi:ussi`**. ## CI and local builds - **Pull requests and main:** Bazel tests (`.github/workflows/tests.yml`). -- **Releases:** Gradle publishes to Maven Central (`.github/workflows/publish-release.yml`). +- **Releases:** Gradle uploads, validates, and releases to Maven Central (`.github/workflows/publish-release.yml` via `publishAndReleaseToMavenCentral`). Both build systems share the same `src/main/java` and `src/test/java` trees. Bazel remains supported for day-to-day development; Gradle is the supported release path for Uber open-source JVM libraries. @@ -19,7 +19,7 @@ Gradle requires JDK 21 or later. On Uber-managed machines that inject an interna 2. Update `maven_coordinates` in `BUILD.bazel` to the same version. 3. Merge to `main`. 4. Create and push an annotated tag `vX.Y.Z` matching `VERSION_NAME`. -5. Confirm the **Publish release to Maven Central** workflow succeeds on GitHub Actions. +5. Confirm the **Release to Maven Central** workflow succeeds (it waits until the deployment is published, not only staged). 6. Confirm the artifact on [Maven Central](https://central.sonatype.com/artifact/com.uber.ussi/ussi). If tag `vX.Y.Z` already exists on an older commit, move the tag after the publish workflow is on `main`, or cut the next patch version instead. diff --git a/gradle.properties b/gradle.properties index 4402b68..ce893e5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -21,4 +21,6 @@ POM_DEVELOPER_NAME=Uber Technologies POM_DEVELOPER_URL=https://uber.com mavenCentralPublishing=true +mavenCentralDeploymentValidation=PUBLISHED +SONATYPE_CLOSE_TIMEOUT_SECONDS=3600 RELEASE_SIGNING_ENABLED=true From 31fca82743d3f0b39bf3a936656835f3e36d80f3 Mon Sep 17 00:00:00 2001 From: Ahmed Metwally Date: Fri, 16 Oct 2026 14:08:06 -0700 Subject: [PATCH 2/5] Align release workflow with h3-java automation Add CHANGELOG-driven GitHub Releases, workflow_dispatch snapshot stripping, and VERSION_NAME/BUILD.bazel prep commits. Keep publishAndReleaseToMavenCentral. --- .github/workflows/publish-release.yml | 50 ++++++++++++++++++++++----- CHANGELOG.md | 12 +++++++ RELEASING.md | 32 ++++++++++++----- 3 files changed, 77 insertions(+), 17 deletions(-) create mode 100644 CHANGELOG.md diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index 52dc6e0..db5cfe2 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -4,15 +4,12 @@ on: workflow_dispatch: inputs: release_version: - description: 'Version to release (must match VERSION_NAME in gradle.properties if empty)' + description: 'Release version (default: VERSION_NAME from gradle.properties, without -SNAPSHOT)' required: false push: tags: - 'v[0-9]+.[0-9]+.[0-9]+' -permissions: - contents: read - concurrency: group: maven-central-release cancel-in-progress: false @@ -21,13 +18,15 @@ jobs: release: if: github.repository == 'uber/ussi' runs-on: ubuntu-latest + permissions: + contents: write steps: - name: Check out USSI sources uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v4.2.2 with: - persist-credentials: false + fetch-depth: 0 - - name: Verify release tag and version + - name: Determine release version env: RELEASE_TAG: ${{ github.ref_name }} RELEASE_VERSION_INPUT: ${{ github.event.inputs.release_version }} @@ -37,6 +36,7 @@ jobs: release_version="$RELEASE_VERSION_INPUT" else release_version="$(sed -n 's/^VERSION_NAME=//p' gradle.properties)" + release_version="${release_version%-SNAPSHOT}" fi else if [[ ! "$RELEASE_TAG" =~ ^v([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then @@ -46,12 +46,38 @@ jobs: release_version="${BASH_REMATCH[1]}.${BASH_REMATCH[2]}.${BASH_REMATCH[3]}" fi configured_version="$(sed -n 's/^VERSION_NAME=//p' gradle.properties)" - if [[ "$configured_version" != "$release_version" ]]; then - echo "VERSION_NAME ($configured_version) must match the release version ($release_version)" >&2 + configured_base="${configured_version%-SNAPSHOT}" + if [[ "$configured_base" != "$release_version" ]]; then + echo "Release version ($release_version) must match VERSION_NAME ($configured_version)" >&2 exit 1 fi echo "RELEASE_VERSION=$release_version" >> "$GITHUB_ENV" + - name: Extract release notes + run: | + awk -v ver="$RELEASE_VERSION" ' + /^## / { if (found) exit; if (index($0, "## [" ver "]") == 1) { found=1; next } } + found + ' CHANGELOG.md > release_notes.md + if [[ ! -s release_notes.md ]]; then + echo "Add a ## [$RELEASE_VERSION] section to CHANGELOG.md" >&2 + exit 1 + fi + + - name: Prepare release version on main + if: github.event_name == 'workflow_dispatch' + run: | + sed -i -E "s/^VERSION_NAME=.*/VERSION_NAME=${RELEASE_VERSION}/" gradle.properties + sed -i -E "s/maven_coordinates = \"com.uber.ussi:ussi:[^\"]+\"/maven_coordinates = \"com.uber.ussi:ussi:${RELEASE_VERSION}\"/" BUILD.bazel + if git diff --quiet; then + echo "VERSION_NAME and BUILD.bazel already at release version ${RELEASE_VERSION}" + exit 0 + fi + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git commit -am "chore: release ${RELEASE_VERSION} [skip ci]" + git push origin HEAD:main + - name: Set up JDK uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v4.7.0 with: @@ -75,3 +101,11 @@ jobs: ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.PGP_SIGNING_KEY_PRIVATE_KEY }} ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.PGP_SIGNING_KEY_PASSWORD }} run: ./gradlew publishAndReleaseToMavenCentral --no-daemon + + - name: Create GitHub Release + uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v2.3.3 + with: + tag_name: v${{ env.RELEASE_VERSION }} + name: ${{ env.RELEASE_VERSION }} + body_path: release_notes.md + generate_release_notes: false diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..21783d6 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,12 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). + +## [0.1.0] - 2026-10-16 + +### Added + +- Initial open-source release of Uber Similarity Search Index (USSI). +- Gradle and Bazel build support; Maven coordinates `com.uber.ussi:ussi`. diff --git a/RELEASING.md b/RELEASING.md index e4e64cf..a71ddf8 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -7,21 +7,35 @@ Published artifacts use **`com.uber.ussi:ussi`**. ## CI and local builds - **Pull requests and main:** Bazel tests (`.github/workflows/tests.yml`). -- **Releases:** Gradle uploads, validates, and releases to Maven Central (`.github/workflows/publish-release.yml` via `publishAndReleaseToMavenCentral`). +- **Releases:** `.github/workflows/publish-release.yml` (Gradle `publishAndReleaseToMavenCentral`, GitHub Release, changelog). Both build systems share the same `src/main/java` and `src/test/java` trees. Bazel remains supported for day-to-day development; Gradle is the supported release path for Uber open-source JVM libraries. Gradle requires JDK 21 or later. On Uber-managed machines that inject an internal Artifactory `init.gradle`, use a clean `GRADLE_USER_HOME` (for example `GRADLE_USER_HOME=$PWD/.gradle-home ./gradlew test`) so dependencies resolve from Maven Central only. -## Cut a release +## Version files -1. Set `VERSION_NAME` in `gradle.properties` to the release version (no `-SNAPSHOT` suffix). -2. Update `maven_coordinates` in `BUILD.bazel` to the same version. +Keep these in sync: + +- `gradle.properties` — `VERSION_NAME` (use `-SNAPSHOT` on `main` between releases) +- `BUILD.bazel` — `maven_coordinates` on `//:src_main` +- `CHANGELOG.md` — `## [X.Y.Z]` section for each release + +## Cut a release (recommended: workflow dispatch) + +1. On `main`, set `VERSION_NAME` to the next release with a `-SNAPSHOT` suffix (for example `0.2.0-SNAPSHOT`) and align `BUILD.bazel`. +2. Add a `## [0.2.0]` section to `CHANGELOG.md`. 3. Merge to `main`. -4. Create and push an annotated tag `vX.Y.Z` matching `VERSION_NAME`. -5. Confirm the **Release to Maven Central** workflow succeeds (it waits until the deployment is published, not only staged). -6. Confirm the artifact on [Maven Central](https://central.sonatype.com/artifact/com.uber.ussi/ussi). +4. Run **Release to Maven Central** → **Run workflow** on `main` (optional `release_version` override). + - CI strips `-SNAPSHOT`, commits the release version to `gradle.properties` and `BUILD.bazel`, publishes to Maven Central, and creates the GitHub Release + tag. +5. Confirm the artifact on [Maven Central](https://central.sonatype.com/artifact/com.uber.ussi/ussi). +6. Open a follow-up PR bumping `VERSION_NAME` and `BUILD.bazel` to the next `-SNAPSHOT` (branch protection may block the workflow from doing this automatically). + +## Cut a release (tag push) + +Alternatively, after `VERSION_NAME` and `BUILD.bazel` already hold the release version (no `-SNAPSHOT`): -If tag `vX.Y.Z` already exists on an older commit, move the tag after the publish workflow is on `main`, or cut the next patch version instead. +1. Push annotated tag `vX.Y.Z`. +2. The same workflow tests, publishes, and creates the GitHub Release. -After the release is published, bump `VERSION_NAME` in `gradle.properties` and `maven_coordinates` in `BUILD.bazel` to the next `-SNAPSHOT` development version. +If tag `vX.Y.Z` already exists on an older commit, move the tag after fixing the release workflow, or cut the next patch version. From 2cae9e2a89f4ecefb8b4e31e50073aaa48a10ae7 Mon Sep 17 00:00:00 2001 From: Ahmed Metwally Date: Fri, 16 Oct 2026 17:10:36 -0700 Subject: [PATCH 3/5] Address release workflow review; rename to release.yml Use runtime git identity, GITHUB_TOKEN for gh-release, match h3-java filename. --- .../workflows/{publish-release.yml => release.yml} | 12 ++++++++---- RELEASING.md | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) rename .github/workflows/{publish-release.yml => release.yml} (90%) diff --git a/.github/workflows/publish-release.yml b/.github/workflows/release.yml similarity index 90% rename from .github/workflows/publish-release.yml rename to .github/workflows/release.yml index db5cfe2..b093dc0 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/release.yml @@ -4,7 +4,7 @@ on: workflow_dispatch: inputs: release_version: - description: 'Release version (default: VERSION_NAME from gradle.properties, without -SNAPSHOT)' + description: 'Version to release (if empty, derive from VERSION_NAME in gradle.properties)' required: false push: tags: @@ -66,6 +66,9 @@ jobs: - name: Prepare release version on main if: github.event_name == 'workflow_dispatch' + env: + GIT_USER_NAME: ${{ github.actor }} + GIT_USER_EMAIL: ${{ format('{0}+{1}@users.noreply.github.com', github.actor_id, github.actor) }} run: | sed -i -E "s/^VERSION_NAME=.*/VERSION_NAME=${RELEASE_VERSION}/" gradle.properties sed -i -E "s/maven_coordinates = \"com.uber.ussi:ussi:[^\"]+\"/maven_coordinates = \"com.uber.ussi:ussi:${RELEASE_VERSION}\"/" BUILD.bazel @@ -73,8 +76,8 @@ jobs: echo "VERSION_NAME and BUILD.bazel already at release version ${RELEASE_VERSION}" exit 0 fi - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git config user.name "$GIT_USER_NAME" + git config user.email "$GIT_USER_EMAIL" git commit -am "chore: release ${RELEASE_VERSION} [skip ci]" git push origin HEAD:main @@ -108,4 +111,5 @@ jobs: tag_name: v${{ env.RELEASE_VERSION }} name: ${{ env.RELEASE_VERSION }} body_path: release_notes.md - generate_release_notes: false + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/RELEASING.md b/RELEASING.md index a71ddf8..6bdc0ad 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -7,7 +7,7 @@ Published artifacts use **`com.uber.ussi:ussi`**. ## CI and local builds - **Pull requests and main:** Bazel tests (`.github/workflows/tests.yml`). -- **Releases:** `.github/workflows/publish-release.yml` (Gradle `publishAndReleaseToMavenCentral`, GitHub Release, changelog). +- **Releases:** `.github/workflows/release.yml` (Gradle `publishAndReleaseToMavenCentral`, GitHub Release, changelog). Both build systems share the same `src/main/java` and `src/test/java` trees. Bazel remains supported for day-to-day development; Gradle is the supported release path for Uber open-source JVM libraries. From 6d658d51ccc5f4c4d395c5b19e3f4345bb01a3d0 Mon Sep 17 00:00:00 2001 From: Ahmed Metwally Date: Fri, 23 Oct 2026 10:26:12 -0700 Subject: [PATCH 4/5] Align release workflow with landed motif #281 Tag-triggered publishToMavenCentral with automatic Central promotion, motif-style changelog and GitHub Release, and USSI BUILD.bazel validation. --- .github/workflows/release.yml | 99 ++++++++++++----------------------- CHANGELOG.md | 7 ++- RELEASING.md | 70 ++++++++++++++++++------- gradle.properties | 3 +- 4 files changed, 89 insertions(+), 90 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b093dc0..8bfd6fd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,15 +1,13 @@ name: Release to Maven Central on: - workflow_dispatch: - inputs: - release_version: - description: 'Version to release (if empty, derive from VERSION_NAME in gradle.properties)' - required: false push: tags: - 'v[0-9]+.[0-9]+.[0-9]+' +permissions: + contents: write # Create the GitHub Release. + concurrency: group: maven-central-release cancel-in-progress: false @@ -18,98 +16,67 @@ jobs: release: if: github.repository == 'uber/ussi' runs-on: ubuntu-latest - permissions: - contents: write steps: - - name: Check out USSI sources - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v4.2.2 + - name: Check out release tag + uses: actions/checkout@v7 with: - fetch-depth: 0 + persist-credentials: false - - name: Determine release version + - name: Verify release tag and version env: RELEASE_TAG: ${{ github.ref_name }} - RELEASE_VERSION_INPUT: ${{ github.event.inputs.release_version }} run: | - if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then - if [[ -n "$RELEASE_VERSION_INPUT" ]]; then - release_version="$RELEASE_VERSION_INPUT" - else - release_version="$(sed -n 's/^VERSION_NAME=//p' gradle.properties)" - release_version="${release_version%-SNAPSHOT}" - fi - else - if [[ ! "$RELEASE_TAG" =~ ^v([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then - echo "Release tag must have the form vX.Y.Z: $RELEASE_TAG" >&2 - exit 1 - fi - release_version="${BASH_REMATCH[1]}.${BASH_REMATCH[2]}.${BASH_REMATCH[3]}" + if [[ ! "$RELEASE_TAG" =~ ^v([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then + echo 'Expected a release tag such as v0.1.0.' >&2 + exit 1 + fi + version="$(sed -n 's/^VERSION_NAME=//p' gradle.properties)" + if [[ "$version" != "${RELEASE_TAG#v}" || "$version" =~ -[Ss][Nn][Aa][Pp][Ss][Hh][Oo][Tt]$ ]]; then + echo 'Release tag must match a non-SNAPSHOT VERSION_NAME.' >&2 + exit 1 fi - configured_version="$(sed -n 's/^VERSION_NAME=//p' gradle.properties)" - configured_base="${configured_version%-SNAPSHOT}" - if [[ "$configured_base" != "$release_version" ]]; then - echo "Release version ($release_version) must match VERSION_NAME ($configured_version)" >&2 + coordinates="$(sed -n 's/.*maven_coordinates = "com.uber.ussi:ussi:\([^"]*\)".*/\1/p' BUILD.bazel)" + if [[ "$coordinates" != "$version" ]]; then + echo 'BUILD.bazel maven_coordinates must match VERSION_NAME.' >&2 exit 1 fi - echo "RELEASE_VERSION=$release_version" >> "$GITHUB_ENV" + printf 'RELEASE_VERSION=%s\n' "$version" >> "$GITHUB_ENV" - name: Extract release notes run: | awk -v ver="$RELEASE_VERSION" ' - /^## / { if (found) exit; if (index($0, "## [" ver "]") == 1) { found=1; next } } + /^# / { if (found) exit; if ($0 == "# " ver) { found=1; next } } found ' CHANGELOG.md > release_notes.md - if [[ ! -s release_notes.md ]]; then - echo "Add a ## [$RELEASE_VERSION] section to CHANGELOG.md" >&2 + if ! grep -q '[^[:space:]]' release_notes.md; then + echo "Add a # $RELEASE_VERSION section with release notes to CHANGELOG.md" >&2 exit 1 fi - - name: Prepare release version on main - if: github.event_name == 'workflow_dispatch' - env: - GIT_USER_NAME: ${{ github.actor }} - GIT_USER_EMAIL: ${{ format('{0}+{1}@users.noreply.github.com', github.actor_id, github.actor) }} - run: | - sed -i -E "s/^VERSION_NAME=.*/VERSION_NAME=${RELEASE_VERSION}/" gradle.properties - sed -i -E "s/maven_coordinates = \"com.uber.ussi:ussi:[^\"]+\"/maven_coordinates = \"com.uber.ussi:ussi:${RELEASE_VERSION}\"/" BUILD.bazel - if git diff --quiet; then - echo "VERSION_NAME and BUILD.bazel already at release version ${RELEASE_VERSION}" - exit 0 - fi - git config user.name "$GIT_USER_NAME" - git config user.email "$GIT_USER_EMAIL" - git commit -am "chore: release ${RELEASE_VERSION} [skip ci]" - git push origin HEAD:main - - name: Set up JDK - uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v4.7.0 + uses: actions/setup-java@v6 with: + distribution: temurin java-version: '21' - distribution: 'temurin' - - name: Setup Gradle - uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v4.4.0 + - name: Set up Gradle and validate wrapper + uses: gradle/actions/setup-gradle@v6 with: cache-disabled: true - - name: Test with Gradle - run: ./gradlew test --no-daemon - - - name: Publish and release to Maven Central + - name: Publish env: - ORG_GRADLE_PROJECT_RELEASE_SIGNING_ENABLED: 'true' ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.MAVEN_CENTRAL_USER_TOKEN_USERNAME }} ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.MAVEN_CENTRAL_USER_TOKEN_PASSWORD }} ORG_GRADLE_PROJECT_signingInMemoryKeyId: ${{ secrets.PGP_PRIVATE_KEY_ID }} ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.PGP_SIGNING_KEY_PRIVATE_KEY }} ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.PGP_SIGNING_KEY_PASSWORD }} - run: ./gradlew publishAndReleaseToMavenCentral --no-daemon + run: ./gradlew publishToMavenCentral --no-daemon - name: Create GitHub Release - uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v2.3.3 - with: - tag_name: v${{ env.RELEASE_VERSION }} - name: ${{ env.RELEASE_VERSION }} - body_path: release_notes.md env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} + RELEASE_TAG: ${{ github.ref_name }} + run: | + gh release create "$RELEASE_TAG" --repo "$GITHUB_REPOSITORY" --verify-tag \ + --title "$RELEASE_VERSION" --notes-file release_notes.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 21783d6..301beee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,8 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). -## [0.1.0] - 2026-10-16 +# 0.1.0 -### Added +Initial open-source release of Uber Similarity Search Index (USSI). -- Initial open-source release of Uber Similarity Search Index (USSI). -- Gradle and Bazel build support; Maven coordinates `com.uber.ussi:ussi`. +Published Maven coordinates: `com.uber.ussi:ussi:0.1.0`. diff --git a/RELEASING.md b/RELEASING.md index 6bdc0ad..144c27d 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -7,35 +7,67 @@ Published artifacts use **`com.uber.ussi:ussi`**. ## CI and local builds - **Pull requests and main:** Bazel tests (`.github/workflows/tests.yml`). -- **Releases:** `.github/workflows/release.yml` (Gradle `publishAndReleaseToMavenCentral`, GitHub Release, changelog). +- **Releases:** [Release to Maven Central](.github/workflows/release.yml) on version tags. Both build systems share the same `src/main/java` and `src/test/java` trees. Bazel remains supported for day-to-day development; Gradle is the supported release path for Uber open-source JVM libraries. Gradle requires JDK 21 or later. On Uber-managed machines that inject an internal Artifactory `init.gradle`, use a clean `GRADLE_USER_HOME` (for example `GRADLE_USER_HOME=$PWD/.gradle-home ./gradlew test`) so dependencies resolve from Maven Central only. -## Version files +## Release process -Keep these in sync: +Creating and pushing a release tag to `uber/ussi` automatically triggers the +[Release to Maven Central workflow](.github/workflows/release.yml). Merging a PR +or pushing a commit to `main` does not trigger a release. -- `gradle.properties` — `VERSION_NAME` (use `-SNAPSHOT` on `main` between releases) -- `BUILD.bazel` — `maven_coordinates` on `//:src_main` -- `CHANGELOG.md` — `## [X.Y.Z]` section for each release +The workflow signs, uploads, and releases `com.uber.ussi:ussi` to Maven Central. +The Gradle Maven Publish plugin's `publishToMavenCentral` task handles both upload +and release because `mavenCentralAutomaticPublishing=true` is set in +`gradle.properties`. After publishing, the workflow creates a GitHub Release for +the tag using the matching `CHANGELOG.md` section as its release notes. The tagged +commit should already have passed CI on `main`. -## Cut a release (recommended: workflow dispatch) +## Prepare and publish a release -1. On `main`, set `VERSION_NAME` to the next release with a `-SNAPSHOT` suffix (for example `0.2.0-SNAPSHOT`) and align `BUILD.bazel`. -2. Add a `## [0.2.0]` section to `CHANGELOG.md`. -3. Merge to `main`. -4. Run **Release to Maven Central** → **Run workflow** on `main` (optional `release_version` override). - - CI strips `-SNAPSHOT`, commits the release version to `gradle.properties` and `BUILD.bazel`, publishes to Maven Central, and creates the GitHub Release + tag. -5. Confirm the artifact on [Maven Central](https://central.sonatype.com/artifact/com.uber.ussi/ussi). -6. Open a follow-up PR bumping `VERSION_NAME` and `BUILD.bazel` to the next `-SNAPSHOT` (branch protection may block the workflow from doing this automatically). +1. Set `VERSION_NAME` in `gradle.properties` to the release version without + `-SNAPSHOT`, for example `0.1.0`. +2. Set `maven_coordinates` on `//:src_main` in `BUILD.bazel` to the same version. +3. Add a matching `# 0.1.0` section with release notes to `CHANGELOG.md`. +4. Commit with `Prepare for release 0.1.0.` and merge the PR into `main`. +5. Tag the release commit and push the tag: -## Cut a release (tag push) + ```sh + git switch main + git pull --ff-only origin main + git tag -a v0.1.0 -m "Version 0.1.0" + git push origin v0.1.0 + ``` -Alternatively, after `VERSION_NAME` and `BUILD.bazel` already hold the release version (no `-SNAPSHOT`): +6. Follow **Release to Maven Central** in GitHub Actions. The workflow validates + the tag, version, Bazel coordinates, and changelog before publishing, then + creates the GitHub Release. Maven Central may take additional time to make a + released version available. +7. Prepare the next development version, such as `0.2.0-SNAPSHOT`, in + `gradle.properties` and `BUILD.bazel`, and submit it in a separate PR. -1. Push annotated tag `vX.Y.Z`. -2. The same workflow tests, publishes, and creates the GitHub Release. +Release tags use the form `vX.Y.Z`. The tag version (without the `v` prefix) must +exactly match `VERSION_NAME`, and snapshot versions are rejected. The workflow +does not change versions, create commits, or push tags. -If tag `vX.Y.Z` already exists on an older commit, move the tag after fixing the release workflow, or cut the next patch version. +## Retry a release + +Open the failed tag-push run of **Release to Maven Central** in GitHub Actions +and select **Re-run failed jobs**. Versions already released to Maven Central +cannot be overwritten; use a new version for changed artifacts. + +## Repository secrets + +These GitHub Actions secrets are configured at the Uber organization level for +`uber/ussi`: + +| Secret | Purpose | +| --- | --- | +| `MAVEN_CENTRAL_USER_TOKEN_USERNAME` | Central Portal user token username for `com.uber.ussi`. | +| `MAVEN_CENTRAL_USER_TOKEN_PASSWORD` | Central Portal user token password. | +| `PGP_SIGNING_KEY_PRIVATE_KEY` | ASCII-armored private signing key. | +| `PGP_PRIVATE_KEY_ID` | Signing subkey ID, if required. Optional. | +| `PGP_SIGNING_KEY_PASSWORD` | Private key passphrase. Optional for an unencrypted key. | diff --git a/gradle.properties b/gradle.properties index ce893e5..3b89b06 100644 --- a/gradle.properties +++ b/gradle.properties @@ -21,6 +21,7 @@ POM_DEVELOPER_NAME=Uber Technologies POM_DEVELOPER_URL=https://uber.com mavenCentralPublishing=true +mavenCentralAutomaticPublishing=true mavenCentralDeploymentValidation=PUBLISHED -SONATYPE_CLOSE_TIMEOUT_SECONDS=3600 +signAllPublications=true RELEASE_SIGNING_ENABLED=true From 6060738f5eff6df3532bbb6d2c2dba1a4268fd29 Mon Sep 17 00:00:00 2001 From: Ahmed Metwally Date: Fri, 23 Oct 2026 12:38:03 -0700 Subject: [PATCH 5/5] Reword CHANGELOG intro to match # X.Y.Z sections --- CHANGELOG.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 301beee..6826a04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,7 @@ # Changelog -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). +Release notes for each version use a top-level `# X.Y.Z` heading (matching the +release workflow and [RELEASING.md](RELEASING.md)). # 0.1.0