Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 1 addition & 14 deletions api-gateway-iam/api-gateway-iam-api/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,16 +1,3 @@
plugins {
`java-library`
}

dependencies {
api("jakarta.validation:jakarta.validation-api")
api("com.fasterxml.jackson.core:jackson-annotations")

testImplementation("org.junit.jupiter:junit-jupiter")
testImplementation("org.assertj:assertj-core")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}

tasks.withType<Test> {
useJUnitPlatform()
id("stablebridge.api-library")
}

This file was deleted.

11 changes: 1 addition & 10 deletions api-gateway-iam/api-gateway-iam-client/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,16 +1,7 @@
plugins {
`java-library`
id("stablebridge.client-library")
}

dependencies {
api(project(":api-gateway-iam:api-gateway-iam-api"))
implementation("org.springframework.cloud:spring-cloud-starter-openfeign")

testImplementation("org.junit.jupiter:junit-jupiter")
testImplementation("org.assertj:assertj-core")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}

tasks.withType<Test> {
useJUnitPlatform()
}
194 changes: 5 additions & 189 deletions api-gateway-iam/api-gateway-iam/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,202 +1,18 @@
plugins {
id("org.springframework.boot")
id("com.google.cloud.tools.jib")
java
`java-test-fixtures`
jacoco
id("stablebridge.service")
}

jib {
from {
image = "docker://eclipse-temurin:25-jre"
}
to {
image = "stablebridge/api-gateway-iam"
tags = setOf("latest")
}
container {
creationTime.set("USE_CURRENT_TIMESTAMP")
}
stablebridge {
jibImageName.set("stablebridge/api-gateway-iam")
jacocoMinimum.set("0.45")
}

val integrationTestSourceSet: SourceSet = sourceSets.create("integrationTest") {
java.srcDir("src/integration-test/java")
resources.srcDir("src/integration-test/resources")
compileClasspath += sourceSets.main.get().output + sourceSets.test.get().output
runtimeClasspath += sourceSets.main.get().output + sourceSets.test.get().output
}

configurations {
named("integrationTestImplementation") { extendsFrom(configurations.testImplementation.get()) }
named("integrationTestRuntimeOnly") { extendsFrom(configurations.testRuntimeOnly.get()) }
}

tasks.register<Test>("integrationTest") {
testClassesDirs = integrationTestSourceSet.output.classesDirs
classpath = integrationTestSourceSet.runtimeClasspath
shouldRunAfter(tasks.test)
configure<JacocoTaskExtension> { isEnabled = false }
}

val businessTestSourceSet: SourceSet = sourceSets.create("businessTest") {
java.srcDir("src/business-test/java")
resources.srcDir("src/business-test/resources")
compileClasspath += sourceSets.main.get().output + sourceSets.test.get().output + integrationTestSourceSet.output
runtimeClasspath += sourceSets.main.get().output + sourceSets.test.get().output + integrationTestSourceSet.output
}

configurations {
named("businessTestImplementation") { extendsFrom(configurations.named("integrationTestImplementation").get()) }
named("businessTestRuntimeOnly") { extendsFrom(configurations.named("integrationTestRuntimeOnly").get()) }
}

tasks.register<Test>("businessTest") {
testClassesDirs = businessTestSourceSet.output.classesDirs
classpath = businessTestSourceSet.runtimeClasspath
shouldRunAfter(tasks.named("integrationTest"))
configure<JacocoTaskExtension> { isEnabled = false }
}

val lombokVersion: String by project
val mapstructVersion: String by project
val lombokMapstructBindingVersion: String by project
val resilience4jVersion: String by project
val flywayVersion: String by project
val archunitVersion: String by project
val testcontainersVersion: String by project
val wiremockVersion: String by project
val springdocVersion: String by project

dependencies {
implementation(project(":api-gateway-iam:api-gateway-iam-api"))

// Spring Boot
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-validation")
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.boot:spring-boot-starter-actuator")

// OpenAPI / Swagger UI
implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:$springdocVersion")
runtimeOnly("io.micrometer:micrometer-registry-prometheus")
implementation("io.micrometer:micrometer-tracing-bridge-otel")
implementation("io.opentelemetry:opentelemetry-exporter-otlp")
implementation("org.springframework.boot:spring-boot-starter-security")
// Redis
implementation("org.springframework.boot:spring-boot-starter-data-redis")

// Kafka via Spring Cloud Stream
implementation("org.springframework.cloud:spring-cloud-stream")
implementation("org.springframework.cloud:spring-cloud-stream-binder-kafka")
implementation("org.springframework.kafka:spring-kafka")

// Feign
implementation("org.springframework.cloud:spring-cloud-starter-openfeign")

// Resilience4j
implementation("io.github.resilience4j:resilience4j-spring-boot3:$resilience4jVersion")
implementation("io.github.resilience4j:resilience4j-circuitbreaker:$resilience4jVersion")

// MapStruct
implementation("org.mapstruct:mapstruct:$mapstructVersion")
annotationProcessor("org.mapstruct:mapstruct-processor:$mapstructVersion")
annotationProcessor("org.projectlombok:lombok-mapstruct-binding:$lombokMapstructBindingVersion")

// Auth — JWT ES256 (Nimbus, BOM-managed via oauth2-jose)
implementation("org.springframework.security:spring-security-oauth2-jose")

// Database
runtimeOnly("org.postgresql:postgresql")
implementation("org.springframework.boot:spring-boot-starter-flyway")
implementation("org.flywaydb:flyway-database-postgresql:$flywayVersion")

// Outbox (namastack)
implementation("io.namastack:namastack-outbox-starter-jdbc:1.1.0")

// Test fixtures
testFixturesImplementation("org.assertj:assertj-core")
testFixturesImplementation("org.mockito:mockito-core")

// Test
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.springframework.kafka:spring-kafka-test")
testImplementation("com.tngtech.archunit:archunit-junit5:$archunitVersion")
"integrationTestImplementation"(testFixtures(project))
"integrationTestImplementation"("org.testcontainers:postgresql:$testcontainersVersion")
"integrationTestImplementation"("org.testcontainers:kafka:$testcontainersVersion")
"integrationTestImplementation"("org.testcontainers:junit-jupiter:$testcontainersVersion")
"integrationTestImplementation"("org.wiremock:wiremock-standalone:$wiremockVersion")
"integrationTestImplementation"("org.springframework.boot:spring-boot-starter-webmvc-test")
"integrationTestImplementation"("org.springframework.boot:spring-boot-starter-security-test")
}

tasks.withType<JavaCompile> {
options.compilerArgs.addAll(listOf(
"-Amapstruct.defaultComponentModel=spring",
"-Amapstruct.unmappedTargetPolicy=IGNORE"
))
}

tasks.withType<Test> {
jvmArgs("-Dnet.bytebuddy.experimental=true")
useJUnitPlatform()
testLogging {
events("passed", "skipped", "failed")
showExceptions = true
showCauses = true
showStackTraces = true
exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
}
}

jacoco {
toolVersion = "0.8.14"
}

tasks.test {
configure<JacocoTaskExtension> {
excludes = listOf("sun.*", "jdk.*", "com.sun.*", "java.*", "javax.*")
}
finalizedBy(tasks.jacocoTestReport)
}

val jacocoExclusions = listOf(
"**/entity/**",
"**/mapper/**",
"**/config/**",
"**/*Application*",
"**/generated/**",
"**/*MapperImpl*"
)

tasks.jacocoTestReport {
dependsOn(tasks.test)
reports {
xml.required.set(true)
html.required.set(true)
}
classDirectories.setFrom(files(classDirectories.files.map {
fileTree(it) { exclude(jacocoExclusions) }
}))
}

tasks.jacocoTestCoverageVerification {
dependsOn(tasks.jacocoTestReport)
violationRules {
rule {
limit {
minimum = "0.45".toBigDecimal()
}
}
}
classDirectories.setFrom(files(classDirectories.files.map {
fileTree(it) { exclude(jacocoExclusions) }
}))
}

tasks.named("check") {
dependsOn(
tasks.named("integrationTest"),
tasks.named("businessTest"),
tasks.jacocoTestCoverageVerification
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,54 +11,27 @@
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.KafkaContainer;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.lifecycle.Startable;
import org.testcontainers.utility.DockerImageName;

import static com.stablecoin.payments.platform.test.TestContainerSupport.kafka;
import static com.stablecoin.payments.platform.test.TestContainerSupport.postgres;
import static com.stablecoin.payments.platform.test.TestContainerSupport.redis;
import static com.stablecoin.payments.platform.test.TestContainerSupport.registerKafkaProperties;
import static com.stablecoin.payments.platform.test.TestContainerSupport.registerPostgresProperties;
import static com.stablecoin.payments.platform.test.TestContainerSupport.registerRedisProperties;
import static com.stablecoin.payments.platform.test.TestContainerSupport.startAll;

@SuppressWarnings("resource")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles("integration-test")
@AutoConfigureMockMvc
public abstract class AbstractIntegrationTest {

static final PostgreSQLContainer<?> POSTGRES =
new PostgreSQLContainer<>("postgres:16-alpine")
.withDatabaseName("s10_api_gateway_iam")
.withUsername("test")
.withPassword("test");

protected static final KafkaContainer KAFKA =
new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:7.6.0"));

protected static final GenericContainer<?> REDIS =
new GenericContainer<>(DockerImageName.parse("redis:7-alpine"))
.withExposedPorts(6379);
static final PostgreSQLContainer<?> POSTGRES = postgres("s10_api_gateway_iam");
protected static final KafkaContainer KAFKA = kafka();
protected static final GenericContainer<?> REDIS = redis();

static {
try {
POSTGRES.start();
KAFKA.start();
REDIS.start();
} catch (RuntimeException ex) {
safeStop(REDIS);
safeStop(KAFKA);
safeStop(POSTGRES);
throw ex;
}
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
safeStop(REDIS);
safeStop(KAFKA);
safeStop(POSTGRES);
}, "testcontainers-shutdown"));
}

private static void safeStop(Startable container) {
try {
if (container != null) {
container.stop();
}
} catch (Exception ignored) {
// best-effort cleanup
}
startAll(POSTGRES, KAFKA, REDIS);
}

@Autowired
Expand All @@ -81,12 +54,8 @@ void cleanDatabase() {

@DynamicPropertySource
static void configureProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", POSTGRES::getJdbcUrl);
registry.add("spring.datasource.username", POSTGRES::getUsername);
registry.add("spring.datasource.password", POSTGRES::getPassword);
registry.add("spring.kafka.bootstrap-servers", KAFKA::getBootstrapServers);
registry.add("spring.cloud.stream.kafka.binder.brokers", KAFKA::getBootstrapServers);
registry.add("spring.data.redis.host", REDIS::getHost);
registry.add("spring.data.redis.port", () -> REDIS.getMappedPort(6379));
registerPostgresProperties(registry, POSTGRES);
registerKafkaProperties(registry, KAFKA);
registerRedisProperties(registry, REDIS);
}
}

This file was deleted.

Loading
Loading