sqldb-postgresql-testing: add TestModule mixin that pins testcontainers Docker API to 1.46 #28

Closed
opened 2026-05-07 13:00:47 +00:00 by mprihoda · 1 comment
mprihoda commented 2026-05-07 13:00:47 +00:00 (Migrated from github.com)

Background

org.testcontainers:testcontainers:1.20.x (and 1.21.x) hard-codes a fallback to Docker API 1.32 in DockerClientProviderStrategy.getClientForConfig:

```java
if (apiVersion == UNKNOWN_VERSION)
.withApiVersion(VERSION_1_32)
```

Docker engine 28+ rejects 1.32 as too old (minimum 1.44 since Docker 25, 29 keeps the same floor):

```
client version 1.32 is too old. Minimum supported API version is 1.44, please upgrade your client to a newer version
```

The shaded DefaultDockerClientConfig.createDefaultConfigBuilder() reads api.version from system properties (via overrideDockerPropertiesWithSystemProperties walking CONFIG_KEYS), so passing -Dapi.version=1.46 to the test JVM lets testcontainers negotiate the right API at handshake time.

Symptom

Any project depending on iw-support-sqldb-postgresql-testing and running its itest suite against a developer machine with modern Docker hits this on every whenDockerAvailable block — silently degrading the suite to "skipped" because the testcontainer never starts.

Reproduced on:

  • Docker engine 29.1.3 (Linux, native socket)
  • testcontainers-java 1.20.4 (transitive via dimafeng::testcontainers-scala-postgresql::0.41.5)
  • Carried by remote-signing ACA-507 phase 3, where Phase 1's `PostgresCredentialRepositorySpec` was also silently skipped before being noticed.

Proposed fix

Provide a TestModule mixin trait in sqldb-postgresql-testing (e.g. PostgreSQLTestcontainersTests) that downstream itests extend instead of plain TestModule. The mixin sets:

```scala
trait PostgreSQLTestcontainersTests extends TestModule:
override def forkArgs = super.forkArgs() ++ Seq("-Dapi.version=1.46")
```

so every consumer inherits the API override automatically. (Same idea applies to sqldb-mysql-testing.)

Workaround in consumer projects

Until the mixin lands, downstream projects need to set this on every itest module:

```scala
override def forkArgs = super.forkArgs() ++ Seq("-Dapi.version=1.46")
```

remote-signing (ACA-507) carries this in infrastructure.itest's forkArgs.

Notes

  • 1.46 was picked as a safe ceiling that Docker 25+ supports. Anything in [1.44, current] should work.
  • A version bump of testcontainers alone doesn't fix this — checked 1.20.4 and 1.21.3 bytecode; both have the same VERSION_1_32 fallback constant.
  • Long-term, testcontainers upstream should remove the hard-coded fallback or at least track a saner default. Worth flagging upstream too if not already.
## Background `org.testcontainers:testcontainers:1.20.x` (and 1.21.x) hard-codes a fallback to Docker API **1.32** in `DockerClientProviderStrategy.getClientForConfig`: \`\`\`java if (apiVersion == UNKNOWN_VERSION) .withApiVersion(VERSION_1_32) \`\`\` Docker engine 28+ rejects 1.32 as too old (minimum 1.44 since Docker 25, 29 keeps the same floor): \`\`\` client version 1.32 is too old. Minimum supported API version is 1.44, please upgrade your client to a newer version \`\`\` The shaded `DefaultDockerClientConfig.createDefaultConfigBuilder()` reads `api.version` from system properties (via `overrideDockerPropertiesWithSystemProperties` walking `CONFIG_KEYS`), so passing `-Dapi.version=1.46` to the test JVM lets testcontainers negotiate the right API at handshake time. ## Symptom Any project depending on `iw-support-sqldb-postgresql-testing` and running its itest suite against a developer machine with modern Docker hits this on every `whenDockerAvailable` block — silently degrading the suite to "skipped" because the testcontainer never starts. Reproduced on: - Docker engine 29.1.3 (Linux, native socket) - testcontainers-java 1.20.4 (transitive via `dimafeng::testcontainers-scala-postgresql::0.41.5`) - Carried by `remote-signing` ACA-507 phase 3, where Phase 1's \`PostgresCredentialRepositorySpec\` was also silently skipped before being noticed. ## Proposed fix Provide a `TestModule` mixin trait in `sqldb-postgresql-testing` (e.g. `PostgreSQLTestcontainersTests`) that downstream itests extend instead of plain `TestModule`. The mixin sets: \`\`\`scala trait PostgreSQLTestcontainersTests extends TestModule: override def forkArgs = super.forkArgs() ++ Seq("-Dapi.version=1.46") \`\`\` so every consumer inherits the API override automatically. (Same idea applies to `sqldb-mysql-testing`.) ## Workaround in consumer projects Until the mixin lands, downstream projects need to set this on every itest module: \`\`\`scala override def forkArgs = super.forkArgs() ++ Seq("-Dapi.version=1.46") \`\`\` `remote-signing` (ACA-507) carries this in `infrastructure.itest`'s `forkArgs`. ## Notes - `1.46` was picked as a safe ceiling that Docker 25+ supports. Anything in `[1.44, current]` should work. - A version bump of testcontainers alone doesn't fix this — checked 1.20.4 and 1.21.3 bytecode; both have the same `VERSION_1_32` fallback constant. - Long-term, testcontainers upstream should remove the hard-coded fallback or at least track a saner default. Worth flagging upstream too if not already.
mprihoda commented 2026-05-15 10:04:22 +00:00 (Migrated from github.com)

Fixed in #29 by bumping testcontainers 1.20.4 → 1.21.4. The upstream backport (released 2025-12-15) removes the hard-coded VERSION_1_32 fallback, so the Mill TestModule mixin / -Dapi.version=1.46 workaround proposed here is no longer needed.

Verified locally on Docker engine 29.1.3 (API 1.52, min 1.44): sqldb-postgresql.test runs 50 tests across 7 specs, sqldb-mysql.test runs 10 tests, 0 ignored in both — silent-skip behavior is gone.

See project-management/issues/SUPP-28/analysis.md for the resolution block and historical investigation.

Fixed in #29 by bumping testcontainers 1.20.4 → 1.21.4. The upstream backport (released 2025-12-15) removes the hard-coded `VERSION_1_32` fallback, so the Mill `TestModule` mixin / `-Dapi.version=1.46` workaround proposed here is no longer needed. Verified locally on Docker engine 29.1.3 (API 1.52, min 1.44): `sqldb-postgresql.test` runs 50 tests across 7 specs, `sqldb-mysql.test` runs 10 tests, 0 ignored in both — silent-skip behavior is gone. See `project-management/issues/SUPP-28/analysis.md` for the resolution block and historical investigation.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
iterative-works/support#28
No description provided.