46 lines
2.2 KiB
Markdown
46 lines
2.2 KiB
Markdown
---
|
|
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까지 함께 설계한다.
|