refactor(build,src): testkit 소스셋 이관과 빌드 게이트 정상화, 미추적 빌드 파일 추적

한 커밋인 이유: src/build.gradle 안에서 ca.testkit-publisher 플러그인 제거와
게이트 수정이 얽혀 있다. 플러그인 적용부만 빼면 web·websocket·persistence-jpa·
persistence-mongo·app-bootstrap 이 사라진 testkitPublisher() 와 *Testkit
컨피규레이션을 계속 참조해 설정 단계에서 빌드가 죽는다. 파일 단위로 나눌 수 없다.

1) testkit 소스셋 → Gradle 표준 java-test-fixtures 이관
   web, websocket, persistence-jpa, persistence-mongo, httpclient, graphql 과
   이들의 testkit 컨피규레이션을 소비하던 app-bootstrap.
   자체 제작 ca.testkit-publisher.gradle 77줄이 사라진다.

2) 실행되지 않거나 실패할 수 없던 빌드 게이트 정상화 (E등급)
   - strict-test-lane 의 실행 카운터가 skip 을 실행으로 세던 것 수정.
     전부 skip 인 레인은 이제 실패한다 (회귀 테스트 2건 추가)
   - public-path 스냅샷이 gitignore 된 src/.env 를 읽던 것을
     config/security.yml 의 바인딩 기본값으로 교체
   - verifyEnvKeys 가 build/ 산출물을 소스로 읽어 삭제된 키를 사용 중으로
     오판하던 것 수정 (입력 4,637 → 4,630 파일)
   - jpa-evidence 가 git 실패를 "워크트리 깨끗함"으로 읽던 것을 fail-closed 로
   - notification-evidence 의 Grade 열 탐지를 헤더 기준으로 교체 +
     표 부재 시 fail-closed
   - spring70CompatibilityTest 가 레인을 복제하며 잃은 fail-closed 복구
     (태스크명 유지 — 워크플로 3곳과 gate-matrix 린트 무손상)
   - 메시징 R2 스켈레톤 주변의 도달 불가 검증 45줄을 MSG-015 명시적 실패로 교체

3) git 에 없던 빌드 필수 파일 추적
   - src/gradle/libs.versions.toml — src/build.gradle 이 9곳에서 참조하는데
     추적되지 않아 깨끗한 체크아웃에서 설정이 실패했다
   - app-bootstrap config/*.yml 15개 — application.yml 이 전부 import 한다.
     하드코딩된 시크릿은 없고 값은 secret://environment/APP_* 참조다

4) 진행 중이던 구현 작업 반영 (redis/idempotency 구성, startup 검증,
   아키텍처 테스트 클래스, notification 콜백 레지스트리 등)

검증:
- 깨끗한 체크아웃에서 ./gradlew help 통과
- :app-bootstrap:test --tests 'dev.caskeleton.bootstrap.architecture.*'
  → 20개 클래스 174 tests, 실패 0, 스킵 0 (이전에는 0개 실행)

미해결: verifyOneTypePerFile 은 손대지 않았다(Checkstyle 로 교체 권고).
B/C/D 등급 100여 건과 CI 단계 분리는 별도 작업 —
docs/superpowers/plans/2026-09-16-ci-stage-separation.md 참고.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
DongHyeonka
2026-09-16 16:53:25 +09:00
co-authored by Claude Opus 5
parent e34519113b
commit 1535481794
397 changed files with 8912 additions and 5916 deletions
@@ -1,3 +1,7 @@
// Shared test code as a Gradle test-fixtures variant — ADR-BUILD-001. Applied here rather than
// from the root, the way the GraphQL leaf does: only a leaf that has shared test code needs it.
apply plugin: 'java-test-fixtures'
// MongoDB Document Persistence Platform leaf — see
// docs/superpowers/specs/2026-08-11-mongodb-document-persistence-platform-design.md (design package)
// and docs/mongodb/repository-adaptation.md (how the design's 19 stable + 12 advanced library
@@ -30,7 +34,7 @@ dependencies {
// The design's module dependency table is enforced as package rules, so ArchUnit is what keeps
// "packages instead of modules" from meaning "no boundary at all".
testImplementation 'com.tngtech.archunit:archunit-junit5:1.3.0'
testImplementation libs.archunit.junit5
testImplementation 'io.projectreactor:reactor-test'
// Real replica set / failover / migration lanes (design §29). Test-scoped so no production
// package can reach a container fixture.
@@ -40,32 +44,43 @@ dependencies {
testImplementation 'org.testcontainers:testcontainers-toxiproxy'
}
// The testkit is its own source set rather than part of `test` because several lanes consume it and
// because the design forbids a production module from depending on the testkit. Declaring its
// dependencies only on the test configurations gives that guarantee without a new Gradle project.
strictTestLanes {
// The testkit compiles against exactly what a test does: `implementation` inheritance runs
// through testImplementation, so this is the module's own dependencies plus the test libraries.
sourceSet('testkit') { compilesAgainst 'main' }
sourceSet('mongoPerformanceTest') { compilesAgainst 'main', 'testkit' }
}
// Every test lane compiles and runs against the testkit.
// Shared test code lives in src/testFixtures, per ADR-BUILD-001. This leaf is the first migration
// off `ca.testkit-publisher`: one leaf, two lanes, no cross-module consumer — the proof that the
// path works before the published testkits follow.
//
// No publishAs: this leaf's testkit is consumed inside the leaf and is not offered to the
// composition root, unlike the JPA one whose ArchUnit rule pack the root applies to the production
// graph. Publishing is opt-in in the convention precisely so that difference stays a decision.
testkitPublisher {
consumedBy 'test'
// `java-test-fixtures` creates the source set and puts it on `test`'s classpath itself, so neither a
// `sourceSet('testFixtures')` declaration nor a `testFixturesPublisher { consumedBy 'test' }` is needed.
// The performance lane is not `test` and still has to say it consumes the fixtures, which is what
// `compilesAgainst` is for — it looks a source set up rather than creating one, so naming a
// plugin-created set works unchanged.
//
// What is given up: the convention's opt-in publishing. This leaf's fixtures are now a consumable
// variant whether or not anybody asks for them. ADR-BUILD-001 records that as an accepted loss —
// unconsumed fixtures are unconsumed, and a leaf that genuinely must not offer them needs a module,
// not a third convention.
strictTestLanes {
sourceSet('mongoPerformanceTest') { compilesAgainst 'main', 'testFixtures' }
}
// The fixtures declare what they compile against, rather than inheriting the test configuration.
//
// The `testkit` source set used to extend `testImplementation`, so it silently saw every test
// library this leaf declared. That is convenient and it is also how a fixture acquires a dependency
// nobody chose for it. Listing them here is three more lines and makes the fixtures' own surface
// reviewable — the same model the GraphQL leaf already uses.
dependencies {
testkitImplementation 'com.tngtech.archunit:archunit-junit5:1.3.0'
testkitImplementation 'io.projectreactor:reactor-test'
testkitImplementation 'org.testcontainers:testcontainers'
testkitImplementation 'org.testcontainers:testcontainers-junit-jupiter'
testkitImplementation 'org.testcontainers:testcontainers-mongodb'
testkitImplementation 'org.testcontainers:testcontainers-toxiproxy'
testFixturesImplementation libs.archunit.junit5
testFixturesImplementation 'io.projectreactor:reactor-test'
testFixturesImplementation 'org.assertj:assertj-core'
testFixturesImplementation 'org.mongodb:bson'
// The ArchUnit rule pack names Spring Data's Repository marker in a rule, so it needs the
// type on its compile classpath even though it never calls it.
testFixturesImplementation 'org.springframework.data:spring-data-commons'
testFixturesImplementation 'org.testcontainers:testcontainers'
testFixturesImplementation 'org.testcontainers:testcontainers-junit-jupiter'
testFixturesImplementation 'org.testcontainers:testcontainers-mongodb'
testFixturesImplementation 'org.testcontainers:testcontainers-toxiproxy'
testFixturesImplementation libs.toxiproxy.java
}
// Pinned server images. The design forbids `latest` for a certification lane (Task 44): a mutable