Skip to content
Open
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
30 changes: 20 additions & 10 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
lint:
timeout-minutes: 15
name: lint
runs-on: 'ubuntu-latest'
runs-on: ${{ github.repository == 'anthropics/anthropic-sdk-java' && 'ubuntu-latest-16core' || 'ubuntu-latest-16-core' }}
if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork)

steps:
Expand All @@ -31,21 +31,25 @@ jobs:
java-version: |
8
21
cache: gradle

- name: Set up Gradle
uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3
with:
# Required for configuration-cache data to be saved/restored across CI runs.
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}

- name: Run lints
run: ./scripts/lint

build:
timeout-minutes: 15
# The first run on a fresh cache compiles everything and generates all documentation, which
# does not fit in 15 minutes; cached runs are much faster.
timeout-minutes: 30
name: build
permissions:
contents: read
id-token: write
runs-on: 'ubuntu-latest'
runs-on: ${{ github.repository == 'anthropics/anthropic-sdk-java' && 'ubuntu-latest-16core' || 'ubuntu-latest-16-core' }}
if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork)

steps:
Expand All @@ -58,10 +62,12 @@ jobs:
java-version: |
8
21
cache: gradle

- name: Set up Gradle
uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3
with:
# Required for configuration-cache data to be saved/restored across CI runs.
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}

- name: Build SDK
run: ./scripts/build
Expand Down Expand Up @@ -94,7 +100,7 @@ jobs:
test:
timeout-minutes: 30
name: test
runs-on: 'ubuntu-latest'
runs-on: ${{ github.repository == 'anthropics/anthropic-sdk-java' && 'ubuntu-latest-16core' || 'ubuntu-latest-16-core' }}
if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
Expand All @@ -106,18 +112,20 @@ jobs:
java-version: |
8
21
cache: gradle

- name: Set up Gradle
uses: gradle/gradle-build-action@a8f75513eafdebd8141bd1cd4e30fcd194af8dfa # v2.12.0
uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3
with:
# Required for configuration-cache data to be saved/restored across CI runs.
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}

- name: Run tests
run: ./scripts/test

detect_breaking_changes_vs_main:
timeout-minutes: 15
name: detect-breaking-changes-vs-main
runs-on: ${{ github.repository == 'stainless-sdks/anthropic-java' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
runs-on: ${{ github.repository == 'anthropics/anthropic-sdk-java' && 'ubuntu-latest-16core' || 'ubuntu-latest-16-core' }}
if: |-
(github.event_name == 'push' &&
!startsWith(github.ref, 'refs/heads/release-please--')) ||
Expand All @@ -140,10 +148,12 @@ jobs:
java-version: |
8
21
cache: gradle

- name: Set up Gradle
uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3
with:
# Required for configuration-cache data to be saved/restored across CI runs.
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}

- name: Determine base SHA
run: |
Expand Down
5 changes: 2 additions & 3 deletions .github/workflows/create-releases.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
release:
name: release
if: github.ref == 'refs/heads/main' && github.repository == 'anthropics/anthropic-sdk-java'
runs-on: ubuntu-latest
runs-on: ubuntu-latest-16-core
environment: production-release

steps:
Expand All @@ -30,11 +30,10 @@ jobs:
java-version: |
8
21
cache: gradle

- name: Set up Gradle
if: ${{ steps.release.outputs.releases_created }}
uses: gradle/gradle-build-action@a8f75513eafdebd8141bd1cd4e30fcd194af8dfa # v2.12.0
uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3

- name: Publish to Sonatype
if: ${{ steps.release.outputs.releases_created }}
Expand Down
7 changes: 3 additions & 4 deletions .github/workflows/publish-sonatype.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
jobs:
publish:
name: publish
runs-on: ubuntu-latest
runs-on: ubuntu-latest-16-core

steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
Expand All @@ -19,10 +19,9 @@ jobs:
java-version: |
8
21
cache: gradle

- name: Set up Gradle
uses: gradle/gradle-build-action@a8f75513eafdebd8141bd1cd4e30fcd194af8dfa # v2.12.0
uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3

- name: Publish to Sonatype
run: |-
Expand All @@ -34,4 +33,4 @@ jobs:
SONATYPE_USERNAME: ${{ secrets.ANTHROPIC_SONATYPE_USERNAME || secrets.SONATYPE_USERNAME }}
SONATYPE_PASSWORD: ${{ secrets.ANTHROPIC_SONATYPE_PASSWORD || secrets.SONATYPE_PASSWORD }}
GPG_SIGNING_KEY: ${{ secrets.ANTHROPIC_SONATYPE_GPG_SIGNING_KEY || secrets.GPG_SIGNING_KEY }}
GPG_SIGNING_PASSWORD: ${{ secrets.ANTHROPIC_SONATYPE_GPG_SIGNING_PASSWORD || secrets.GPG_SIGNING_PASSWORD }}
GPG_SIGNING_PASSWORD: ${{ secrets.ANTHROPIC_SONATYPE_GPG_SIGNING_PASSWORD || secrets.GPG_SIGNING_PASSWORD }}
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "2.40.1"
".": "2.41.0"
}
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Changelog

## 2.41.0 (2026-06-11)

Full Changelog: [v2.40.1...v2.41.0](https://github.com/anthropics/anthropic-sdk-java/compare/v2.40.1...v2.41.0)

### Build System

* fix runners ([#66](https://github.com/anthropics/anthropic-sdk-java/issues/66)) ([19882bb](https://github.com/anthropics/anthropic-sdk-java/commit/19882bbada3e1ccbd1cb4fc10b011801cd0865fa))
* speed up local and CI builds ([#62](https://github.com/anthropics/anthropic-sdk-java/issues/62)) ([78de617](https://github.com/anthropics/anthropic-sdk-java/commit/78de617c06dc8fb31327ec4682649a613860b348))

## 2.40.1 (2026-06-09)

Full Changelog: [v2.40.0...v2.40.1](https://github.com/anthropics/anthropic-sdk-java/compare/v2.40.0...v2.40.1)
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Full documentation is available at **[platform.claude.com/docs/en/api/sdks/java]
### Gradle

```kotlin
implementation("com.anthropic:anthropic-java:2.40.1")
implementation("com.anthropic:anthropic-java:2.41.0")
```

### Maven
Expand All @@ -24,7 +24,7 @@ implementation("com.anthropic:anthropic-java:2.40.1")
<dependency>
<groupId>com.anthropic</groupId>
<artifactId>anthropic-java</artifactId>
<version>2.40.1</version>
<version>2.41.0</version>
</dependency>
```

Expand Down
31 changes: 24 additions & 7 deletions anthropic-java-proguard-test/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ val proguardJarPath = "${layout.buildDirectory.get()}/libs/${project.name}-${pro
val proguardJar by tasks.registering(proguard.gradle.ProGuardTask::class) {
group = "verification"
dependsOn(tasks.shadowJar)
notCompatibleWithConfigurationCache("ProGuard")

injars(tasks.shadowJar)
// Pass the archive path rather than the task itself: `Task` objects cannot
// be serialized to the configuration cache.
injars(tasks.shadowJar.get().archiveFile.get().asFile.absolutePath)
outjars(proguardJarPath)
printmapping("${layout.buildDirectory.get()}/proguard-mapping.txt")

Expand All @@ -57,40 +58,56 @@ val proguardJar by tasks.registering(proguard.gradle.ProGuardTask::class) {
val testProGuard by tasks.registering(JavaExec::class) {
group = "verification"
dependsOn(proguardJar)
notCompatibleWithConfigurationCache("ProGuard")

mainClass.set("com.anthropic.proguard.ProGuardCompatibilityTest")
classpath = files(proguardJarPath)

// This is a verification task with no file outputs, so rerun it only when
// the JAR changes.
outputs.upToDateWhen { true }
}

val r8JarPath = "${layout.buildDirectory.get()}/libs/${project.name}-${project.version}-r8.jar"
val r8Jar by tasks.registering(JavaExec::class) {
group = "verification"
dependsOn(tasks.shadowJar)
notCompatibleWithConfigurationCache("R8")

mainClass.set("com.android.tools.r8.R8")
classpath = buildscript.configurations["classpath"]

val proguardConfigs = listOf(
"./test.pro",
"../anthropic-java-core/src/main/resources/META-INF/proguard/anthropic-java-core.pro",
)

args = listOf(
"--release",
"--classfile",
"--output", r8JarPath,
"--lib", System.getProperty("java.home"),
"--pg-conf", "./test.pro",
"--pg-conf", "../anthropic-java-core/src/main/resources/META-INF/proguard/anthropic-java-core.pro",
"--pg-conf", proguardConfigs[0],
"--pg-conf", proguardConfigs[1],
"--pg-map-output", "${layout.buildDirectory.get()}/r8-mapping.txt",
tasks.shadowJar.get().archiveFile.get().asFile.absolutePath,
)

// `args` are not tracked as task inputs, so declare them explicitly for
// up-to-date checking.
inputs.files(tasks.shadowJar.map { it.archiveFile })
inputs.files(proguardConfigs)
outputs.file(r8JarPath)
}

val testR8 by tasks.registering(JavaExec::class) {
group = "verification"
dependsOn(r8Jar)
notCompatibleWithConfigurationCache("R8")

mainClass.set("com.anthropic.proguard.ProGuardCompatibilityTest")
classpath = files(r8JarPath)

// This is a verification task with no file outputs, so rerun it only when
// the JAR changes.
outputs.upToDateWhen { true }
}

tasks.test {
Expand Down
48 changes: 31 additions & 17 deletions anthropic-java/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,37 @@ dependencies {
api(project(":anthropic-java-client-okhttp"))
}

// Redefine `dokkaJavadoc` to:
// - Depend on the root project's task for merging the docs of all the projects
// - Forward that task's output to this task's output
tasks.named("dokkaJavadoc").configure {
actions.clear()
// This module's javadoc JAR must document the API of every module it
// re-exports, so add each module's main sources to this module's `dokkaJavadoc`
// task as extra source sets.
tasks.named<org.jetbrains.dokka.gradle.DokkaTask>("dokkaJavadoc").configure {
// Run after every other module's `dokkaJavadoc`: this task's documentation generation is by
// far the largest, and Dokka generates in-process, so running it concurrently with another
// large generation can exhaust the Gradle daemon's heap.
rootProject.subprojects
.filter { it.name != project.name }
.forEach { subproject -> mustRunAfter(subproject.tasks.matching { it.name == "dokkaJavadoc" }) }

val dokkaJavadocCollector = rootProject.tasks["dokkaJavadocCollector"]
dependsOn(dokkaJavadocCollector)

val outputDirectory = project.layout.buildDirectory.dir("dokka/javadoc")
doLast {
copy {
from(dokkaJavadocCollector.outputs.files)
into(outputDirectory)
duplicatesStrategy = DuplicatesStrategy.INCLUDE
}
dokkaSourceSets {
rootProject.subprojects
.filter { it.file("src/main/kotlin").exists() }
.sortedBy { it.name }
.forEach { subproject ->
register(subproject.name) {
sourceRoots.from(
listOf("src/main/kotlin", "src/main/java")
.map(subproject::file)
.filter { it.exists() }
)
// Resolve lazily: sibling projects may not be configured
// yet when this runs.
classpath.from(
project.provider {
subproject.configurations.getByName("compileClasspath")
}
)
jdkVersion.set(8)
}
}
}

outputs.dir(outputDirectory)
}
9 changes: 1 addition & 8 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ repositories {

allprojects {
group = "com.anthropic"
version = "2.40.1" // x-release-please-version
version = "2.41.0" // x-release-please-version
}

subprojects {
Expand All @@ -26,10 +26,3 @@ subprojects {
subprojects {
apply(plugin = "org.jetbrains.dokka")
}

// Avoid race conditions between `dokkaJavadocCollector` and `dokkaJavadocJar` tasks
tasks.named("dokkaJavadocCollector").configure {
subprojects.flatMap { it.tasks }
.filter { it.project.name != "anthropic-java" && it.name == "dokkaJavadocJar" }
.forEach { mustRunAfter(it) }
}
10 changes: 9 additions & 1 deletion buildSrc/src/main/kotlin/anthropic.java.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ tasks.withType<Test>().configureEach {

// Run tests in parallel to some degree.
maxParallelForks = (Runtime.getRuntime().availableProcessors() / 2).coerceAtLeast(1)
forkEvery = 100

// Mockito's ByteBuddy agent emits a JVM warning when loaded dynamically. Tests that capture
// stderr (e.g. LoggingHttpClientTest) see this warning interleaved with their expected output
Expand All @@ -49,6 +48,15 @@ tasks.withType<Test>().configureEach {
}
}

dependencies {
// SLF4J lazily initializes on the first `LoggerFactory.getLogger` call in
// the JVM and, without a provider, prints a warning to stderr. That warning
// corrupts tests that capture and assert on exact stderr contents when
// another test races the initialization. Binding a no-op provider keeps
// SLF4J silent.
"testRuntimeOnly"("org.slf4j:slf4j-nop:2.0.16")
}

val palantir by configurations.creating
dependencies {
palantir("com.palantir.javaformat:palantir-java-format:2.89.0")
Expand Down
Loading
Loading