Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,71 @@ jobs:
chmod +x "$BASE_DETECTOR"
"$BASE_DETECTOR" "$BASE_COMMIT"

version_support_matrix:
name: CI / version support matrix
runs-on: ubuntu-24.04
timeout-minutes: 5

outputs:
runtime-matrix: ${{ steps.matrix.outputs.runtime-matrix }}

steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false

- name: Set up Java
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
distribution: temurin
java-version: 21

- name: Set up Gradle
uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2

- name: Read version support policy
id: matrix
run: |
./scripts/gradle generateVersionSupportMatrix -PversionSupportMatrix=pull-request
echo "runtime-matrix=$(< build/version-support-matrix.json)" >> "$GITHUB_OUTPUT"

runtime_compatibility:
name: CI / runtime compatibility / Java ${{ matrix.java }}
needs: version_support_matrix
runs-on: ubuntu-24.04
timeout-minutes: 20

strategy:
fail-fast: false
matrix:
java: ${{ fromJSON(needs.version_support_matrix.outputs.runtime-matrix) }}

steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false

- name: Set up consumer Java
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
distribution: temurin
java-version: ${{ matrix.java }}

- name: Set up build Java
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
distribution: temurin
java-version: 21

- name: Set up Gradle
uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2

- name: Run consumer compatibility smoke test
run: >-
./scripts/gradle
:openai-java-runtime-compatibility:runRuntimeCompatibility
-PruntimeJavaVersion=${{ matrix.java }}

required:
name: CI / required
if: always()
Expand All @@ -146,6 +211,7 @@ jobs:
- build
- test
- api_compatibility
- runtime_compatibility
runs-on: ubuntu-24.04
timeout-minutes: 5

Expand All @@ -159,6 +225,7 @@ jobs:
BUILD_RESULT: ${{ needs.build.result }}
TEST_RESULT: ${{ needs.test.result }}
API_COMPATIBILITY_RESULT: ${{ needs.api_compatibility.result }}
RUNTIME_COMPATIBILITY_RESULT: ${{ needs.runtime_compatibility.result }}
run: |
set -euo pipefail

Expand All @@ -178,6 +245,8 @@ jobs:
if [[ "$EVENT_NAME" == "pull_request" && "$API_COMPATIBILITY_RESULT" != "success" ]]; then
failed_jobs+=("API compatibility: $API_COMPATIBILITY_RESULT")
fi
[[ "$RUNTIME_COMPATIBILITY_RESULT" == "success" ]] ||
failed_jobs+=("runtime compatibility: $RUNTIME_COMPATIBILITY_RESULT")

if (( ${#failed_jobs[@]} > 0 )); then
printf 'Required CI job did not succeed: %s\n' "${failed_jobs[@]}"
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/publish-sonatype-reusable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,13 @@ concurrency:
cancel-in-progress: false

jobs:
runtime_compatibility:
name: Publish / runtime compatibility
uses: ./.github/workflows/runtime-compatibility.yml

publish:
name: Publish / Sonatype
needs: runtime_compatibility
runs-on: ubuntu-24.04
timeout-minutes: 60
environment: publish
Expand Down
82 changes: 82 additions & 0 deletions .github/workflows/runtime-compatibility.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Exercises representative consumer entry points on every supported JVM. It runs nightly to catch
# ecosystem drift and is reusable so automated and manual publications are gated by the same matrix.
name: Runtime compatibility

on:
workflow_call:
schedule:
- cron: '0 7 * * *'
workflow_dispatch:
Comment thread
jbeckwith-oai marked this conversation as resolved.

permissions:
contents: read

concurrency:
group: runtime-compatibility-${{ github.ref }}
cancel-in-progress: false

jobs:
version_support_matrix:
name: Runtime compatibility / version support matrix
runs-on: ubuntu-24.04
timeout-minutes: 5

outputs:
runtime-matrix: ${{ steps.matrix.outputs.runtime-matrix }}

steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false

- name: Set up Java
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
distribution: temurin
java-version: 21

- name: Set up Gradle
uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2

- name: Read version support policy
id: matrix
run: |
./scripts/gradle generateVersionSupportMatrix -PversionSupportMatrix=full
echo "runtime-matrix=$(< build/version-support-matrix.json)" >> "$GITHUB_OUTPUT"

runtime_compatibility:
name: Runtime compatibility / Java ${{ matrix.java }}
needs: version_support_matrix
runs-on: ubuntu-24.04
timeout-minutes: 20

strategy:
fail-fast: false
matrix:
java: ${{ fromJSON(needs.version_support_matrix.outputs.runtime-matrix) }}

steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false

- name: Set up consumer Java
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
distribution: temurin
java-version: ${{ matrix.java }}

- name: Set up build Java
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
distribution: temurin
java-version: 21

- name: Set up Gradle
uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2

- name: Run consumer compatibility smoke test
run: >-
./scripts/gradle
:openai-java-runtime-compatibility:runRuntimeCompatibility
-PruntimeJavaVersion=${{ matrix.java }}
16 changes: 14 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@

## Setting up the environment

This repository uses [Gradle](https://gradle.org/) with Kotlin DSL for building and dependency management. The SDK requires Java 8, but development requires JDK 21 for the Kotlin toolchain.
This repository uses [Gradle](https://gradle.org/) with Kotlin DSL for building and dependency
management. The framework-neutral SDK requires Java 8, while development requires JDK 21 for the
Kotlin toolchain. See the [Java version support policy](docs/version-support-policy.md) for
artifact-level runtime, framework, lifecycle, and release rules.

## Project structure

The SDK consists of three artifacts:
The SDK's primary artifacts are:

- `openai-java-core`
- Contains core SDK logic
Expand All @@ -18,6 +21,15 @@ The SDK consists of three artifacts:
- `openai-java`
- Depends on and exposes the APIs of both `openai-java-core` and `openai-java-client-okhttp`
- Does not have its own logic
- `openai-java-bedrock`
- Adds optional Amazon Bedrock authentication and credential-provider integration
- `openai-java-spring-boot-starter`
- Provides the legacy Spring Boot 2 integration
- Is retained to verify the final 4.45.0 release, but is OpenAI EOL and no longer published

`openai-java-runtime-compatibility` is a non-published fixture that exercises representative
behavior for each supported artifact on an isolated runtime classpath. Its JVM matrix and each
artifact's eligibility on a given JVM come from `gradle/version-support.properties`.

## Modifying or adding code

Expand Down
24 changes: 16 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ The REST API documentation can be found on [platform.openai.com](https://platfor

<!-- x-release-please-start-version -->

[_Try `openai-java-spring-boot-starter` if you're using Spring Boot!_](#spring-boot)

### Gradle

```kotlin
Expand All @@ -41,7 +39,8 @@ implementation("com.openai:openai-java:4.45.0")

## Requirements

This library requires Java 8 or later.
The framework-neutral SDK artifacts require Java 8 or later. Runtime floors and lifecycle states
are declared per artifact in the [Java version support policy](docs/version-support-policy.md).

## Usage

Expand Down Expand Up @@ -1453,11 +1452,17 @@ GraalVM should automatically detect and use the published metadata, but [manual

## Spring Boot

If you're using Spring Boot, then you can use the SDK's [Spring Boot starter](https://docs.spring.io/spring-boot/docs/2.7.18/reference/htmlsingle/#using.build-systems.starters) to simplify configuration and get set up quickly.
> [!WARNING]
> `openai-java-spring-boot-starter` targets Spring Boot 2.7 and is OpenAI EOL as of 2026-07-27.
> Version 4.45.0 is the final supported, tested, and published release. The artifact remains
> downloadable but receives no fixes, testing, or compatibility support. See the
> [Spring Boot 2 EOL decision and migration path](docs/spring-boot-2-eol.md). New Spring
> applications should depend on `openai-java` directly and provide an `OpenAIClient` bean until a
> supported, generation-specific integration is available.

### Installation
Existing Spring Boot 2 applications can use the legacy starter to simplify configuration.

<!-- x-release-please-start-version -->
### Installation

#### Gradle

Expand All @@ -1475,8 +1480,6 @@ implementation("com.openai:openai-java-spring-boot-starter:4.45.0")
</dependency>
```

<!-- x-release-please-end -->

### Configuration

The [client's environment variable options](#client-configuration) can be configured in [`application.properties` or `application.yml`](https://docs.spring.io/spring-boot/how-to/properties-and-configuration.html).
Expand Down Expand Up @@ -1961,6 +1964,11 @@ This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) con
1. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_
2. Changes that we do not expect to impact the vast majority of users in practice.

Those exceptions do not apply to raising a supported JVM or JDK API floor, changing an integration's
framework generation, removing a published artifact, or removing a transitive dependency that
consumers may rely on; those changes require a major release. Announcing EOL without removing or
changing the last available artifact may be a minor release.

We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.

We are keen for your feedback; please open an [issue](https://www.github.com/openai/openai-java/issues) with questions, bugs, or suggestions.
78 changes: 78 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
import com.openai.gradle.GenerateVersionSupportMatrixTask
import com.openai.gradle.VersionSupportPolicy
import com.openai.gradle.VerifyVersionSupportPolicyTask
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.api.tasks.SourceSetContainer
import org.gradle.api.tasks.compile.JavaCompile
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

buildscript {
dependencies {
constraints {
Expand Down Expand Up @@ -56,6 +64,76 @@ subprojects {
apply(plugin = "org.jetbrains.dokka")
}

val versionSupportFile = layout.projectDirectory.file("gradle/version-support.properties")
val versionSupport = VersionSupportPolicy.load(versionSupportFile.asFile)

tasks.register<GenerateVersionSupportMatrixTask>("generateVersionSupportMatrix") {
group = "verification"
description = "Generates a CI runtime matrix from the version support policy."

policyFile.set(versionSupportFile)
mode.set(providers.gradleProperty("versionSupportMatrix"))
outputFile.set(layout.buildDirectory.file("version-support-matrix.json"))
}

tasks.register("verifyVersionSupportPolicy") {
group = "verification"
description = "Verifies published artifact runtime floors and lifecycle declarations."

inputs.file(versionSupportFile)
dependsOn(versionSupport.artifacts.keys.map { ":$it:verifyVersionSupportPolicy" })
}

subprojects {
val artifactName = name
val artifactSupport = versionSupport.artifacts[artifactName]

pluginManager.withPlugin("openai.publish") {
checkNotNull(artifactSupport) {
"$artifactName is published but missing from ${versionSupportFile.asFile}"
}
}

if (artifactSupport != null) {
pluginManager.withPlugin("java") {
val java = extensions.getByType(JavaPluginExtension::class.java)
val mainSourceSet = extensions.getByType(SourceSetContainer::class.java).getByName("main")
val compileJava = tasks.named<JavaCompile>("compileJava")

val verify =
tasks.register<VerifyVersionSupportPolicyTask>("verifyVersionSupportPolicy") {
group = "verification"
description =
"Verifies $artifactName against its declared version support policy."

this.artifactName.set(artifactName)
runtimeFloor.set(artifactSupport.runtime)
lifecycle.set(artifactSupport.lifecycle.propertyValue)
requiredBuildJdk.set(versionSupport.buildJdk)
configuredBuildJdk.set(java.toolchain.languageVersion.map { it.asInt() })
sourceCompatibility.set(java.sourceCompatibility.majorVersion.toInt())
Comment thread
jbeckwith-oai marked this conversation as resolved.
targetCompatibility.set(java.targetCompatibility.majorVersion.toInt())
javaRelease.set(compileJava.flatMap { it.options.release })
classFiles.from(mainSourceSet.output.classesDirs)

dependsOn(tasks.named("classes"))
}

pluginManager.withPlugin("org.jetbrains.kotlin.jvm") {
val compileKotlin = tasks.named<KotlinCompile>("compileKotlin")
verify.configure {
kotlinJvmTarget.set(
compileKotlin.flatMap { it.compilerOptions.jvmTarget }.map { it.target }
)
kotlinFreeCompilerArgs.set(
compileKotlin.flatMap { it.compilerOptions.freeCompilerArgs }
)
}
}
}
}
}

// Avoid race conditions between `dokkaJavadocCollector` and `dokkaJavadocJar` tasks
tasks.named("dokkaJavadocCollector").configure {
subprojects.flatMap { it.tasks }
Expand Down
7 changes: 7 additions & 0 deletions buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,11 @@ repositories {
dependencies {
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.20")
implementation("com.vanniktech:gradle-maven-publish-plugin:0.28.0")

testImplementation(kotlin("test"))
testImplementation("org.junit.jupiter:junit-jupiter:5.9.3")
}

tasks.test {
useJUnitPlatform()
}
Loading
Loading