Skip to content

fix(ci): Update publishing url to ossrh-staging-api#300

Merged
unidevel merged 2 commits into
prestodb:masterfrom
unidevel:fix-release
Apr 24, 2026
Merged

fix(ci): Update publishing url to ossrh-staging-api#300
unidevel merged 2 commits into
prestodb:masterfrom
unidevel:fix-release

Conversation

@unidevel
Copy link
Copy Markdown
Contributor

No description provided.

@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai Bot commented Apr 24, 2026

Reviewer's Guide

Updates Maven Central publishing to use the new ossrh-staging-api endpoint and adds an automatic publishing Gradle task, while simplifying and adjusting the GitHub release workflow to align with the new publishing flow and tagging/versioning strategy.

Sequence diagram for CI release workflow and OSSRH staging API publishing

sequenceDiagram
    actor Developer
    participant GitHubActions
    participant GradleBuild
    participant SonatypeOSSRH

    Developer->>GitHubActions: Push to master / trigger release workflow
    GitHubActions->>GitHubActions: Determine release_version and next_version
    GitHubActions->>GitHubActions: Update build.gradle to release_version
    GitHubActions->>GitHubActions: Commit [release-action] release version
    GitHubActions->>GitHubActions: Create branch release-release_version and tag release_version

    GitHubActions->>GradleBuild: Run ./gradlew sign publish publishToMavenCentral
    GradleBuild->>SonatypeOSSRH: Publish artifacts to repository ossrh-staging-api

    GradleBuild->>SonatypeOSSRH: HTTP POST /manual/upload/defaultRepository/namespace
    Note right of GradleBuild: Gradle task publishToMavenCentral builds Authorization Bearer token from NEXUS_USERNAME and NEXUS_PASSWORD
    SonatypeOSSRH-->>GradleBuild: HTTP response (success or error)

    GradleBuild-->>GitHubActions: Build and publish result

    GitHubActions->>GitHubActions: Checkout master
    GitHubActions->>GitHubActions: Update build.gradle to next_version
    GitHubActions->>GitHubActions: Commit [release-action] prepare for next development iteration
    GitHubActions->>GitHubActions: Push master and tags to origin

    GitHubActions-->>Developer: Release job status and logs
Loading

Flow diagram for updated GitHub release workflow and versioning

flowchart TD
    A["Start release workflow"] --> B["Compute release_version from build.gradle
(SNAPSHOT stripped)"]
    B --> C["Get last_version and next_version
from tags and release_version"]

    C --> D["Update build.gradle to release_version"]
    D --> E["git add build.gradle"]
    E --> F["git commit -m '[release-action] release version release_version'"]

    F --> G["Create branch release-release_version"]
    G --> H["git tag -a release_version -m 'Release release_version'"]

    H --> I["Set up GPG key and Gradle properties"]
    I --> J["Run ./gradlew sign publish publishToMavenCentral"]

    J --> K["Gradle publishToMavenCentral task
POSTs to ossrh-staging-api"]

    K --> L{"Publishing successful?"}
    L -->|"No"| M["Fail workflow with GradleException"]
    L -->|"Yes"| N["git checkout master"]

    N --> O["Update build.gradle to next_version"]
    O --> P["git add build.gradle"]
    P --> Q["git commit -m '[release-action] prepare for next development iteration'"]

    Q --> R["git push origin master --tags"]
    R --> S["End release workflow"]
Loading

File-Level Changes

Change Details Files
Switch Maven repository configuration to the new Sonatype ossrh-staging-api endpoint and name.
  • Replace the legacy oss.sonatype.org staging deployment URL with the new ossrh-staging-api.central.sonatype.com endpoint
  • Assign an explicit repository name for the Maven repository configuration
build.gradle
Introduce a Gradle task to trigger automatic Maven Central publishing via the Sonatype staging API.
  • Register a new publishToMavenCentral task grouped under 'publishing' that depends on all subproject publish tasks
  • Within the task, read Nexus credentials and namespace from environment variables and construct a basic auth token
  • Call the Sonatype ossrh-staging-api manual upload endpoint with publishing_type=automatic using an HTTP POST with JSON headers
  • Handle HTTP responses by logging success details or throwing a GradleException on non-2xx responses
build.gradle
Refactor the GitHub release workflow to remove CHANGELOG generation, adjust version bumping strategy, and integrate the new Gradle publishing task.
  • Remove automatic CHANGELOG.md generation and the next_release_msg environment variable
  • Update the release-commit message to a machine-friendly '[release-action] release version ' format
  • Create a dedicated release branch per version before tagging, and later switch back to master for post-release changes
  • Move the next development version bump earlier in the workflow, committing it on master with a standardized commit message
  • Ensure Gradle publishing runs the new publishToMavenCentral task along with signing and publishing
  • Adjust final push step to push from master, including tags, after the branch/commit choreography
.github/workflows/release.yml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 2 issues, and left some high level feedback:

  • In the new publishToMavenCentral task, the Authorization header uses a Base64-encoded username:password with scheme Bearer; if this endpoint expects HTTP Basic auth, the header should be Authorization: Basic <base64-creds> instead to match standard Sonatype usage.
  • The publishToMavenCentral URL connection does not set connect or read timeouts, so a hanging Sonatype endpoint could stall the Gradle build; consider configuring reasonable timeouts on the URLConnection.
  • The workflow creates a release-${{ env.release_version }} branch but never pushes it, so the release branch exists only locally in CI; if you intend to keep release branches in the remote repo, add a push for that branch before the final git push origin master --tags.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In the new `publishToMavenCentral` task, the Authorization header uses a Base64-encoded `username:password` with scheme `Bearer`; if this endpoint expects HTTP Basic auth, the header should be `Authorization: Basic <base64-creds>` instead to match standard Sonatype usage.
- The `publishToMavenCentral` URL connection does not set connect or read timeouts, so a hanging Sonatype endpoint could stall the Gradle build; consider configuring reasonable timeouts on the `URLConnection`.
- The workflow creates a `release-${{ env.release_version }}` branch but never pushes it, so the release branch exists only locally in CI; if you intend to keep release branches in the remote repo, add a push for that branch before the final `git push origin master --tags`.

## Individual Comments

### Comment 1
<location path="build.gradle" line_range="221-227" />
<code_context>
+        def username = System.getenv('NEXUS_USERNAME')
+        def password = System.getenv('NEXUS_PASSWORD')
+        def namespace = System.getenv('NEXUS_NAMESPACE') ?: "io.prestodb"
+        def credentials = "${username}:${password}"
+        def token = credentials.bytes.encodeBase64().toString()
+
+        def url = "https://ossrh-staging-api.central.sonatype.com/manual/upload/defaultRepository/${namespace}?publishing_type=automatic"
+        def connection = new URL(url).openConnection()
+        connection.setRequestMethod('POST')
+        connection.setRequestProperty('Authorization', "Bearer ${token}")
+        connection.setRequestProperty('Content-Type', 'application/json')
+        connection.setRequestProperty('Accept', 'application/json')
</code_context>
<issue_to_address>
**issue (bug_risk):** Authorization header likely should use Basic auth instead of Bearer for Sonatype staging API.

This endpoint usually requires HTTP Basic auth with `Authorization: Basic <base64(username:password)>`. You correctly base64‑encode `username:password`, but then send it as a Bearer token, which is likely to cause 401/403. Update this to `connection.setRequestProperty('Authorization', "Basic ${token}")` or confirm the expected auth scheme in the Sonatype docs.
</issue_to_address>

### Comment 2
<location path="build.gradle" line_range="218-230" />
<code_context>
+        def token = credentials.bytes.encodeBase64().toString()
+
+        def url = "https://ossrh-staging-api.central.sonatype.com/manual/upload/defaultRepository/${namespace}?publishing_type=automatic"
+        def connection = new URL(url).openConnection()
+        connection.setRequestMethod('POST')
+        connection.setRequestProperty('Authorization', "Bearer ${token}")
+        connection.setRequestProperty('Content-Type', 'application/json')
+        connection.setRequestProperty('Accept', 'application/json')
+        connection.setDoOutput(true)
+
+        def responseCode = connection.getResponseCode()
</code_context>
<issue_to_address>
**suggestion (bug_risk):** HTTP connection lacks timeouts and minimal validation of required environment variables.

This manual HTTP call has no `connectTimeout`/`readTimeout` and also assumes `NEXUS_USERNAME`/`NEXUS_PASSWORD` are always set. If they’re missing, the call proceeds with `null:null`, and without timeouts a network issue could hang the build. Please add reasonable timeouts (e.g. 30s) and fail fast with a clear `GradleException` when required credentials are absent.

```suggestion
        def username = System.getenv('NEXUS_USERNAME')
        def password = System.getenv('NEXUS_PASSWORD')

        if (!username || !password) {
            throw new org.gradle.api.GradleException(
                "NEXUS_USERNAME and NEXUS_PASSWORD environment variables must be set to publish to Maven Central."
            )
        }

        def namespace = System.getenv('NEXUS_NAMESPACE') ?: "io.prestodb"
        def credentials = "${username}:${password}"
        def token = credentials.bytes.encodeBase64().toString()

        def url = "https://ossrh-staging-api.central.sonatype.com/manual/upload/defaultRepository/${namespace}?publishing_type=automatic"
        def connection = new URL(url).openConnection()
        connection.connectTimeout = 30_000
        connection.readTimeout = 30_000
        connection.setRequestMethod('POST')
        connection.setRequestProperty('Authorization', "Bearer ${token}")
        connection.setRequestProperty('Content-Type', 'application/json')
        connection.setRequestProperty('Accept', 'application/json')
        connection.setDoOutput(true)
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread build.gradle
Comment thread build.gradle
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Copy link
Copy Markdown
Member

@imjalpreet imjalpreet left a comment

Choose a reason for hiding this comment

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

Thanks, @unidevel.

@unidevel unidevel merged commit 86553fa into prestodb:master Apr 24, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants