diff --git a/.gitignore b/.gitignore index f8b92c3..456f721 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ .gradle build +release.sh +.env.release diff --git a/build.gradle.kts b/build.gradle.kts index 69bf39e..55dd91d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -43,11 +43,17 @@ subprojects { from(project.the()["main"].allSource) } + val javadocJar by tasks.registering(Jar::class) { + archiveClassifier.set("javadoc") + from(tasks.named("javadoc")) + } + extensions.configure("publishing") { publications { create("mavenJava") { from(components["java"]) artifact(sourcesJar.get()) + artifact(javadocJar.get()) pom { name.set("Spring Test Containers") @@ -81,7 +87,8 @@ subprojects { repositories { mavenLocal() maven { - url = layout.buildDirectory.dir("staging-deploy").get().asFile.toURI() + name = "staging" + url = rootProject.layout.buildDirectory.dir("staging-deploy").get().asFile.toURI() } } } @@ -106,3 +113,34 @@ jreleaser { } } } + +val installGitHooks by tasks.registering { + doLast { + val gitDir = File(rootDir, ".git") + val hooksDir = File(gitDir, "hooks") + val hookSource = File(rootDir, "scripts/git-hooks/pre-commit") + val hookTarget = File(hooksDir, "pre-commit") + + if (!hookSource.exists()) { + println("No pre-commit script found at ${hookSource.path}. Skipping hook installation.") + return@doLast + } + + if (!gitDir.exists()) { + println("Not a Git repository. Skipping Git hook installation.") + return@doLast + } + + println("Installing Git pre-commit hook...") + hookSource.copyTo(hookTarget, overwrite = true) + hookTarget.setExecutable(true) + println("✅ Git hook installed at: ${hookTarget.path}") + } +} + +// Automatically install Git hooks on project evaluation +if (System.getenv("CI") != "true") { + gradle.projectsEvaluated { + tasks.findByName("build")?.dependsOn("installGitHooks") + } +} diff --git a/git-hooks/install-hooks.sh b/git-hooks/install-hooks.sh deleted file mode 100755 index d7ccf66..0000000 --- a/git-hooks/install-hooks.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh - -# Script to install Git hooks - -echo "Installing Git hooks..." - -# Create hooks directory if it doesn't exist -mkdir -p .git/hooks - -# Copy pre-commit hook -cp git-hooks/pre-commit .git/hooks/ -chmod +x .git/hooks/pre-commit - -echo "Git hooks installed successfully." \ No newline at end of file diff --git a/modules/mysql/src/main/java/io/flowinquiry/testcontainers/jdbc/mysql/MySqlContainerProvider.java b/modules/mysql/src/main/java/io/flowinquiry/testcontainers/jdbc/mysql/MySqlContainerProvider.java index 3676100..5d205b2 100644 --- a/modules/mysql/src/main/java/io/flowinquiry/testcontainers/jdbc/mysql/MySqlContainerProvider.java +++ b/modules/mysql/src/main/java/io/flowinquiry/testcontainers/jdbc/mysql/MySqlContainerProvider.java @@ -4,13 +4,55 @@ import io.flowinquiry.testcontainers.jdbc.SpringAwareJdbcContainerProvider; import org.testcontainers.containers.MySQLContainer; +/** + * MySQL-specific implementation of the {@link SpringAwareJdbcContainerProvider}. + * + *

This class provides support for MySQL database containers in the Spring TestContainers + * framework. It creates and manages a {@link MySQLContainer} instance, which is a TestContainers + * implementation for MySQL databases. + * + *

This provider is automatically discovered by the {@link + * io.flowinquiry.testcontainers.jdbc.JdbcContainerProviderFactory} using Java's ServiceLoader + * mechanism when a test class is annotated with {@code @EnableMySQL}. + * + *

The provider handles: + * + *

    + *
  • Creating a MySQL container with the specified Docker image and version + *
  • Starting and stopping the container + *
  • Integrating the container with Spring's environment configuration + *
+ * + * @see SpringAwareJdbcContainerProvider + * @see MySQLContainer + * @see io.flowinquiry.testcontainers.jdbc.EnableMySQL + */ public class MySqlContainerProvider extends SpringAwareJdbcContainerProvider { + /** + * Returns the type of database managed by this provider. + * + *

This implementation returns {@link Rdbms#MYSQL}, indicating that this provider supports + * MySQL databases. + * + * @return {@link Rdbms#MYSQL} as the supported database type + */ @Override public Rdbms getType() { return Rdbms.MYSQL; } + /** + * Creates a new MySQL database container. + * + *

This method creates a {@link MySQLContainer} instance configured with the Docker image and + * version specified in the {@code @EnableMySQL} annotation on the test class. + * + *

The container is created but not started. The {@link #start()} method must be called to + * start the container before it can be used. + * + * @return a new {@link MySQLContainer} instance + */ @Override protected MySQLContainer createJdbcDatabaseContainer() { return new MySQLContainer<>(dockerImage + ":" + version); diff --git a/modules/postgresql/src/main/java/io/flowinquiry/testcontainers/jdbc/postgresql/PostgreSqlContainerProvider.java b/modules/postgresql/src/main/java/io/flowinquiry/testcontainers/jdbc/postgresql/PostgreSqlContainerProvider.java index b6ad7b6..135b652 100644 --- a/modules/postgresql/src/main/java/io/flowinquiry/testcontainers/jdbc/postgresql/PostgreSqlContainerProvider.java +++ b/modules/postgresql/src/main/java/io/flowinquiry/testcontainers/jdbc/postgresql/PostgreSqlContainerProvider.java @@ -5,13 +5,55 @@ import org.testcontainers.containers.JdbcDatabaseContainer; import org.testcontainers.containers.PostgreSQLContainer; +/** + * PostgreSQL-specific implementation of the {@link SpringAwareJdbcContainerProvider}. + * + *

This class provides support for PostgreSQL database containers in the Spring TestContainers + * framework. It creates and manages a {@link PostgreSQLContainer} instance, which is a + * TestContainers implementation for PostgreSQL databases. + * + *

This provider is automatically discovered by the {@link + * io.flowinquiry.testcontainers.jdbc.JdbcContainerProviderFactory} using Java's ServiceLoader + * mechanism when a test class is annotated with {@code @EnablePostgreSQL}. + * + *

The provider handles: + * + *

    + *
  • Creating a PostgreSQL container with the specified Docker image and version + *
  • Starting and stopping the container + *
  • Integrating the container with Spring's environment configuration + *
+ * + * @see SpringAwareJdbcContainerProvider + * @see PostgreSQLContainer + * @see io.flowinquiry.testcontainers.jdbc.EnablePostgreSQL + */ public class PostgreSqlContainerProvider extends SpringAwareJdbcContainerProvider { + /** + * Returns the type of database managed by this provider. + * + *

This implementation returns {@link Rdbms#POSTGRESQL}, indicating that this provider supports + * PostgreSQL databases. + * + * @return {@link Rdbms#POSTGRESQL} as the supported database type + */ @Override public Rdbms getType() { return Rdbms.POSTGRESQL; } + /** + * Creates a new PostgreSQL database container. + * + *

This method creates a {@link PostgreSQLContainer} instance configured with the Docker image + * and version specified in the {@code @EnablePostgreSQL} annotation on the test class. + * + *

The container is created but not started. The {@link #start()} method must be called to + * start the container before it can be used. + * + * @return a new {@link PostgreSQLContainer} instance + */ @Override protected JdbcDatabaseContainer createJdbcDatabaseContainer() { return new PostgreSQLContainer<>(dockerImage + ":" + version); diff --git a/git-hooks/pre-commit b/scripts/git-hooks/pre-commit similarity index 100% rename from git-hooks/pre-commit rename to scripts/git-hooks/pre-commit diff --git a/spring-testcontainers/src/main/java/io/flowinquiry/testcontainers/jdbc/JdbcContainerProviderFactory.java b/spring-testcontainers/src/main/java/io/flowinquiry/testcontainers/jdbc/JdbcContainerProviderFactory.java index 50de794..b1b72f5 100644 --- a/spring-testcontainers/src/main/java/io/flowinquiry/testcontainers/jdbc/JdbcContainerProviderFactory.java +++ b/spring-testcontainers/src/main/java/io/flowinquiry/testcontainers/jdbc/JdbcContainerProviderFactory.java @@ -2,8 +2,45 @@ import java.util.ServiceLoader; +/** + * Factory class for creating and configuring JDBC container providers. + * + *

This factory is responsible for discovering and initializing the appropriate {@link + * JdbcContainerProvider} implementation based on the database type specified in the {@link + * EnableJdbcContainer} annotation. + * + *

The factory uses Java's {@link ServiceLoader} mechanism to discover available provider + * implementations. It selects the provider that matches the requested database type, initializes it + * with the specified Docker image and version, and prepares it for use in tests. + * + *

This class is primarily used by the {@link JdbcExtension} to create container providers for + * test classes annotated with database-specific annotations like {@code @EnablePostgreSQL} or + * {@code @EnableMySQL}. + * + * @see JdbcContainerProvider + * @see EnableJdbcContainer + * @see ServiceLoader + */ public class JdbcContainerProviderFactory { + /** + * Creates and initializes a JDBC container provider for the specified configuration. + * + *

This method: + * + *

    + *
  1. Discovers all available {@link JdbcContainerProvider} implementations using the {@link + * ServiceLoader} mechanism + *
  2. Selects the provider that supports the database type specified in the {@link + * EnableJdbcContainer} annotation + *
  3. Initializes the provider with the specified Docker image and version + *
  4. Creates the JDBC database container + *
+ * + * @param enableJdbcContainer the annotation containing the database configuration + * @return a fully initialized JDBC container provider ready for use in tests + * @throws IllegalStateException if no provider is found for the specified database type + */ public static JdbcContainerProvider getProvider(EnableJdbcContainer enableJdbcContainer) { SpringAwareJdbcContainerProvider provider = (SpringAwareJdbcContainerProvider) diff --git a/spring-testcontainers/src/main/java/io/flowinquiry/testcontainers/jdbc/JdbcExtension.java b/spring-testcontainers/src/main/java/io/flowinquiry/testcontainers/jdbc/JdbcExtension.java index 4ba0c52..9f36b1c 100644 --- a/spring-testcontainers/src/main/java/io/flowinquiry/testcontainers/jdbc/JdbcExtension.java +++ b/spring-testcontainers/src/main/java/io/flowinquiry/testcontainers/jdbc/JdbcExtension.java @@ -10,12 +10,45 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +/** + * A JUnit 5 extension that manages JDBC database containers for integration testing. + * + *

This extension automatically starts and stops database containers based on annotations present + * on the test class. It works with meta-annotations that are themselves annotated with {@link + * EnableJdbcContainer}, such as {@code @EnablePostgreSQL}, {@code @EnableMySQL}, etc. + * + *

The extension handles the lifecycle of database containers: + * + *

    + *
  • Before all tests: Detects database configuration from annotations and starts the + * appropriate container + *
  • After all tests: Stops the container and cleans up resources + *
+ * + *

Usage example: + * + *

{@code
+ * @EnablePostgreSQL
+ * class MyIntegrationTest {
+ *     // Test methods that require a PostgreSQL database
+ * }
+ * }
+ */ public class JdbcExtension implements BeforeAllCallback, AfterAllCallback { private static final Logger log = LoggerFactory.getLogger(JdbcExtension.class); private JdbcContainerProvider provider; + /** + * Called before all tests in the current test class. + * + *

This method detects the database configuration from annotations on the test class, creates + * the appropriate container provider, and starts the database container if needed. If a container + * for this test class is already running, it reuses the existing container. + * + * @param context the extension context for the test class + */ @Override public void beforeAll(ExtensionContext context) { Class testClass = context.getRequiredTestClass(); @@ -33,6 +66,14 @@ public void beforeAll(ExtensionContext context) { } } + /** + * Called after all tests in the current test class have completed. + * + *

This method stops the database container if it was started by this extension and removes the + * container reference from the registry to allow proper cleanup. + * + * @param context the extension context for the test class + */ @Override public void afterAll(ExtensionContext context) { if (provider != null) { @@ -88,6 +129,19 @@ private Annotation findNearestAnnotationWith( return null; } + /** + * Builds a resolved JDBC container configuration from a source annotation and its + * meta-annotation. + * + *

This method extracts configuration values (version and dockerImage) from the source + * annotation and combines them with the database type (rdbms) from the meta-annotation to create + * a complete {@link EnableJdbcContainer} configuration. + * + * @param sourceAnnotation the source annotation containing version and dockerImage values + * @param meta the meta-annotation containing the database type (rdbms) + * @return a resolved {@link EnableJdbcContainer} configuration + * @throws IllegalStateException if reflection fails to extract values from the source annotation + */ private EnableJdbcContainer buildResolvedJdbcConfig( Annotation sourceAnnotation, EnableJdbcContainer meta) { try {