diff --git a/.github/actions/setup-gradle/action.yml b/.github/actions/setup-gradle/action.yml index c97d776e04f..76d1b0ff4b2 100644 --- a/.github/actions/setup-gradle/action.yml +++ b/.github/actions/setup-gradle/action.yml @@ -4,7 +4,7 @@ runs: using: "composite" steps: - name: Setup Gradle Build Action - uses: gradle/actions/setup-gradle@v4 + uses: gradle/actions/setup-gradle@v6 with: gradle-home-cache-includes: | caches diff --git a/.github/actions/setup-java/action.yml b/.github/actions/setup-java/action.yml index ee8c3323fc1..093fbc2e7fd 100644 --- a/.github/actions/setup-java/action.yml +++ b/.github/actions/setup-java/action.yml @@ -8,7 +8,7 @@ inputs: runs: using: "composite" steps: - - uses: actions/setup-java@v4 + - uses: actions/setup-java@v5 with: java-version: ${{ inputs.java-version }} distribution: temurin diff --git a/.github/actions/setup-junit-report/action.yml b/.github/actions/setup-junit-report/action.yml index 538af9af21f..df0af39297f 100644 --- a/.github/actions/setup-junit-report/action.yml +++ b/.github/actions/setup-junit-report/action.yml @@ -4,7 +4,7 @@ runs: using: "composite" steps: - name: Publish Test Report - uses: mikepenz/action-junit-report@v4 + uses: mikepenz/action-junit-report@v6 if: always() # always run even if the previous step fails with: report_paths: '**/build/test-results/test/TEST-*.xml' diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 72a6d9110b6..c668168cff8 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,433 +1,343 @@ version: 2 + registries: gradle-plugin-portal: type: maven-repository url: https://plugins.gradle.org/m2 - username: dummy # Required by dependabot - password: dummy # Required by dependabot -updates: - - package-ecosystem: "gradle" - directory: "/core" + username: dummy # Required by Dependabot + password: dummy # Required by Dependabot + +multi-ecosystem-groups: + dependencies: schedule: interval: "weekly" - open-pull-requests-limit: 10 - ignore: - - dependency-name: "org.slf4j:slf4j-api" - update-types: [ "version-update:semver-major" ] - - dependency-name: "org.mockito:mockito-core" - update-types: [ "version-update:semver-major" ] - - dependency-name: "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" - update-types: [ "version-update:semver-minor", "version-update:semver-patch" ] + day: "monday" + +updates: + # Gradle plugins declared in the root build. - package-ecosystem: "gradle" directory: "/" allow: - dependency-name: "com.gradle*" registries: - gradle-plugin-portal - schedule: - interval: "weekly" - open-pull-requests-limit: 10 + patterns: + - "com.gradle*" + multi-ecosystem-group: dependencies + cooldown: + default-days: 7 ignore: - dependency-name: "com.gradleup.shadow" - update-types: [ "version-update:semver-major" ] + update-types: ["version-update:semver-major"] -# Explicit entry for each module - - package-ecosystem: "gradle" - directory: "/modules/activemq" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 + # Core dependencies have compatibility constraints that do not apply to every module. - package-ecosystem: "gradle" - directory: "/modules/azure" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 + directory: "/core" + patterns: + - "*" + multi-ecosystem-group: dependencies + cooldown: + default-days: 7 + ignore: + - dependency-name: "org.slf4j:slf4j-api" + update-types: ["version-update:semver-major"] + - dependency-name: "org.mockito:mockito-core" + update-types: ["version-update:semver-major"] + - dependency-name: "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" + update-types: ["version-update:semver-minor", "version-update:semver-patch"] + - dependency-name: "org.junit.jupiter:junit-jupiter" + update-types: ["version-update:semver-major"] + - dependency-name: "org.junit.platform:junit-platform-launcher" + update-types: ["version-update:semver-major"] + - dependency-name: "io.rest-assured:rest-assured" + update-types: ["version-update:semver-major"] + + # Modules without additional compatibility constraints. + - package-ecosystem: "gradle" + directories: + - "/modules/activemq" + - "/modules/azure" + - "/modules/clickhouse" + - "/modules/cockroachdb" + - "/modules/couchbase" + - "/modules/cratedb" + - "/modules/database-commons" + - "/modules/databend" + - "/modules/db2" + - "/modules/elasticsearch" + - "/modules/gcloud" + - "/modules/hivemq" + - "/modules/k6" + - "/modules/kafka" + - "/modules/ldap" + - "/modules/localstack" + - "/modules/milvus" + - "/modules/minio" + - "/modules/mongodb" + - "/modules/mssqlserver" + - "/modules/mysql" + - "/modules/nginx" + - "/modules/oceanbase" + - "/modules/openfga" + - "/modules/oracle-free" + - "/modules/oracle-xe" + - "/modules/orientdb" + - "/modules/postgresql" + - "/modules/presto" + - "/modules/qdrant" + - "/modules/questdb" + - "/modules/rabbitmq" + - "/modules/scylladb" + - "/modules/tidb" + - "/modules/timeplus" + - "/modules/toxiproxy" + - "/modules/trino" + - "/modules/typesense" + - "/modules/weaviate" + - "/modules/yugabytedb" + patterns: + - "*" + multi-ecosystem-group: dependencies + cooldown: + default-days: 7 + + # Modules sharing the same REST Assured compatibility constraint. + - package-ecosystem: "gradle" + directories: + - "/modules/chromadb" + - "/modules/consul" + - "/modules/grafana" + - "/modules/mockserver" + - "/modules/ollama" + - "/modules/redpanda" + - "/modules/vault" + patterns: + - "*" + multi-ecosystem-group: dependencies + cooldown: + default-days: 7 + ignore: + - dependency-name: "io.rest-assured:rest-assured" + update-types: ["version-update:semver-major"] + - package-ecosystem: "gradle" directory: "/modules/cassandra" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 + patterns: ["*"] + multi-ecosystem-group: dependencies + cooldown: + default-days: 7 ignore: - dependency-name: "io.dropwizard.metrics:metrics-core" - update-types: [ "version-update:semver-major" ] - - package-ecosystem: "gradle" - directory: "/modules/chromadb" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/clickhouse" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/cockroachdb" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/consul" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/couchbase" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/cratedb" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/database-commons" - schedule: - interval: "monthly" - - package-ecosystem: "gradle" - directory: "/modules/databend" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/db2" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/dynalite" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/elasticsearch" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/gcloud" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/grafana" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/hivemq" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 + update-types: ["version-update:semver-major"] + - package-ecosystem: "gradle" directory: "/modules/influxdb" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 + patterns: ["*"] + multi-ecosystem-group: dependencies + cooldown: + default-days: 7 ignore: - dependency-name: "com.influxdb:influxdb-java-client" - update-types: [ "version-update:semver-major" ] + update-types: ["version-update:semver-major"] + - package-ecosystem: "gradle" directory: "/modules/jdbc" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 + patterns: ["*"] + multi-ecosystem-group: dependencies + cooldown: + default-days: 7 ignore: - dependency-name: "org.mockito:mockito-core" - update-types: [ "version-update:semver-major" ] + update-types: ["version-update:semver-major"] + - package-ecosystem: "gradle" directory: "/modules/jdbc-test" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 + patterns: ["*"] + multi-ecosystem-group: dependencies + cooldown: + default-days: 7 ignore: - dependency-name: "org.apache.tomcat:tomcat-jdbc" - update-types: [ "version-update:semver-minor" ] + update-types: ["version-update:semver-minor"] + - dependency-name: "org.junit.jupiter:junit-jupiter" + update-types: ["version-update:semver-major"] + - package-ecosystem: "gradle" directory: "/modules/junit-jupiter" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 + patterns: ["*"] + multi-ecosystem-group: dependencies + cooldown: + default-days: 7 ignore: - dependency-name: "org.mockito:mockito-core" - update-types: [ "version-update:semver-major" ] + update-types: ["version-update:semver-major"] + - dependency-name: "org.junit:junit-bom" + update-types: ["version-update:semver-major"] + - package-ecosystem: "gradle" directory: "/modules/k3s" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 + patterns: ["*"] + multi-ecosystem-group: dependencies + cooldown: + default-days: 7 ignore: - dependency-name: "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml" - update-types: [ "version-update:semver-minor", "version-update:semver-patch" ] - - package-ecosystem: "gradle" - directory: "/modules/k6" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/kafka" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/ldap" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/localstack" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 + update-types: ["version-update:semver-minor", "version-update:semver-patch"] + - package-ecosystem: "gradle" directory: "/modules/mariadb" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 + patterns: ["*"] + multi-ecosystem-group: dependencies + cooldown: + default-days: 7 ignore: - dependency-name: "org.mariadb:r2dbc-mariadb" - update-types: [ "version-update:semver-minor" ] - - package-ecosystem: "gradle" - directory: "/modules/milvus" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/minio" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/mockserver" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/mongodb" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/mssqlserver" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/mysql" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 + update-types: ["version-update:semver-minor"] + - package-ecosystem: "gradle" directory: "/modules/neo4j" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 + patterns: ["*"] + multi-ecosystem-group: dependencies + cooldown: + default-days: 7 ignore: - dependency-name: "org.neo4j.driver:neo4j-java-driver" - update-types: [ "version-update:semver-major" ] + update-types: ["version-update:semver-major"] - dependency-name: "org.neo4j:neo4j" - update-types: [ "version-update:semver-major" ] - - package-ecosystem: "gradle" - directory: "/modules/nginx" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/oceanbase" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/ollama" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/openfga" - schedule: - interval: "monthly" - - package-ecosystem: "gradle" - directory: "/modules/oracle-free" - schedule: - interval: "monthly" - - package-ecosystem: "gradle" - directory: "/modules/oracle-xe" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/orientdb" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/postgresql" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/presto" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 + update-types: ["version-update:semver-major"] + - package-ecosystem: "gradle" directory: "/modules/pinecone" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 + patterns: ["*"] + multi-ecosystem-group: dependencies + cooldown: + default-days: 7 ignore: - dependency-name: "io.pinecone:pinecone-client" - update-types: [ "version-update:semver-major" ] + update-types: ["version-update:semver-major"] + - package-ecosystem: "gradle" directory: "/modules/pulsar" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 + patterns: ["*"] + multi-ecosystem-group: dependencies + cooldown: + default-days: 7 ignore: - dependency-name: "org.apache.pulsar:pulsar-bom" - update-types: [ "version-update:semver-patch" ] - - package-ecosystem: "gradle" - directory: "/modules/qdrant" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/questdb" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 + update-types: ["version-update:semver-patch"] + - package-ecosystem: "gradle" directory: "/modules/r2dbc" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 + patterns: ["*"] + multi-ecosystem-group: dependencies + cooldown: + default-days: 7 ignore: - dependency-name: "io.r2dbc:r2dbc-spi" - update-types: [ "version-update:semver-major", "version-update:semver-minor" ] - - package-ecosystem: "gradle" - directory: "/modules/rabbitmq" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/redpanda" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/scylladb" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 + update-types: ["version-update:semver-major", "version-update:semver-minor"] + - dependency-name: "org.junit.jupiter:junit-jupiter" + update-types: ["version-update:semver-major"] + - package-ecosystem: "gradle" directory: "/modules/selenium" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 + patterns: ["*"] + multi-ecosystem-group: dependencies + cooldown: + default-days: 7 ignore: - dependency-name: "org.seleniumhq.selenium:selenium-bom" - update-types: [ "version-update:semver-minor" ] + update-types: ["version-update:semver-minor"] + - package-ecosystem: "gradle" directory: "/modules/solace" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 + patterns: ["*"] + multi-ecosystem-group: dependencies + cooldown: + default-days: 7 ignore: - dependency-name: "org.apache.qpid:qpid-jms-client" - update-types: [ "version-update:semver-major" ] + update-types: ["version-update:semver-major"] + - package-ecosystem: "gradle" directory: "/modules/solr" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 + patterns: ["*"] + multi-ecosystem-group: dependencies + cooldown: + default-days: 7 ignore: - dependency-name: "org.apache.solr:solr-solrj" - update-types: [ "version-update:semver-major" ] + update-types: ["version-update:semver-major"] + - package-ecosystem: "gradle" directory: "/modules/spock" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/tidb" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/timeplus" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/toxiproxy" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/trino" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/typesense" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/vault" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/weaviate" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "gradle" - directory: "/modules/yugabytedb" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 + patterns: ["*"] + multi-ecosystem-group: dependencies + cooldown: + default-days: 7 + ignore: + - dependency-name: "org.junit:junit-bom" + update-types: ["version-update:semver-major"] -# Examples - package-ecosystem: "gradle" directory: "/examples" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 + patterns: ["*"] + multi-ecosystem-group: dependencies + cooldown: + default-days: 7 ignore: - dependency-name: "ch.qos.logback:logback-classic" - update-types: [ "version-update:semver-minor" ] + update-types: ["version-update:semver-minor"] - dependency-name: "org.apache.solr:solr-solrj" - update-types: [ "version-update:semver-major" ] + update-types: ["version-update:semver-major"] - dependency-name: "org.neo4j.driver:neo4j-java-driver" - update-types: [ "version-update:semver-major" ] + update-types: ["version-update:semver-major"] - dependency-name: "org.testng:testng" - update-types: [ "version-update:semver-minor" ] + update-types: ["version-update:semver-minor"] - dependency-name: "org.slf4j:slf4j-api" - update-types: [ "version-update:semver-major" ] + update-types: ["version-update:semver-major"] - dependency-name: "org.springframework.boot" - update-types: [ "version-update:semver-major" ] + update-types: ["version-update:semver-major"] - dependency-name: "com.diffplug.spotless" - update-types: [ "version-update:semver-major", "version-update:semver-minor" ] + update-types: ["version-update:semver-major", "version-update:semver-minor"] - dependency-name: "com.hazelcast:hazelcast" - update-types: [ "version-update:semver-minor" ] + update-types: ["version-update:semver-minor"] + - dependency-name: "org.junit.jupiter:junit-jupiter" + update-types: ["version-update:semver-major"] + - dependency-name: "org.junit.platform:junit-platform-launcher" + update-types: ["version-update:semver-major"] + - dependency-name: "org.junit:junit-bom" + update-types: ["version-update:semver-major"] + - dependency-name: "com.gradleup.shadow" + update-types: ["version-update:semver-major"] -# Smoke test - package-ecosystem: "gradle" directory: "/smoke-test" - schedule: - interval: "monthly" - open-pull-requests-limit: 10 + patterns: ["*"] + multi-ecosystem-group: dependencies + cooldown: + default-days: 7 ignore: - dependency-name: "ch.qos.logback:logback-classic" - update-types: [ "version-update:semver-minor" ] + update-types: ["version-update:semver-minor"] - dependency-name: "com.diffplug.spotless" - update-types: [ "version-update:semver-major", "version-update:semver-minor" ] + update-types: ["version-update:semver-major", "version-update:semver-minor"] + - dependency-name: "org.junit.jupiter:junit-jupiter" + update-types: ["version-update:semver-major"] + - dependency-name: "org.junit.platform:junit-platform-launcher" + update-types: ["version-update:semver-major"] + - dependency-name: "com.gradleup.shadow" + update-types: ["version-update:semver-major"] -# GitHub Actions - package-ecosystem: "github-actions" - directory: "/" + directories: + - "/" + - "/.github/actions/**" schedule: interval: "weekly" - open-pull-requests-limit: 10 + day: "monday" + groups: + github-actions: + patterns: + - "*" + cooldown: + default-days: 7 diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 31553ebfff1..6137bf623e3 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,6 +1,8 @@ -[Creating a Redis container (JUnit 4)](../examples/junit4/generic/src/test/java/generic/ContainerCreationTest.java) inside_block:simple +[Creating a Redis container](../examples/junit5/redis/src/test/java/quickstart/RedisBackedCacheIntTest.java) inside_block:container -Further options may be specified: - - -[Creating a container with more options (JUnit 4)](../examples/junit4/generic/src/test/java/generic/ContainerCreationTest.java) inside_block:withOptions - - -These containers, as `@ClassRule`s, will be started before any tests in the class run, and will be destroyed after all +The container, as `@Container`, will be started before any tests in the class run, and will be destroyed after all tests have run. diff --git a/docs/features/creating_images.md b/docs/features/creating_images.md index 6f1988ed28e..8a239d342cc 100644 --- a/docs/features/creating_images.md +++ b/docs/features/creating_images.md @@ -13,9 +13,9 @@ Testcontainers will `docker build` a temporary container image, and will use it `ImageFromDockerfile` accepts arbitrary files, strings or classpath resources to be used as files in the build context. At least one of these needs to be a `Dockerfile`. + ```java -@Rule -public GenericContainer dslContainer = new GenericContainer( +GenericContainer container = new GenericContainer( new ImageFromDockerfile() .withFileFromString("folder/someFile.txt", "hello") .withFileFromClasspath("test.txt", "mappable-resource/test-resource.txt") diff --git a/docs/modules/activemq.md b/docs/modules/activemq.md index 07cc6e75381..7959c47576a 100644 --- a/docs/modules/activemq.md +++ b/docs/modules/activemq.md @@ -1,7 +1,7 @@ # ActiveMQ -Testcontainers module for [ActiveMQ](https://hub.docker.com/r/apache/activemq-classic) and -[Artemis](https://hub.docker.com/r/apache/activemq-artemis). +Testcontainers module for [ActiveMQ](https://hub.docker.com/r/apache/activemq) and +[Artemis](https://hub.docker.com/r/apache/artemis). ## ActiveMQContainer's usage examples diff --git a/docs/modules/azure.md b/docs/modules/azure.md index 1b3242551c1..461fcc9f679 100644 --- a/docs/modules/azure.md +++ b/docs/modules/azure.md @@ -27,6 +27,12 @@ Start Azurite Emulator during a test: !!! note SSL configuration is possible using the `withSsl(MountableFile, String)` and `withSsl(MountableFile, MountableFile)` methods. +Newer Azure Storage SDK versions can send API versions that Azurite does not support. Use `withCommandOptions(...)` to append extra Azurite flags such as `--skipApiVersionCheck`. `AzuriteContainer` rebuilds its process command in `configure()`, so `.withCommand(...)` cannot be used for extra flags. + + +[Pass extra Azurite command options](../../modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerCommandTest.java) inside_block:commandOptions + + If the tested application needs to use more than one set of credentials, the container can be configured to use custom credentials. Please see some examples below. diff --git a/docs/modules/databases/neo4j.md b/docs/modules/databases/neo4j.md index 9bfb7fbfca7..c7b06e99fe7 100644 --- a/docs/modules/databases/neo4j.md +++ b/docs/modules/databases/neo4j.md @@ -9,19 +9,12 @@ the Testcontainers integration supports also newer 5.x images of Neo4j. ## Usage example -Declare your Testcontainers as a `@ClassRule` or `@Rule` in a JUnit 4 test or as static or member attribute of a JUnit 5 test annotated with `@Container` as you would with other Testcontainers. -You can either use call `getBoltUrl()` or `getHttpUrl()` on the Neo4j container. -`getBoltUrl()` is meant to be used with one of the [official Bolt drivers](https://neo4j.com/developer/language-guides/) while `getHttpUrl()` gives you the HTTP-address of the transactional HTTP endpoint. -On the JVM you would most likely use the [Java driver](https://github.com/neo4j/neo4j-java-driver). - -The following example uses the JUnit 5 extension `@Testcontainers` and demonstrates both the usage of the Java Driver and the REST endpoint: +You can start a Neo4j container instance from any Java application by using: -[JUnit 5 example](../../../examples/neo4j-container/src/test/java/org/testcontainers/containers/Neo4jExampleTest.java) inside_block:junitExample +[Neo4j container](../../../modules/neo4j/src/test/java/org/testcontainers/neo4j/Neo4jContainerTest.java) inside_block:container -You are not limited to Unit tests, and you can use an instance of the Neo4j Testcontainers in vanilla Java code as well. - ## Additional features ### Custom password diff --git a/docs/modules/docker_compose.md b/docs/modules/docker_compose.md index 2ac45912479..3d3d7a510c2 100644 --- a/docs/modules/docker_compose.md +++ b/docs/modules/docker_compose.md @@ -72,7 +72,7 @@ accessible via the static factory methods from of the `Wait` class. For instance, we can wait for exposed port and set a custom timeout: -[Wait for the exposed port and use a custom timeout](../../core/src/test/java/org/testcontainers/junit/ComposeContainerWithWaitStrategies.java) inside_block:composeContainerWaitForPortWithTimeout +[Wait for the exposed port and use a custom timeout](../../core/src/test/java/org/testcontainers/junit/ComposeContainerWithWaitStrategiesTest.java) inside_block:composeContainerWaitForPortWithTimeout Needless to say, we can define different strategies for each service in our Docker Compose setup. @@ -81,7 +81,7 @@ For example, our Redis container can wait for a successful redis-cli command, while our db service waits for a specific log message: -[Wait for a custom command and a log message](../../core/src/test/java/org/testcontainers/junit/ComposeContainerWithWaitStrategies.java) inside_block:composeContainerWithCombinedWaitStrategies +[Wait for a custom command and a log message](../../core/src/test/java/org/testcontainers/junit/ComposeContainerWithWaitStrategiesTest.java) inside_block:composeContainerWithCombinedWaitStrategies diff --git a/docs/modules/elasticsearch.md b/docs/modules/elasticsearch.md index c1fb4a3f6a8..5817a21de02 100644 --- a/docs/modules/elasticsearch.md +++ b/docs/modules/elasticsearch.md @@ -30,6 +30,33 @@ You can turn on security by providing a password: [HttpClient](../../modules/elasticsearch/src/test/java/org/testcontainers/elasticsearch/ElasticsearchContainerTest.java) inside_block:httpClientSecuredContainer +## Kibana container + +This module also provides a `KibanaContainer` for testing with [Kibana](https://www.elastic.co/kibana). +Kibana requires a connection to Elasticsearch and `KibanaContainer` supports two modes: managed and external. + +### Managed mode + +In managed mode, `KibanaContainer` automatically connects to an `ElasticsearchContainer`: + + +[Kibana with Elasticsearch](../../modules/elasticsearch/src/test/java/org/testcontainers/elasticsearch/KibanaContainerTest.java) inside_block:managedModeCanStartAndReachElasticsearchInSameExplicitNetwork + + +When using managed mode with explicit networks, both containers must share the same `Network` instance. +Alternatively, you can omit the network configuration entirely, and `KibanaContainer` will do its best effort to create a shared, ad-hoc network automatically. + +### External mode + +In external mode, `KibanaContainer` connects to an external Elasticsearch instance via URL and using provided credentials: + + +[Kibana with external Elasticsearch](../../modules/elasticsearch/src/test/java/org/testcontainers/elasticsearch/KibanaContainerTest.java) inside_block:externalModeCanWorkWithUsernamePassword + + +For external mode with HTTPS, use `withElasticsearchCaCertificate()` to provide the CA certificate. +You can authenticate using either username/password (`withElasticsearchCredentials()`) or service account tokens (`withElasticsearchServiceAccountToken()`). + ## Adding this module to your project dependencies Add the following dependency to your `pom.xml`/`build.gradle` file: diff --git a/docs/modules/hivemq.md b/docs/modules/hivemq.md index 0029204a06c..8bba4c18b36 100644 --- a/docs/modules/hivemq.md +++ b/docs/modules/hivemq.md @@ -2,7 +2,7 @@ ![hivemq logo](../modules_logos/hivemq-module.png) -Automatic starting HiveMQ docker containers for JUnit4 and JUnit5 tests. +Automatic starting HiveMQ docker containers for JUnit5 tests. This enables testing MQTT client applications and integration testing of custom HiveMQ extensions. - Community forum: https://community.hivemq.com/ diff --git a/docs/modules/k6.md b/docs/modules/k6.md index 4783ca1e5ad..13e0ddc9252 100644 --- a/docs/modules/k6.md +++ b/docs/modules/k6.md @@ -11,12 +11,23 @@ Testcontainers module for [k6](https://registry.hub.docker.com/r/grafana/k6). ## Basic script execution -Execute a simple k6 test script, `test.js`, with commandline options and injected script variable. +You can start a K6 container instance from any Java application by using: + + +[Setup the container](../../modules/k6/src/test/java/org/testcontainers/k6/K6ContainerTests.java) inside_block:standard_k6 + + +The test above uses a simple k6 script, `test.js`, with command line options and an injected script variable. + +Once the container is started, you can wait for the test results to be collected: + + +[Wait for test results](../../modules/k6/src/test/java/org/testcontainers/k6/K6ContainerTests.java) inside_block:wait + Create a simple k6 test script to be executed as part of your tests: -[Setup the container](../../modules/k6/src/test/java/org/testcontainers/k6/K6ContainerTests.java) inside_block:standard_k6 [Content of `scripts/test.js`](../../modules/k6/src/test/resources/scripts/test.js) inside_block:access_script_vars diff --git a/docs/modules/localstack.md b/docs/modules/localstack.md index 72d4fc843a7..ca51979f5a0 100644 --- a/docs/modules/localstack.md +++ b/docs/modules/localstack.md @@ -10,15 +10,21 @@ You can start a LocalStack container instance from any Java application by using [Container creation](../../modules/localstack/src/test/java/org/testcontainers/localstack/LocalStackContainerTest.java) inside_block:container +Environment variables listed in the [LocalStack configuration documentation](https://docs.localstack.cloud/references/configuration/) may be used to customize LocalStack's configuration. +Use the `.withEnv(key, value)` method on `LocalStackContainer` to apply configuration settings. + +!!! note + Starting March 23, 2026, `localstack/localstack` requires authentication via a `LOCALSTACK_AUTH_TOKEN` environment variable. Without it, the container will fail to start. + + Use `.withEnv("LOCALSTACK_AUTH_TOKEN", System.getenv("LOCALSTACK_AUTH_TOKEN"))` to pass the token. + See the [LocalStack blog post](https://blog.localstack.cloud/localstack-single-image-next-steps/) for more details. + ## Creating a client using AWS SDK [AWS SDK V2](../../modules/localstack/src/test/java/org/testcontainers/localstack/LocalStackContainerTest.java) inside_block:with_aws_sdk_v2 -Environment variables listed in [Localstack's README](https://github.com/localstack/localstack#configurations) may be used to customize Localstack's configuration. -Use the `.withEnv(key, value)` method on `LocalStackContainer` to apply configuration settings. - ## Adding this module to your project dependencies Add the following dependency to your `pom.xml`/`build.gradle` file: diff --git a/docs/modules/vault.md b/docs/modules/vault.md index 45d34844b7f..161efa8ccb0 100644 --- a/docs/modules/vault.md +++ b/docs/modules/vault.md @@ -4,7 +4,7 @@ Testcontainers module for [Vault](https://github.com/hashicorp/vault). Vault is ## Usage example -Start Vault container as a `@ClassRule`: +You can start a Vault container instance from any Java application by using: [Starting a Vault container](../../modules/vault/src/test/java/org/testcontainers/vault/VaultContainerTest.java) inside_block:vaultContainer @@ -22,21 +22,6 @@ Use Http API to read data from Vault container: [Use Http API to read data](../../modules/vault/src/test/java/org/testcontainers/vault/VaultContainerTest.java) inside_block:readFirstSecretPathOverHttpApi -Use client library to read data from Vault container: - - -[Use library to read data](../../modules/vault/src/test/java/org/testcontainers/vault/VaultContainerTest.java) inside_block:readWithLibrary - - -[See full example.](https://github.com/testcontainers/testcontainers-java/blob/master/modules/vault/src/test/java/org/testcontainers/vault/VaultContainerTest.java) - -## Why Vault in Junit tests? - -With the increasing popularity of Vault and secret management, applications are now needing to source secrets from Vault. -This can prove challenging in the development phase without a running Vault instance readily on hand. This library -aims to solve your apps integration testing with Vault. You can also use it to -test how your application behaves with Vault by writing different test scenarios in Junit. - ## Adding this module to your project dependencies Add the following dependency to your `pom.xml`/`build.gradle` file: diff --git a/docs/supported_docker_environment/continuous_integration/circle_ci.md b/docs/supported_docker_environment/continuous_integration/circle_ci.md index d6e85a62a79..936192cc799 100644 --- a/docs/supported_docker_environment/continuous_integration/circle_ci.md +++ b/docs/supported_docker_environment/continuous_integration/circle_ci.md @@ -1,7 +1,7 @@ # CircleCI (Cloud, Server v2.x, and Server v3.x) Your CircleCI configuration should use a dedicated VM for Testcontainers to work. You can achieve this by specifying the -executor type in your `.circleci/config.yml` to be `machine` instead of the default `docker` executor (see [Choosing an Executor Type](https://circleci.com/docs/2.0/executor-types/) for more info). +executor type in your `.circleci/config.yml` to be `machine` instead of the default `docker` executor (see [Choosing an Executor Type](https://circleci.com/docs/executor-intro) for more info). Here is a sample CircleCI configuration that does a checkout of a project and runs Maven: diff --git a/docs/test_framework_integration/junit_5.md b/docs/test_framework_integration/junit_5.md index 883adc90af9..aed2d515af9 100644 --- a/docs/test_framework_integration/junit_5.md +++ b/docs/test_framework_integration/junit_5.md @@ -1,7 +1,6 @@ # Jupiter / JUnit 5 -While Testcontainers is tightly coupled with the JUnit 4.x rule API, this module provides -an API that is based on the [JUnit Jupiter](https://junit.org/junit5/) extension model. +This module provides an API that is based on the [JUnit Jupiter](https://junit.org/junit5/) extension model. The extension supports two modes: @@ -58,10 +57,6 @@ using JUnit 5. ## Limitations -Since this module has a dependency onto JUnit Jupiter and on Testcontainers core, which -has a dependency onto JUnit 4.x, projects using this module will end up with both, JUnit Jupiter -and JUnit 4.x in the test classpath. - This extension has only been tested with sequential test execution. Using it with parallel test execution is unsupported and may have unintended side effects. ## Adding Testcontainers JUnit 5 support to your project dependencies diff --git a/docs/test_framework_integration/manual_lifecycle_control.md b/docs/test_framework_integration/manual_lifecycle_control.md index 6de3cb47196..e1005397c00 100644 --- a/docs/test_framework_integration/manual_lifecycle_control.md +++ b/docs/test_framework_integration/manual_lifecycle_control.md @@ -1,7 +1,6 @@ # Manual container lifecycle control -While Testcontainers was originally built with JUnit 4 integration in mind, it is fully usable with other test -frameworks, or with no framework at all. +Testcontainers is fully usable with any test framework, or with no framework at all. ## Manually starting/stopping containers diff --git a/examples/immudb/build.gradle b/examples/immudb/build.gradle index 4c2256983eb..a4d656dd762 100644 --- a/examples/immudb/build.gradle +++ b/examples/immudb/build.gradle @@ -15,7 +15,6 @@ dependencies { testImplementation 'ch.qos.logback:logback-classic:1.3.15' testImplementation 'org.junit.jupiter:junit-jupiter:5.13.4' testRuntimeOnly 'org.junit.platform:junit-platform-launcher:1.11.0' - testRuntimeOnly 'org.junit.platform:junit-platform-launcher:1.11.0' } test { diff --git a/examples/neo4j-container/build.gradle b/examples/neo4j-container/build.gradle index 5ba6faf08af..7a6eed0016d 100644 --- a/examples/neo4j-container/build.gradle +++ b/examples/neo4j-container/build.gradle @@ -14,3 +14,7 @@ dependencies { testImplementation 'org.junit.jupiter:junit-jupiter:5.13.4' testRuntimeOnly 'org.junit.platform:junit-platform-launcher:1.11.0' } + +test { + useJUnitPlatform() +} diff --git a/examples/neo4j-container/src/test/java/org/testcontainers/containers/Neo4jExampleTest.java b/examples/neo4j-container/src/test/java/org/testcontainers/containers/Neo4jExampleTest.java index 38c22a0ff45..bc8770aaef0 100644 --- a/examples/neo4j-container/src/test/java/org/testcontainers/containers/Neo4jExampleTest.java +++ b/examples/neo4j-container/src/test/java/org/testcontainers/containers/Neo4jExampleTest.java @@ -22,7 +22,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; -// junitExample { @Testcontainers class Neo4jExampleTest { @@ -68,4 +67,3 @@ void testSomethingUsingHttp() throws IOException { } } } -// } diff --git a/examples/ollama-hugging-face/src/test/java/com/example/ollamahf/OllamaHuggingFaceContainer.java b/examples/ollama-hugging-face/src/test/java/com/example/ollamahf/OllamaHuggingFaceContainer.java index 55fd110fa13..58267134a5f 100644 --- a/examples/ollama-hugging-face/src/test/java/com/example/ollamahf/OllamaHuggingFaceContainer.java +++ b/examples/ollama-hugging-face/src/test/java/com/example/ollamahf/OllamaHuggingFaceContainer.java @@ -28,14 +28,7 @@ protected void containerIsStarted(InspectContainerResponse containerInfo, boolea executeCommand("apt-get", "upgrade", "-y"); executeCommand("apt-get", "install", "-y", "python3-pip"); executeCommand("pip", "install", "huggingface-hub"); - executeCommand( - "huggingface-cli", - "download", - huggingFaceModel.repository, - huggingFaceModel.model, - "--local-dir", - "." - ); + executeCommand("hf", "download", huggingFaceModel.repository, huggingFaceModel.model, "--local-dir", "."); executeCommand("sh", "-c", String.format("echo '%s' > Modelfile", huggingFaceModel.modelfileContent)); executeCommand("ollama", "create", huggingFaceModel.model, "-f", "Modelfile"); executeCommand("rm", huggingFaceModel.model); @@ -48,7 +41,7 @@ private void executeCommand(String... command) throws ContainerLaunchException, ExecResult execResult = execInContainer(command); if (execResult.getExitCode() > 0) { throw new ContainerLaunchException( - "Failed to execute " + String.join(" ", command) + ": " + execResult.getStderr() + "Failed to execute " + String.join(" ", command) + ": " + execResult.getStdout() ); } } diff --git a/examples/settings.gradle b/examples/settings.gradle index 8d144867bbd..b9b58a917bf 100644 --- a/examples/settings.gradle +++ b/examples/settings.gradle @@ -5,7 +5,6 @@ buildscript { } } dependencies { - classpath "gradle.plugin.ch.myniva.gradle:s3-build-cache:0.10.0" classpath "com.gradle.enterprise:com.gradle.enterprise.gradle.plugin:3.17.4" classpath "com.gradle:common-custom-user-data-gradle-plugin:2.0.1" } diff --git a/gradle.properties b/gradle.properties index ce0f80d957e..f9e383482f4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,4 +3,4 @@ org.gradle.caching=true org.gradle.configureondemand=true org.gradle.jvmargs=-Xmx2g -testcontainers.version=2.0.1 +testcontainers.version=2.0.5 diff --git a/gradle/publishing.gradle b/gradle/publishing.gradle index 9ecd231d3e1..3e3faaf08ce 100644 --- a/gradle/publishing.gradle +++ b/gradle/publishing.gradle @@ -96,7 +96,7 @@ publishing { } repositories { maven { - url = layout.buildDirectory.dir('staging-deploy') + url = rootProject.layout.buildDirectory.dir('staging-deploy') } } } @@ -112,7 +112,7 @@ jreleaser { central { active = 'ALWAYS' url = 'https://central.sonatype.com/api/v1/publisher' - stagingRepository(layout.buildDirectory.dir("staging-deploy").get().toString()) + stagingRepository(rootProject.layout.buildDirectory.dir("staging-deploy").get().toString()) stage = 'UPLOAD' applyMavenCentralRules = true namespace = 'org.testcontainers' diff --git a/mkdocs.yml b/mkdocs.yml index 60e224f9dfa..ae447212912 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -137,7 +137,6 @@ nav: - Contributing: - contributing.md - contributing_docs.md - - bounty.md edit_uri: edit/main/docs/ extra: - latest_version: 2.0.1 + latest_version: 2.0.5 diff --git a/modules/activemq/build.gradle b/modules/activemq/build.gradle index f0ad74ba76b..c77b386698f 100644 --- a/modules/activemq/build.gradle +++ b/modules/activemq/build.gradle @@ -3,6 +3,6 @@ description = "Testcontainers :: ActiveMQ" dependencies { api project(':testcontainers') - testImplementation "org.apache.activemq:activemq-client:6.1.7" - testImplementation "org.apache.activemq:artemis-jakarta-client:2.42.0" + testImplementation "org.apache.activemq:activemq-client:6.2.4" + testImplementation "org.apache.activemq:artemis-jakarta-client:2.55.0" } diff --git a/modules/activemq/src/main/java/org/testcontainers/activemq/ActiveMQContainer.java b/modules/activemq/src/main/java/org/testcontainers/activemq/ActiveMQContainer.java index 14814d95da9..9313efc55d6 100644 --- a/modules/activemq/src/main/java/org/testcontainers/activemq/ActiveMQContainer.java +++ b/modules/activemq/src/main/java/org/testcontainers/activemq/ActiveMQContainer.java @@ -21,7 +21,11 @@ */ public class ActiveMQContainer extends GenericContainer { - private static final DockerImageName DEFAULT_IMAGE = DockerImageName.parse("apache/activemq-classic"); + private static final DockerImageName APACHE_ACTIVEMQ_CLASSIC_IMAGE = DockerImageName.parse( + "apache/activemq-classic" + ); + + private static final DockerImageName DEFAULT_IMAGE = DockerImageName.parse("apache/activemq"); private static final int WEB_CONSOLE_PORT = 8161; @@ -45,7 +49,7 @@ public ActiveMQContainer(String image) { public ActiveMQContainer(DockerImageName dockerImageName) { super(dockerImageName); - dockerImageName.assertCompatibleWith(DEFAULT_IMAGE); + dockerImageName.assertCompatibleWith(DEFAULT_IMAGE, APACHE_ACTIVEMQ_CLASSIC_IMAGE); withExposedPorts(WEB_CONSOLE_PORT, TCP_PORT, AMQP_PORT, STOMP_PORT, MQTT_PORT, WS_PORT); waitingFor(Wait.forLogMessage(".*Apache ActiveMQ.*started.*", 1).withStartupTimeout(Duration.ofMinutes(1))); diff --git a/modules/activemq/src/main/java/org/testcontainers/activemq/ArtemisContainer.java b/modules/activemq/src/main/java/org/testcontainers/activemq/ArtemisContainer.java index 7d4918a9306..82072993b48 100644 --- a/modules/activemq/src/main/java/org/testcontainers/activemq/ArtemisContainer.java +++ b/modules/activemq/src/main/java/org/testcontainers/activemq/ArtemisContainer.java @@ -9,6 +9,8 @@ /** * Testcontainers implementation for Apache ActiveMQ Artemis. *

+ * Supported images: {@code apache/artemis}, {@code apache/activemq-artemis} + *

* Exposed ports: *