Skip to content

ci: restore reliable Maven Central publishing - #824

Merged
jbeckwith-oai merged 6 commits into
mainfrom
codex/fix-sonatype-publishing
Jul 31, 2026
Merged

ci: restore reliable Maven Central publishing#824
jbeckwith-oai merged 6 commits into
mainfrom
codex/fix-sonatype-publishing

Conversation

@jbeckwith-oai

@jbeckwith-oai jbeckwith-oai commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Summary

  • restore Maven Central publishing to a normal top-level job bound directly to the protected publish environment
  • keep the release pipeline linear: select an immutable source, run compatibility, publish, then wait for public artifacts
  • support guarded retries of existing GitHub release tags without a reusable publishing workflow or helper scripts
  • verify every expected POM, binary, sources, and Javadoc artifact is public before reporting success

Root cause

#811 moved Maven Central publishing into a reusable workflow. The v4.46.0 and v4.47.0 runs reached a job named for the publish environment, but all four Sonatype/GPG values were empty at that boundary. Both runs failed during GPG import before Gradle publishing began.

The last successful release, v4.45.0, used a normal top-level publish job. This change returns to that proven secret boundary. It also closes the false-green gap where the Vanniktech task can return after Central Portal accepts an upload but before Maven Central serves it publicly.

Design

The workflow has three jobs:

  1. Select the source. Automatic releases use the release action's exact tag and SHA. A retry checks out refs/tags/<version> and verifies the tag, published GitHub release target, main ancestry, and Gradle version.
  2. Run the runtime compatibility matrix against that exact SHA.
  3. Publish that exact SHA from a normal job with environment: publish, then poll Maven Central for every expected POM, binary, sources, and Javadoc file.

Retries require an operator to confirm in Central Portal that the immutable version has no existing deployment. A single non-cancelling concurrency group prevents overlapping automatic releases and retries.

Recovery after merge

  1. Inspect Central Portal and confirm v4.46.0 has no existing deployment.
  2. Run Create releases manually from main with release_tag=v4.46.0 and check the confirmation input.
  3. Wait for the workflow to prove all four modules are completely public.
  4. Repeat for v4.47.0.

Do not retry a red post-upload run until its Central Portal deployment state is understood.

Addresses #823.

Validation

  • traced the last successful release and both failing release runs, including environment-secret resolution and Gradle invocation
  • Actionlint 1.7.12
  • Zizmor 1.28.0 pedantic audit: no findings
  • YAML parsing, embedded Bash parsing, and git diff --check
  • exact-tag validation against the real v4.46.0 and v4.47.0 GitHub releases
  • complete 16-file public-artifact poll against the known-good v4.45.0 release
  • signing-key import and ID extraction with a fresh encrypted GPG key
  • full local Maven publication for both missing tags under JDK 21 / Gradle 8.12
  • verified 32 non-empty primary POM, binary, sources, and Javadoc files across v4.46.0 and v4.47.0
  • thermo-nuclear maintainability review

Copilot AI review requested due to automatic review settings July 30, 2026 22:53

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR repairs Maven Central (Sonatype) publishing after CI was refactored to use a reusable workflow, ensuring the publish path receives the required protected secrets and that both compatibility checks and publishing run from the same validated source ref.

Changes:

  • Pass secrets into the Sonatype reusable workflow via secrets: inherit from the caller workflows.
  • Add a “validate source ref” job and thread the validated ref through runtime-compatibility and publish checkouts.
  • Add fail-fast credential validation for required Sonatype/GPG secrets and allow the manual recovery workflow to publish an existing release tag.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
.github/workflows/runtime-compatibility.yml Adds a workflow_call input to run runtime compatibility against a caller-provided git ref.
.github/workflows/publish-sonatype.yml Extends manual publishing to accept a required existing release tag and forwards it to the reusable workflow, inheriting secrets.
.github/workflows/publish-sonatype-reusable.yml Adds a validate job to select the source ref, gates publishing on runtime compatibility, validates credentials early, and checks out the validated ref for publishing.
.github/workflows/create-releases.yml Ensures the automated release workflow opts into secret inheritance when calling the reusable Sonatype publish workflow.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/workflows/publish-sonatype-reusable.yml Outdated
@jbeckwith-oai
jbeckwith-oai marked this pull request as ready for review July 30, 2026 23:51
@jbeckwith-oai
jbeckwith-oai requested a review from a team as a code owner July 30, 2026 23:51
@openai-sdks

openai-sdks Bot commented Jul 30, 2026

Copy link
Copy Markdown

OkTest Summary

237/237 SDK tests passed in 16.346s for Java SDK PR #824.

Test results — 42 files
Test Result Time
tests/chat-completions-complex-body.test.ts ✅ Passed 309ms
tests/chat-completions-create.test.ts ✅ Passed 554ms
tests/chat-completions-stream.test.ts ✅ Passed 377ms
tests/files-content-binary.test.ts ✅ Passed 325ms
tests/files-create-multipart.test.ts ✅ Passed 297ms
tests/files-list-pagination.test.ts ✅ Passed 254ms
tests/initialize-config.test.ts ✅ Passed 235ms
tests/instance-isolation.test.ts ✅ Passed 210ms
tests/models-list.test.ts ✅ Passed 176ms
tests/responses-background-lifecycle.test.ts ✅ Passed 639ms
tests/responses-body-method-errors.test.ts ✅ Passed 564ms
tests/responses-cancel-timeout.test.ts ✅ Passed 288ms
tests/responses-cancel.test.ts ✅ Passed 320ms
tests/responses-compact-retries.test.ts ✅ Passed 455ms
tests/responses-compact.test.ts ✅ Passed 338ms
tests/responses-create-advanced-stream.test.ts ✅ Passed 285ms
tests/responses-create-advanced.test.ts ✅ Passed 1.12s
tests/responses-create-disconnect.test.ts ✅ Passed 959ms
tests/responses-create-errors.test.ts ✅ Passed 369ms
tests/responses-create-malformed-api-responses.test.ts ✅ Passed 302ms
tests/responses-create-retries.test.ts ✅ Passed 300ms
tests/responses-create-stream-failures.test.ts ✅ Passed 323ms
tests/responses-create-stream-timeout.test.ts ✅ Passed 234ms
tests/responses-create-stream-wire.test.ts ✅ Passed 6.32s
tests/responses-create-stream.test.ts ✅ Passed 604ms
tests/responses-create-terminal-states.test.ts ✅ Passed 335ms
tests/responses-create-timeout.test.ts ✅ Passed 247ms
tests/responses-create.test.ts ✅ Passed 277ms
tests/responses-delete.test.ts ✅ Passed 289ms
tests/responses-input-items-errors.test.ts ✅ Passed 267ms
tests/responses-input-items-list.test.ts ✅ Passed 291ms
tests/responses-input-items-options.test.ts ✅ Passed 512ms
tests/responses-input-tokens-count-timeout.test.ts ✅ Passed 252ms
tests/responses-input-tokens-count.test.ts ✅ Passed 467ms
tests/responses-malformed-inputs.test.ts ✅ Passed 5.128s
tests/responses-not-found-errors.test.ts ✅ Passed 391ms
tests/responses-parse.test.ts ✅ Passed 499ms
tests/responses-retrieve-retries.test.ts ✅ Passed 268ms
tests/responses-retrieve.test.ts ✅ Passed 373ms
tests/responses-stored-method-errors.test.ts ✅ Passed 1.048s
tests/retry-behavior.test.ts ✅ Passed 3.453s
tests/sdk-error-shape.test.ts ✅ Passed 436ms

View OkTest run #30601848795

SDK merge (93072ab24854) · head (64e62c7feb6c) · base (3c146dde510e) · OkTest (91635c6a2723)

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fa4797e18a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/publish-sonatype-reusable.yml Outdated
Copilot AI review requested due to automatic review settings July 31, 2026 01:37
@jbeckwith-oai jbeckwith-oai changed the title fix(ci): restore Sonatype publishing fix(ci): make Maven Central releases verifiable and recoverable Jul 31, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: db6b0c8bef

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/scripts/validate-release-source.sh Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Comment thread .github/workflows/create-releases.yml Outdated
Copilot AI review requested due to automatic review settings July 31, 2026 02:05

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.

Copilot AI review requested due to automatic review settings July 31, 2026 02:40
@jbeckwith-oai jbeckwith-oai changed the title fix(ci): make Maven Central releases verifiable and recoverable fix(ci): restore reliable Maven Central publishing Jul 31, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

Suppressed comments (4)

.github/workflows/runtime-compatibility.yml:69

  • Same issue as above: the checkout ref uses inputs.ref directly, which can break schedule runs. Gate inputs.ref usage on the event type.
          ref: ${{ inputs.ref || github.sha }}

.github/workflows/create-releases.yml:40

  • The release job is bound to the protected publish environment even though it only selects/validates the source. This expands the publish-secret boundary earlier than necessary and can also block automatic releases if the environment requires approval. Bind environment: publish only to the actual publish job.
    if: github.ref == 'refs/heads/main' && github.repository == 'openai/openai-java'
    runs-on: ubuntu-24.04
    timeout-minutes: 15
    environment: publish
    outputs:

.github/workflows/create-releases.yml:185

  • The GraalVM native-image file check fails silently (no error output) when the directory is missing/empty, which makes release failures harder to diagnose. Emit a clear ::error:: message (matching other steps in this workflow) before exiting non-zero.
      - name: Check generated GraalVM files
        run: |
          directory="openai-java-core/src/main/resources/META-INF/native-image"
          [[ -d "$directory" && -n "$(ls -A "$directory")" ]]

.github/workflows/runtime-compatibility.yml:37

  • inputs.* is only guaranteed to be available for workflow_call/workflow_dispatch. Since this workflow also runs on schedule, referencing inputs.ref directly can fail on scheduled runs. Gate the inputs.ref access on github.event_name == 'workflow_call'.

This issue also appears on line 69 of the same file.

          ref: ${{ inputs.ref || github.sha }}

Copilot AI review requested due to automatic review settings July 31, 2026 03:06

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Suppressed comments (3)

.github/workflows/runtime-compatibility.yml:70

  • Same as above: the checkout ref: expression uses inputs.ref in a workflow that can run on schedule. Guard inputs.ref behind a workflow_call check so scheduled runs reliably fall back to github.sha.
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
        with:
          persist-credentials: false
          ref: ${{ inputs.ref || github.sha }}

.github/workflows/create-releases.yml:40

  • environment: publish is set on the release (source selection) job. If the publish environment is protected, this will force approvals / environment gating before the unprivileged validation + source selection steps and also makes the publish secrets available earlier than necessary. Consider removing the environment binding from this job and keeping it only on the actual Maven Central publish job.
    runs-on: ubuntu-24.04
    timeout-minutes: 15
    environment: publish
    outputs:

.github/workflows/create-releases.yml:244

  • The Maven Central polling step only waits for *.pom and the primary *.jar. This can still report success while -sources.jar / -javadoc.jar are not yet publicly served, even though the publishing plugin config enables both (buildSrc/src/main/kotlin/openai.publish.gradle.kts:37-42). To fully close the “false green” gap, include those jars in the poll set.
            for artifact in $MAVEN_ARTIFACTS; do
              for extension in pom jar; do
                url="$MAVEN_CENTRAL_BASE_URL/$artifact/$version/$artifact-$version.$extension"
                if ! curl --fail --silent --show-error --head --location \
                  --connect-timeout 10 --max-time 30 "$url" >/dev/null; then

Comment thread .github/workflows/runtime-compatibility.yml
Copilot AI review requested due to automatic review settings July 31, 2026 03:32

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

Suppressed comments (1)

.github/workflows/create-releases.yml:40

  • jobs.release is bound to the protected publish environment even though it only selects/validates the source and may exit without publishing (e.g., scheduled/push runs where releases_created is false). If the environment requires approvals, this will block or require manual approval for non-publishing runs and expands the protected-environment scope beyond the actual publication step. Consider keeping environment: publish only on the publish job (and any steps that truly need those secrets).
    timeout-minutes: 15
    environment: publish
    outputs:

@jbeckwith-oai jbeckwith-oai changed the title fix(ci): restore reliable Maven Central publishing ci: restore reliable Maven Central publishing Jul 31, 2026
@jbeckwith-oai
jbeckwith-oai merged commit a162e07 into main Jul 31, 2026
14 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.

3 participants