63 lines
5.1 KiB
Markdown
63 lines
5.1 KiB
Markdown
---
|
|
title: error / gradle-strict-lock-stale-entry-non-resolvable-config-2026-07-08
|
|
source_type: error-note
|
|
status: raw
|
|
related_branches: [chore-ulid-to-uuidv7]
|
|
related_projects: [ca-skeleton]
|
|
tags: [error, ca-skeleton, gradle, dependency-locking, strict-lock, resolveAndLockAll, sampleFixture]
|
|
created: 2026-07-08
|
|
status_label: resolved
|
|
---
|
|
|
|
# error: gradle-strict-lock-stale-entry-non-resolvable-config-2026-07-08
|
|
|
|
> Layer: `raw/errors/` — 작업 중 마주친 단일 실패·트러블슈팅 기록. 원본은 raw에 영구 보관한다.
|
|
|
|
## Parent / 부모
|
|
|
|
- [[raw/branch-notes/chore-ulid-to-uuidv7]] — ULID→UUIDv7 리팩터에서 `ulid-creator`→`uuid-creator` 의존 교체 + 락 재생성 중 발생.
|
|
- [[raw/project-notes/ca-skeleton-operational-contract]] — ca-tmpl STRICT dependency-locking(D8) 운영 이슈.
|
|
|
|
## 증상 / Symptom
|
|
|
|
- `com.github.f4b6a3:ulid-creator:5.2.3` → `uuid-creator:6.1.1` 로 build.gradle 2곳을 바꾸고 `cd src && ./gradlew resolveAndLockAll --write-locks` (BUILD SUCCESSFUL) 실행 후에도, `app-bootstrap/gradle.lockfile` 에 **낡은 줄이 남음**:
|
|
```text
|
|
com.github.f4b6a3:ulid-creator:5.2.3=sampleFixture
|
|
com.github.f4b6a3:uuid-creator:6.1.1=productionRuntimeClasspath,runtimeClasspath,sampleOffTestRuntimeClasspath,testRuntimeClasspath
|
|
```
|
|
즉 `uuid-creator` 는 resolvable config 들에 잡혔지만 `sampleFixture` config 태그는 여전히 `ulid-creator` 를 가리킴.
|
|
- 발생 컨텍스트: 의존 교체 후 STRICT lock 재생성. 발생 시점: 2026-07-08. 재현 가능 여부: `always` — non-resolvable config 를 통과하는 의존이 버전 변경될 때마다.
|
|
|
|
## 재현 절차 / Reproduction
|
|
|
|
1. `app-bootstrap/build.gradle` 처럼 `configurations { sampleFixture { canBeConsumed=false; canBeResolved=false } }` 를 두고 `testCompileClasspath.extendsFrom sampleFixture` 로 확장.
|
|
2. `sampleFixture project(':sample-portfolio')` 가 끌어오는 **전이 의존의 버전**을 바꿈(여기선 sample-portfolio 의 `ulid-creator`→`uuid-creator`).
|
|
3. `cd src && ./gradlew resolveAndLockAll --write-locks` 실행.
|
|
4. 기대: 모든 lock 태그가 새 좌표로 갱신. 실제: `=sampleFixture` 로만 태그된 낡은 좌표가 lockfile 에 잔존.
|
|
|
|
## 근본 원인 / Root cause
|
|
|
|
- 직접 원인: `resolveAndLockAll` 태스크 본문이 `configurations.findAll { it.canBeResolved }.each { it.resolve() }` — `canBeResolved = false` 인 `sampleFixture` 는 필터에서 제외되어 **직접 resolve 되지 않음**. `--write-locks` 는 그 실행에서 resolve 된 config 의 lock 항목만 다시 씀. resolve 안 된 config 의 기존 항목은 **삭제/갱신되지 않고 보존**된다.
|
|
- 근본 원인: STRICT lock 이 실패하지 않는 이유 — `sampleFixture` 는 어떤 빌드에서도 직접 resolve 되지 않으므로 그 태그의 lock 항목은 검증되지 않는다(확장 대상인 `testRuntimeClasspath` 등은 새 `uuid-creator` 로 올바르게 검증됨). 그래서 조용히 통과하지만, 커밋되는 lockfile 에 사라진 의존(`ulid-creator`)이 남아 "ULID 완전 제거" 계약을 위반.
|
|
|
|
## 해결 / Resolution
|
|
|
|
- 적용한 조치: lockfile 수동 병합 — 낡은 `ulid-creator:5.2.3=sampleFixture` 줄을 삭제하고, `uuid-creator:6.1.1` 줄의 config 목록에 `sampleFixture` 를 **알파벳 위치**(runtimeClasspath 다음, sampleOffTestRuntimeClasspath 앞)에 삽입:
|
|
```text
|
|
com.github.f4b6a3:uuid-creator:6.1.1=productionRuntimeClasspath,runtimeClasspath,sampleFixture,sampleOffTestRuntimeClasspath,testRuntimeClasspath
|
|
```
|
|
(sample-portfolio→uuid-creator 이므로 sampleFixture 가 uuid-creator 를 포함하는 것이 올바른 상태. resolvable config 목록은 건드리지 않아 누락 위험 없음.)
|
|
- 검증 방법: `cd src && ./gradlew check` (내부에서 `verifyDependencyLocks` STRICT 재해석) BUILD SUCCESSFUL — lockfile 일관성 확인. 전 lockfile grep 으로 `ulid-creator` 0건 확인.
|
|
- 잔여 위험 / 후속: 대안 = `sampleFixture { canBeResolved = true }` 로 일시 전환 후 `resolveAndLockAll` 재실행하고 원복. 수동 편집보다 재현성은 높으나 build.gradle 변경 위험이 있어 이번엔 타깃 lock 편집을 택함.
|
|
|
|
## 회고 / Lessons
|
|
|
|
- 빨리 감지하는 신호: 전이 의존 버전을 바꾼 뒤 **모든 `*.lockfile` 에서 OLD 좌표를 grep** 한다 — `resolveAndLockAll` 성공 로그만 믿지 않는다.
|
|
- 예방 체크리스트: `canBeResolved=false` 인 aggregation/bucket config(예: `sampleFixture`)는 `resolveAndLockAll` 의 `findAll { it.canBeResolved }` 필터에서 빠진다 → 그 태그의 lock 항목은 자동 갱신 안 됨. 버킷을 확장하는 resolvable config 는 갱신되지만 버킷 태그 자체는 stale 로 남는다.
|
|
- 일반화된 교훈: Gradle STRICT locking 에서 "빌드가 통과한다 ≠ lockfile 이 깨끗하다". non-resolvable config 의 lock 항목은 검증 사각지대라, 의존 삭제/교체 시 수동 대조가 필요하다.
|
|
|
|
## Related / 관련
|
|
|
|
- 관련 branch note: [[raw/branch-notes/chore-ulid-to-uuidv7]]
|
|
- 관련 계약: [[raw/branch-notes/feature-resource-identifier-contract]] (식별자 생성 라이브러리 의존의 owner)
|