diff --git a/build.gradle b/build.gradle index 6de2a95..df8d5ec 100644 --- a/build.gradle +++ b/build.gradle @@ -92,6 +92,14 @@ tasks.withType(JavaCompile).configureEach { tasks.withType(Test).configureEach { systemProperty 'file.encoding', 'UTF-8' jvmArgs '-Dfile.encoding=UTF-8' + + // Testcontainers 가 쓰는 docker-java 는 API 버전을 따로 주지 않으면 1.32 로 고정한다. + // Docker Engine 29 는 최소 API 가 1.40 이라 이 요청을 400 으로 거부하고, Testcontainers 는 + // "Docker 를 찾지 못함" 으로 판단해 통합 테스트를 조용히 건너뛴다(disabledWithoutDocker). + // 로컬(Docker Desktop, Engine 29)에서 스키마 정합성 검증이 한 번도 돌지 않던 이유다. + // CI 가 통과하는 건 러너가 아직 이전 Engine 이기 때문이라, 러너가 올라가면 CI 도 같은 상태가 된다. + // 1.44 는 Engine 25 이상이 지원하므로 로컬·CI 모두 안전하다. 필요하면 -Papi.version= 으로 덮어쓴다. + systemProperty 'api.version', project.findProperty('api.version') ?: '1.44' } tasks.named('test') { @@ -101,6 +109,22 @@ tasks.named('test') { excludeTags 'live' } finalizedBy(tasks.named('jacocoTestReport')) + + // 스키마 정합성 검증이 skip 되면 로컬에서도 크게 알린다. + // CI 는 같은 경우 빌드를 실패시키지만(ci-cd.yml "Assert schema validation actually ran"), + // 로컬은 초록불이 뜬 채 지나가서 Docker 가 없거나 연결이 안 되는 걸 아무도 몰랐다. + // 로컬에서 실패시키지는 않는다 — Docker 없이도 나머지 테스트는 돌려야 한다. + doLast { + def report = file("${buildDir}/test-results/test/TEST-com.carecode.integration.FlywaySchemaValidationTest.xml") + if (report.exists() && !(report.text =~ /skipped="0"/)) { + logger.warn(""" + | + |[경고] 스키마 정합성 검증(FlywaySchemaValidationTest)이 skip 됐습니다. + | Docker 가 없거나 연결되지 않았습니다. 마이그레이션과 엔티티가 어긋나도 이 빌드는 잡지 못합니다. + | Docker Desktop 을 켜고 다시 실행하세요. (CI 에서는 이 상태가 빌드 실패입니다) + |""".stripMargin()) + } + } } /** 공공데이터 실연동 점검. 키를 환경변수로 넘겨 수동 실행한다. */ diff --git a/docs/quality/regression-safety.md b/docs/quality/regression-safety.md index f5ecbf7..db5df7e 100644 --- a/docs/quality/regression-safety.md +++ b/docs/quality/regression-safety.md @@ -126,6 +126,35 @@ CI 에 실행 여부 검사를 넣었습니다. CI 는 `ubuntu-latest` 라 Docker 가 있으므로 정상 실행됩니다. 이 검사는 **환경이 바뀌어 조용히 빠지는 상황**을 막습니다. +### Docker 가 켜져 있는데도 skip 되던 문제 (#92) + +로컬(Windows + Docker Desktop, Engine 29)에서는 Docker 가 켜져 있어도 skip 됐습니다. + +| 요청 API 버전 | 결과 | +|---------------|------| +| 1.32 | **거부** (빈 `/info` 를 400 으로 반환) | +| 1.40 / 1.44 | 정상 | + +Testcontainers 가 쓰는 docker-java 는 API 버전을 따로 주지 않으면 **1.32 로 고정**합니다. +Engine 29 는 최소 API 가 1.40 이라 이 요청을 거부하고, Testcontainers 는 이를 "Docker 를 찾지 못함" 으로 +판단해 테스트를 건너뜁니다. Testcontainers 를 1.21.4, 2.0.5 로 올려도 같았습니다. + +`build.gradle` 의 테스트 태스크에서 `api.version=1.44` 를 넘겨 해결했습니다. 의존성은 바꾸지 않았습니다. +1.44 는 Engine 25 이상이 지원하므로 CI 에도 안전합니다. 다르게 주려면 `./gradlew test -Papi.version=1.45`. + +**CI 도 같은 시한폭탄을 안고 있었습니다.** 지금 CI 가 통과하는 건 러너가 아직 이전 Engine 이기 때문이고, +러너가 29 로 올라가면 위 검사가 빌드를 실패시켰을 겁니다. + +### 로컬에서도 알린다 + +로컬은 CI 처럼 실패시키지 않습니다 — Docker 없이도 나머지 테스트는 돌려야 합니다. +대신 skip 되면 테스트 끝에 경고를 띄웁니다. + +``` +[경고] 스키마 정합성 검증(FlywaySchemaValidationTest)이 skip 됐습니다. + Docker 가 없거나 연결되지 않았습니다. 마이그레이션과 엔티티가 어긋나도 이 빌드는 잡지 못합니다. +``` + ## 테스트 지형 ```mermaid