From 0492aa1130e412e9cff8e0a52801f0917d69ce53 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 12 Mar 2026 19:30:59 +0000 Subject: [PATCH 1/6] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 75c1218..005d7f3 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 83 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/courier%2Fcourier-19330fca8fa9bbae835ec9d9f83b37b3df364d9b462090b9623bfc9b6eae99c2.yml openapi_spec_hash: 0bc6889464c9ac2542b4837f569c1837 -config_hash: 1ae49ed522c8423378d9463cdd0fb880 +config_hash: c501fe3838c270e9b44dd5dc4b7fca70 From 2e80101af06db1bf289c85f3efba011d5ed0e795 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 17 Mar 2026 04:12:22 +0000 Subject: [PATCH 2/6] chore(internal): tweak CI branches --- .github/workflows/ci.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b704659..dc7e2ec 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,12 +1,14 @@ name: CI on: push: - branches-ignore: - - 'generated' - - 'codegen/**' - - 'integrated/**' - - 'stl-preview-head/**' - - 'stl-preview-base/**' + branches: + - '**' + - '!integrated/**' + - '!stl-preview-head/**' + - '!stl-preview-base/**' + - '!generated' + - '!codegen/**' + - 'codegen/stl/**' pull_request: branches-ignore: - 'stl-preview-head/**' From bf3c18dc04417a8f2376a636b8a9631d0653f168 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 18 Mar 2026 02:55:28 +0000 Subject: [PATCH 3/6] chore(internal): update retry delay tests --- .../com/courier/core/http/RetryingHttpClientTest.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/courier-java-core/src/test/kotlin/com/courier/core/http/RetryingHttpClientTest.kt b/courier-java-core/src/test/kotlin/com/courier/core/http/RetryingHttpClientTest.kt index e5636ac..c465498 100644 --- a/courier-java-core/src/test/kotlin/com/courier/core/http/RetryingHttpClientTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/core/http/RetryingHttpClientTest.kt @@ -400,9 +400,9 @@ internal class RetryingHttpClientTest { assertThat(sleeper.durations).hasSize(3) // retries=1: 0.5s * [0.75, 1.0] assertThat(sleeper.durations[0]).isBetween(Duration.ofMillis(375), Duration.ofMillis(500)) - // retries=2: 1.0s * [0.75, 1.0] + // retries=2: 1s * [0.75, 1.0] assertThat(sleeper.durations[1]).isBetween(Duration.ofMillis(750), Duration.ofMillis(1000)) - // retries=3: 2.0s * [0.75, 1.0] + // retries=3: 2s * [0.75, 1.0] assertThat(sleeper.durations[2]).isBetween(Duration.ofMillis(1500), Duration.ofMillis(2000)) assertNoResponseLeaks() } @@ -427,9 +427,9 @@ internal class RetryingHttpClientTest { assertThat(response.statusCode()).isEqualTo(503) verify(7, postRequestedFor(urlPathEqualTo("/something"))) assertThat(sleeper.durations).hasSize(6) - // retries=5: min(0.5 * 2^4, 8) = 8.0s * [0.75, 1.0] + // retries=5: backoff hits the 8s cap * [0.75, 1.0] assertThat(sleeper.durations[4]).isBetween(Duration.ofMillis(6000), Duration.ofMillis(8000)) - // retries=6: min(0.5 * 2^5, 8) = min(16, 8) = 8.0s * [0.75, 1.0] (capped) + // retries=6: still capped at 8s * [0.75, 1.0] assertThat(sleeper.durations[5]).isBetween(Duration.ofMillis(6000), Duration.ofMillis(8000)) assertNoResponseLeaks() } From 2d3fb18657ed5c6f761d6cfd0e3fb46921c26092 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 18 Mar 2026 03:13:20 +0000 Subject: [PATCH 4/6] fix(client): allow updating header/query affecting fields in `toBuilder()` --- .../kotlin/com/courier/core/ClientOptions.kt | 7 +++--- .../com/courier/core/ClientOptionsTest.kt | 23 +++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/courier-java-core/src/main/kotlin/com/courier/core/ClientOptions.kt b/courier-java-core/src/main/kotlin/com/courier/core/ClientOptions.kt index 122fde6..bee2096 100644 --- a/courier-java-core/src/main/kotlin/com/courier/core/ClientOptions.kt +++ b/courier-java-core/src/main/kotlin/com/courier/core/ClientOptions.kt @@ -403,13 +403,14 @@ private constructor( headers.put("X-Stainless-Runtime", "JRE") headers.put("X-Stainless-Runtime-Version", getJavaVersion()) headers.put("X-Stainless-Kotlin-Version", KotlinVersion.CURRENT.toString()) + // We replace after all the default headers to allow end-users to overwrite them. + headers.replaceAll(this.headers.build()) + queryParams.replaceAll(this.queryParams.build()) apiKey.let { if (!it.isEmpty()) { - headers.put("Authorization", "Bearer $it") + headers.replace("Authorization", "Bearer $it") } } - headers.replaceAll(this.headers.build()) - queryParams.replaceAll(this.queryParams.build()) return ClientOptions( httpClient, diff --git a/courier-java-core/src/test/kotlin/com/courier/core/ClientOptionsTest.kt b/courier-java-core/src/test/kotlin/com/courier/core/ClientOptionsTest.kt index bb4ebcb..fd9aa5c 100644 --- a/courier-java-core/src/test/kotlin/com/courier/core/ClientOptionsTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/core/ClientOptionsTest.kt @@ -16,6 +16,29 @@ internal class ClientOptionsTest { private val httpClient = mock() + @Test + fun putHeader_canOverwriteDefaultHeader() { + val clientOptions = + ClientOptions.builder() + .httpClient(httpClient) + .putHeader("User-Agent", "My User Agent") + .apiKey("My API Key") + .build() + + assertThat(clientOptions.headers.values("User-Agent")).containsExactly("My User Agent") + } + + @Test + fun toBuilder_bearerAuthCanBeUpdated() { + var clientOptions = + ClientOptions.builder().httpClient(httpClient).apiKey("My API Key").build() + + clientOptions = clientOptions.toBuilder().apiKey("another My API Key").build() + + assertThat(clientOptions.headers.values("Authorization")) + .containsExactly("Bearer another My API Key") + } + @Test fun toBuilder_whenOriginalClientOptionsGarbageCollected_doesNotCloseOriginalClient() { var clientOptions = From 5b3a0b51f7e134df397f10abc756e9c3e6adb93f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 20 Mar 2026 02:12:11 +0000 Subject: [PATCH 5/6] chore(internal): bump ktfmt --- buildSrc/src/main/kotlin/courier.kotlin.gradle.kts | 2 +- scripts/fast-format | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/buildSrc/src/main/kotlin/courier.kotlin.gradle.kts b/buildSrc/src/main/kotlin/courier.kotlin.gradle.kts index 9de64f2..28ed476 100644 --- a/buildSrc/src/main/kotlin/courier.kotlin.gradle.kts +++ b/buildSrc/src/main/kotlin/courier.kotlin.gradle.kts @@ -40,7 +40,7 @@ tasks.withType().configureEach { val ktfmt by configurations.creating dependencies { - ktfmt("com.facebook:ktfmt:0.56") + ktfmt("com.facebook:ktfmt:0.61") } fun registerKtfmt( diff --git a/scripts/fast-format b/scripts/fast-format index 1b3bc47..35a1dee 100755 --- a/scripts/fast-format +++ b/scripts/fast-format @@ -24,8 +24,8 @@ if [ ! -f "$FILE_LIST" ]; then exit 1 fi -if ! command -v ktfmt-fast-format &> /dev/null; then - echo "Error: ktfmt-fast-format not found" +if ! command -v ktfmt &> /dev/null; then + echo "Error: ktfmt not found" exit 1 fi @@ -36,7 +36,7 @@ echo "==> Done looking for Kotlin files" if [[ -n "$kt_files" ]]; then echo "==> will format Kotlin files" - echo "$kt_files" | tr '\n' '\0' | xargs -0 ktfmt-fast-format --kotlinlang-style "$@" + echo "$kt_files" | tr '\n' '\0' | xargs -0 ktfmt --kotlinlang-style "$@" else echo "No Kotlin files to format -- expected outcome during incremental formatting" fi From e1317350ed4e96e623693145dbabad21bff76508 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 20 Mar 2026 02:12:28 +0000 Subject: [PATCH 6/6] release: 4.10.1 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 15 +++++++++++++++ build.gradle.kts | 2 +- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index ad56a78..95fa24d 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "4.10.0" + ".": "4.10.1" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 712ef68..a1d91cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +## 4.10.1 (2026-03-20) + +Full Changelog: [v4.10.0...v4.10.1](https://github.com/trycourier/courier-java/compare/v4.10.0...v4.10.1) + +### Bug Fixes + +* **client:** allow updating header/query affecting fields in `toBuilder()` ([2d3fb18](https://github.com/trycourier/courier-java/commit/2d3fb18657ed5c6f761d6cfd0e3fb46921c26092)) + + +### Chores + +* **internal:** bump ktfmt ([5b3a0b5](https://github.com/trycourier/courier-java/commit/5b3a0b51f7e134df397f10abc756e9c3e6adb93f)) +* **internal:** tweak CI branches ([2e80101](https://github.com/trycourier/courier-java/commit/2e80101af06db1bf289c85f3efba011d5ed0e795)) +* **internal:** update retry delay tests ([bf3c18d](https://github.com/trycourier/courier-java/commit/bf3c18dc04417a8f2376a636b8a9631d0653f168)) + ## 4.10.0 (2026-03-12) Full Changelog: [v4.9.1...v4.10.0](https://github.com/trycourier/courier-java/compare/v4.9.1...v4.10.0) diff --git a/build.gradle.kts b/build.gradle.kts index 653fe82..37a3f7e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ repositories { allprojects { group = "com.courier" - version = "4.10.0" // x-release-please-version + version = "4.10.1" // x-release-please-version } subprojects {