refactor(build,ci): 현재 상태 검증을 걷어내고 불변조건만 남기는 검증 표면 축소
외부 리뷰("현재 상태를 유지하기 위한 검증이 너무 많고, 그 검증 자체를
다시 검증하는 구조까지 생겼다")를 설계 문서로 정리하고 코드로 반영한다.
설계·판단 근거는 docs/superpowers/specs/2026-09-16-verification-surface-reduction-design.md.
삭제
- .github/ci-gate-matrix.yml(1,025줄) + verify-gate-matrix.sh(568줄):
Gradle task graph와 workflow graph에 이미 있는 정보의 3중 복제
- verify-gradle-wrapper.sh(799줄): workflow 바이트 해시 잠금.
wrapper 검증은 gradle/actions/wrapper-validation(full SHA 핀)에 위임
- DeveloperExperienceContractTest 등의 CI YAML mutation 테스트:
애플리케이션 test suite가 GitHub Actions YAML 파서를 검증하던 계층 역전
- 문서 drift 파서: verifyReadmeCommands, verifyRunbookReferences,
verifyDocumentedLeafCount, verifyTestSourceSetRegistry
- 빈 레지스트리를 지키던 커스텀 YAML 파서: verifyTrivyignore,
verifyQuarantineSunset, flaky-quarantine.yaml
- verifyConfigurationPropertiesProcessor, verifyOneTypePerFile:
각각 ca.spring-config convention과 Checkstyle OneTopLevelClass가 대체
- 정상 입력으로도 성공할 수 없던 messaging always-fail task
- ModuleRegistry의 JSON 필드 집합 정확 일치, sample-portfolio negative guard
이동
- java/quality/spring 공통 설정을 configure(subprojects) 블록에서
ca.java-conventions / ca.quality-conventions / ca.java-library /
ca.spring-library convention plugin으로
- 아키텍처 검증을 ca.architecture로, JPA·messaging qualification을
gradle/qualification/ 아래로, verifyEnvKeys를 :app-bootstrap 소유로
완화
- Git revision은 releaseCheck·아카이브 생성에서만 요구. 일반 빌드는 SNAPSHOT
- SpotBugs/FindSecBugs는 로컬 check에서 빼고 qualityCheck 레인으로
task 계층
- leaf check는 그 leaf만. architectureCheck / qualityCheck /
configContractCheck / integrationCheck / ci / releaseCheck로 이름 분리
CI
- _reusable-gradle.yml 신규. checkout + wrapper validation + JDK/캐시 공통화
- fileserver-release.yml -> fileserver-certification.yml (CD가 아니라 certification)
- GitHub Actions = CI + artifact, Argo CD = CD 경계를 docs/ci-cd/boundary.md로 고정
순증감 +3,274 / -7,483.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
d00c76241c
commit
ef947e5bb0
@@ -1,27 +1,30 @@
|
||||
name: Set up Java and the Gradle cache
|
||||
name: Set up Java and Gradle
|
||||
description: >-
|
||||
Installs the repository's pinned Temurin JDK and restores the Gradle cache keyed on this
|
||||
repository's build files. Every Gradle job used to carry this block verbatim, so the JDK patch
|
||||
level and the cache key lived in fifty-nine places and could drift in any one of them.
|
||||
Installs the repository's pinned Temurin JDK, then configures Gradle through the official
|
||||
setup-gradle action — which validates every checked-in wrapper jar and manages the Gradle cache.
|
||||
Every Gradle job used to carry the JDK block verbatim, so the JDK patch level lived in fifty-nine
|
||||
places; every job also carried a separate three-line wrapper-validation step, so the pinned action
|
||||
SHA lived in forty.
|
||||
|
||||
# Deliberately NOT in this action: `actions/checkout` and the Gradle wrapper validation step.
|
||||
# Wrapper validation is INSIDE this action now.
|
||||
#
|
||||
# Neither can move here, and the reasons are different:
|
||||
# It could not be before, and the reason was not a GitHub limitation: .github/scripts/
|
||||
# verify-gradle-wrapper.sh read every workflow job and required it to contain, literally and in this
|
||||
# order, an `actions/checkout@` step, the exact three-field pinned wrapper-validation step, and then
|
||||
# the Gradle invocation. That literalness was the whole guard — "this job validated the wrapper" had
|
||||
# to be answerable from the workflow file alone — and it is what made the step uninlineable.
|
||||
#
|
||||
# * checkout — a `./.github/actions/...` reference is resolved from the checked-out working
|
||||
# copy, so the action file does not exist until checkout has already run. A composite action
|
||||
# cannot contain the step that makes itself readable.
|
||||
# * wrapper validation — .github/scripts/verify-gradle-wrapper.sh reads each workflow job and
|
||||
# requires it to contain, literally and in this order, an `actions/checkout@` step, the exact
|
||||
# three-field pinned wrapper-validation step, and then the Gradle invocation. That literalness
|
||||
# is the guard: it is what makes "this job validated the wrapper before running it" checkable
|
||||
# from the workflow file alone. Hiding the step behind an action would also break the guarded
|
||||
# `if: ${{ always() && steps.gradle-wrapper-validation.outcome == 'success' }}` form the same
|
||||
# script enforces, because a composite action's step ids are not visible to its caller — the
|
||||
# condition would silently evaluate to false and skip the step it was protecting.
|
||||
# That script is gone (it also byte-hashed all twelve workflow files, so a comment change needed a
|
||||
# hash update, while an attacker with write access would simply have updated both). The guarantee it
|
||||
# was protecting is now the official action's own: `gradle/actions/setup-gradle` validates all
|
||||
# wrapper jars by default (`validate-wrappers`, default true), and the action is pinned to a full
|
||||
# commit SHA here — which GitHub's own hardening guide calls the only immutable action reference.
|
||||
#
|
||||
# So a Gradle job is four lines of preamble (checkout, the three-line validation step) plus one
|
||||
# line for this action, instead of thirteen.
|
||||
# `actions/checkout` still cannot move here: a `./.github/actions/...` reference is resolved from the
|
||||
# checked-out working copy, so this file does not exist until checkout has already run. A composite
|
||||
# action cannot contain the step that makes itself readable.
|
||||
#
|
||||
# So a Gradle job is two lines — checkout, then this action.
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
@@ -30,8 +33,9 @@ runs:
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: "21.0.11+10"
|
||||
cache: gradle
|
||||
cache-dependency-path: |
|
||||
src/**/*.gradle
|
||||
src/**/gradle-wrapper.properties
|
||||
src/**/gradle.lockfile
|
||||
# Gradle's own caching, not setup-java's `cache: gradle`. The two cache the same directory with
|
||||
# different keys, and running both is how a job restores one cache and saves the other.
|
||||
- uses: gradle/actions/setup-gradle@3f131e8634966bd73d06cc69884922b02e6faf92 # gradle/actions@v6
|
||||
with:
|
||||
build-scan-publish: false
|
||||
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
|
||||
|
||||
Reference in New Issue
Block a user