--- title: Gradle custom source set isolation failures source_type: error-note status: raw tags: [gradle, test-source-set, sample-off, archunit, ca-skeleton] created: 2026-06-25 --- # Gradle custom source set isolation failures ## Parent - [[raw/branch-notes/feature-sample-removal-adoption-contract]] ## Symptom `app-bootstrap`에 sample 없는 검증 축을 추가하기 위해 `sampleOffTest` source set/task를 만들자 단일 원인이 아니라 여러 tooling 경계가 순차적으로 실패했다. ## Causes - Strict dependency locking은 새 configuration마다 lock state가 필요하다. - Custom test source set은 `main` output을 명시하지 않으면 테스트 컴파일/실행 classpath가 일반 `test`와 달라진다. - ArchUnit `ImportOption.DoNotIncludeTests`는 Gradle 기본 test output은 제외하지만 custom `sampleOffTest` output은 production class처럼 import할 수 있다. - sample을 제거하면 일부 ArchUnit 규칙은 빈 corpus가 되어 `allowEmptyShould(true)`가 필요할 수 있다. - MVC slice smoke는 core controller를 명시 import하지 않으면 sample-off classpath에서 404가 날 수 있다. - `check`가 custom source set의 checkstyle/spotbugs task까지 전이 실행하면, 테스트 fixture용 스타일 위반이 release gate를 과도하게 막을 수 있다. ## Fix - `resolveAndLockAll --write-locks`로 `gradle.lockfile` 갱신. - `sampleOffTest`에 `sourceSets.main.output` 포함. - `ProductionClassImportOption`으로 기본 test output과 `sampleOffTest` output을 모두 제외. - sample 없는 corpus가 정상인 계약에는 `allowEmptyShould(true)` 적용. - `/healthcheck` smoke에 `HealthcheckController` 명시 import. - `checkstyleSampleOffTest`/`spotbugsSampleOffTest`는 warning-only policy로 두고, 실제 release-blocking sample-off 계약은 `sampleOffTest`에 둠. ## Verification - `./gradlew :app-bootstrap:sampleOffTest --no-daemon` - `./gradlew check verifyPublicPathSnapshot --no-daemon` - `bash .github/scripts/verify-gate-matrix.sh` ## Prevention Custom source set은 dependency graph만이 아니라 compile output, static-analysis task, ArchUnit import option, empty-corpus semantics까지 함께 설계한다.