This is an automated email from the ASF dual-hosted git repository.
epugh pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr-mcp.git
The following commit(s) were added to refs/heads/main by this push:
new 93ffdb79 build(test): pin Testcontainers images in the version catalog
(#199)
93ffdb79 is described below
commit 93ffdb79f43009f916060fee8d2aa13811145b71
Author: Aditya Parikh <[email protected]>
AuthorDate: Wed Sep 16 14:03:50 2026 -0400
build(test): pin Testcontainers images in the version catalog (#199)
* test(observability): re-enable OtlpExportIntegrationTest
The class had been @Disabled since #41 because starting the Grafana LGTM
Testcontainer threw a ClassNotFoundException for
org.eclipse.jetty.client.transport.HttpClientTransportOverHTTP. The Jetty
pin has since moved with the SolrJ 10 bump, jetty-client 12.0.34 is on the
test runtime classpath and contains that class, and the container now
starts cleanly.
With the annotation removed, three methods failed with
AuthenticationCredentialsNotFoundException: the test calls @PreAuthorize
service methods directly, with no MCP request and hence no principal. Rather
than switch http.security.enabled off, the test authenticates its own thread
with a TestingAuthenticationToken in @BeforeEach and clears it in
@AfterEach, so method security stays active while OTLP export is verified.
All seven methods pass; the build no longer reports any skipped tests.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_019zJ9WA8nNyA5Yxb8ueM7vV
Signed-off-by: Aditya Parikh <[email protected]>
* build(test): pin Testcontainers images in the version catalog
Pin the Solr and Grafana LGTM images the tests start to exact tags,
solr:9.9.0-slim and grafana/otel-lgtm:0.33.0, declared once as
test-image-solr / test-image-lgtm in gradle/libs.versions.toml. Previously
the Solr default was spelled out three times and the LGTM image floated on
latest: the locally cached "latest" was 0.28.0 from May while Docker Hub's
had moved to 0.33.0, so the same test run meant different things on
different machines.
processTestResources expands the pins into test-images.properties and the
Gradle test tasks also forward them as system properties. A new TestImages
resolver prefers a non-blank -Dsolr.test.image / -Dlgtm.test.image, so the
Solr compatibility matrix keeps working, and falls back to the resource
otherwise; the resource is included in the native test binary explicitly.
TestImagesTest fails the build if a pin is missing, floats on latest, or is
not an exact release tag.
Verified: ./gradlew build 407 tests, 0 failures, 0 skipped;
./gradlew nativeTest -Pnative 405 tests, 0 failures, 138 skipped (Mockito).
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_019zJ9WA8nNyA5Yxb8ueM7vV
Signed-off-by: Aditya Parikh <[email protected]>
* build(test): read catalog pins directly in TestImagesTest
TestImagesTest cleared the real solr.test.image / lgtm.test.image system
properties, and Gradle runs every test class in one fork, so any container
started after it fell back to the catalog pin. The Solr compatibility matrix
in CI passes -Dsolr.test.image and could end up testing the pinned version
while reporting another. The pin-guard tests now read the expanded resource
through TestImages.pinned(key) and never touch system properties; the two
override tests that covered three lines of resolve() are dropped.
Also hoists the catalog pins to one declaration in build.gradle.kts, removes
the duplicate systemProperty forwarding on integrationTest (withType<Test>
already covers it), and stops the docs from demonstrating the moving
solr:9.9-slim tag as an override example.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CiUHyyXLTo9ATdgg8eRFZJ
Signed-off-by: Aditya Parikh <[email protected]>
* test(observability): drop stale disabled-note and redundant
setAuthenticated
The class javadoc still said the test was disabled for a Jetty
ClassNotFoundException; that paragraph now describes the LGTM container and
the self-authenticated test thread. TestingAuthenticationToken's authorities
constructor already marks the token authenticated, so the explicit call
goes.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CiUHyyXLTo9ATdgg8eRFZJ
Signed-off-by: Aditya Parikh <[email protected]>
* build(test): back out TestImages indirection per review
Eric Pugh asked to back this out: it adds indirection for little value,
and hides the Docker image name that should be visible right at the
Testcontainers call, matching the pattern apache/solr itself uses.
TestcontainersConfiguration and OtlpExportIntegrationTest now read
System.getProperty("solr.test.image"/"lgtm.test.image", <literal pin>)
directly, so the image is visible in the call and -Dsolr.test.image
still drives the Solr compatibility matrix in CI. TestImages.java,
TestImagesTest.java, and the test-images.properties resource (plus its
native -H:IncludeResources hint) are gone with the class that used
them. The gradle/libs.versions.toml pins stay as the single declared
version, with a comment that the call-site literals must be bumped
alongside them.
Verified: ./gradlew build 403 tests, 0 failures, 0 skipped (JDK 25).
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Signed-off-by: Aditya Parikh <[email protected]>
---------
Signed-off-by: Aditya Parikh <[email protected]>
Co-authored-by: Claude Fable 5.1 <[email protected]>
---
AGENTS.md | 6 +++---
build.gradle.kts | 19 +++++++++++++++----
dev-docs/DEVELOPMENT.md | 6 +++---
gradle/libs.versions.toml | 7 +++++++
.../solr/mcp/server/TestcontainersConfiguration.java | 4 +++-
.../observability/OtlpExportIntegrationTest.java | 5 ++++-
6 files changed, 35 insertions(+), 12 deletions(-)
diff --git a/AGENTS.md b/AGENTS.md
index 15ddc422..53fd90c6 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -381,12 +381,12 @@ are exercised. The Jib JVM path runs in
`build-and-publish.yml`.
### Solr Version Compatibility Testing
-The Solr Docker image used in tests is configurable via the `solr.test.image`
system property (default: `solr:9.9-slim`):
+The Solr Docker image used in tests is pinned as `test-image-solr` in
`gradle/libs.versions.toml` (the Grafana LGTM image for the OTLP test as
`test-image-lgtm`), matching the literal default in
`TestcontainersConfiguration`/`OtlpExportIntegrationTest`. Override the Solr
image for one run with the `solr.test.image` system property:
```bash
./gradlew test -Dsolr.test.image=solr:8.11-slim # Solr 8.11
./gradlew test -Dsolr.test.image=solr:9.4-slim # Solr 9.4
-./gradlew test -Dsolr.test.image=solr:9.9-slim # Solr 9.9 (default)
+./gradlew test -Dsolr.test.image=solr:9.9.0-slim # Solr 9.9 (the pinned
default)
./gradlew test -Dsolr.test.image=solr:9.10-slim # Solr 9.10
./gradlew test -Dsolr.test.image=solr:10-slim # Solr 10
```
@@ -404,7 +404,7 @@ Remaining known differences from Solr 9:
- **`/admin/mbeans` removed:** Cache and handler stats from
`getCollectionStats()` will always be `null` on Solr 10. A future migration to
`/admin/metrics` will restore these metrics.
- **Metrics migration:** Dropwizard metrics replaced by OpenTelemetry. Metric
names switch to snake_case in Solr 10.
- **SolrJ base URL:** Already uses root URLs — **no change needed**.
-- **SolrJ version:** `solr-solrj` is on 10.0.0 (`gradle/libs.versions.toml`),
released to Maven Central and bumped in #58. Jetty artifacts are declared
versionless and managed by Spring Boot's BOM, so there is no separate Jetty pin
to update. Note the client is *newer* than the default test server:
`solr.test.image` defaults to `solr:9.9-slim`, so the standard build exercises
a SolrJ 10 client against Solr 9.9.
+- **SolrJ version:** `solr-solrj` is on 10.0.0 (`gradle/libs.versions.toml`),
released to Maven Central and bumped in #58. Jetty artifacts are declared
versionless and managed by Spring Boot's BOM, so there is no separate Jetty pin
to update. Note the client is *newer* than the default test server:
`solr.test.image` defaults to `solr:9.9.0-slim`, so the standard build
exercises a SolrJ 10 client against Solr 9.9.
## Key Configuration
diff --git a/build.gradle.kts b/build.gradle.kts
index 12ede13a..b0933b5e 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -203,6 +203,18 @@ springBoot {
buildInfo()
}
+// Testcontainers image pins live in gradle/libs.versions.toml;
-Dsolr.test.image
+// and -Dlgtm.test.image override them for a single run (e.g. the Solr
+// compatibility matrix in CI).
+val solrPin =
+ libs.versions.test.image.solr
+ .get()
+val lgtmPin =
+ libs.versions.test.image.lgtm
+ .get()
+val solrTestImage = System.getProperty("solr.test.image", solrPin)
+val lgtmTestImage = System.getProperty("lgtm.test.image", lgtmPin)
+
tasks.withType<Test> {
useJUnitPlatform {
// Only exclude docker integration tests from regular test runs, not
from dockerIntegrationTest
@@ -217,8 +229,9 @@ tasks.withType<Test> {
if (name != "dockerIntegrationTest") {
dependsOn(tasks.bootJar)
}
- // Forward solr.test.image system property to test JVMs for Solr version
compatibility testing
- systemProperty("solr.test.image", System.getProperty("solr.test.image",
"solr:9.9-slim"))
+ // Forward the Testcontainers image pins (or a per-run -D override) to
test JVMs.
+ systemProperty("solr.test.image", solrTestImage)
+ systemProperty("lgtm.test.image", lgtmTestImage)
if (name != "dockerIntegrationTest") {
finalizedBy(tasks.jacocoTestReport)
}
@@ -254,8 +267,6 @@ tasks.register<Test>("integrationTest") {
testClassesDirs = sourceSets["test"].output.classesDirs
classpath = sourceSets["test"].runtimeClasspath
- systemProperty("solr.test.image", System.getProperty("solr.test.image",
"solr:9.9-slim"))
-
mustRunAfter(tasks.named("unitTest"))
finalizedBy(tasks.jacocoTestReport)
diff --git a/dev-docs/DEVELOPMENT.md b/dev-docs/DEVELOPMENT.md
index c11def43..88b5afa6 100644
--- a/dev-docs/DEVELOPMENT.md
+++ b/dev-docs/DEVELOPMENT.md
@@ -189,12 +189,12 @@ This runs tests tagged with `@Tag("docker-integration")`
which verify:
### Solr Version Compatibility
-Tests run against `solr:9.9-slim` by default. Point them at another Solr
version with the `solr.test.image` system property:
+Tests run against the Solr image pinned as `test-image-solr` in
`gradle/libs.versions.toml` by default (the LGTM image for the OTLP test is
pinned there too, as `test-image-lgtm`). Point them at another Solr version
with the `solr.test.image` system property:
```bash
./gradlew test -Dsolr.test.image=solr:8.11-slim # Solr 8.11
./gradlew test -Dsolr.test.image=solr:9.4-slim # Solr 9.4
-./gradlew test -Dsolr.test.image=solr:9.9-slim # Solr 9.9 (default)
+./gradlew test -Dsolr.test.image=solr:9.9.0-slim # Solr 9.9 (the pinned
default)
./gradlew test -Dsolr.test.image=solr:9.10-slim # Solr 9.10
./gradlew test -Dsolr.test.image=solr:10-slim # Solr 10
```
@@ -205,7 +205,7 @@ Tests run against `solr:9.9-slim` by default. Point them at
another Solr version
endpoint was removed in Solr 10, so `getCacheMetrics()`/`getHandlerMetrics()`
catch
`RuntimeException` and return `null` — `cacheStats`/`handlerStats` from
`get-collection-stats`
are therefore always `null` on Solr 10 (a future migration to `/admin/metrics`
will restore
-them). SolrJ is on 10.0.0; since `solr.test.image` defaults to
`solr:9.9-slim`, the standard
+them). SolrJ is on 10.0.0; since the pinned test image is Solr 9.9, the
standard
build runs a SolrJ 10 client against a Solr 9.9 server.
### Test with MCP Inspector
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index ca672722..b5cdc021 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -38,6 +38,13 @@ nullaway = "0.13.1"
# Test dependencies
testcontainers = "1.21.3"
+# Docker images started by Testcontainers. Exact tags only (never "latest" or a
+# moving minor tag). Forwarded to tests as the solr.test.image /
lgtm.test.image
+# system properties, which also override them for a single run; the literal
+# default at each Testcontainers call site (TestcontainersConfiguration,
+# OtlpExportIntegrationTest) must be bumped along with these pins.
+test-image-solr = "solr:9.9.0-slim"
+test-image-lgtm = "grafana/otel-lgtm:0.33.0"
awaitility = "4.3.0"
opentelemetry-instrumentation-bom = "2.26.1"
diff --git
a/src/test/java/org/apache/solr/mcp/server/TestcontainersConfiguration.java
b/src/test/java/org/apache/solr/mcp/server/TestcontainersConfiguration.java
index 5f6267a2..ef324e1f 100644
--- a/src/test/java/org/apache/solr/mcp/server/TestcontainersConfiguration.java
+++ b/src/test/java/org/apache/solr/mcp/server/TestcontainersConfiguration.java
@@ -29,7 +29,9 @@ public class TestcontainersConfiguration {
@Bean
SolrContainer solr() {
- String solrImage = System.getProperty("solr.test.image",
"solr:9.9-slim");
+ // Pinned in gradle/libs.versions.toml as test-image-solr;
-Dsolr.test.image
+ // overrides it for a single run (e.g. the Solr compatibility
matrix in CI).
+ String solrImage = System.getProperty("solr.test.image",
"solr:9.9.0-slim");
return new SolrContainer(DockerImageName.parse(solrImage));
}
diff --git
a/src/test/java/org/apache/solr/mcp/server/observability/OtlpExportIntegrationTest.java
b/src/test/java/org/apache/solr/mcp/server/observability/OtlpExportIntegrationTest.java
index 894fae0e..bdf324f8 100644
---
a/src/test/java/org/apache/solr/mcp/server/observability/OtlpExportIntegrationTest.java
+++
b/src/test/java/org/apache/solr/mcp/server/observability/OtlpExportIntegrationTest.java
@@ -92,9 +92,12 @@ class OtlpExportIntegrationTest {
* The {@code @ServiceConnection} annotation enables Spring Boot to
recognize
* this container for service connection auto-configuration.
*/
+ // Pinned in gradle/libs.versions.toml as test-image-lgtm;
-Dlgtm.test.image
+ // overrides it for a single run.
@Container
@ServiceConnection
- static LgtmStackContainer lgtmStack = new
LgtmStackContainer("grafana/otel-lgtm:latest");
+ static LgtmStackContainer lgtmStack = new LgtmStackContainer(
+ System.getProperty("lgtm.test.image",
"grafana/otel-lgtm:0.33.0"));
@Autowired
private SearchService searchService;