Files
llm-wiki/wiki/blog/ca-tmpl-devops-ci-supply-chain-dx-2026-07-02.md

10 KiB

title, source_type, status, confidence, tags, related_projects, last_reviewed, canonical_sources, audience, target_publish, status_label
title source_type status confidence tags related_projects last_reviewed canonical_sources audience target_publish status_label
CI와 Supply Chain을 Skeleton 계약으로 묶기 blog verified high
blog
ca-tmpl
devops
ci-cd
supply-chain
ca-tmpl
2026-07-03
wiki/projects/ca-tmpl/devops-ci-supply-chain-dx
backend-engineer ready

CI와 Supply Chain을 Skeleton 계약으로 묶기

Parent / 부모 (필수)

타깃 독자 / Target reader

  • 독자 profile: template repo의 CI, static analysis, release/supply-chain baseline을 설계하려는 엔지니어.
  • 이미 안다고 가정하는 것: Gradle, GitHub Actions, dependency lock, SBOM, static analysis.
  • 처음 듣는다고 가정하는 것: CI를 도구 목록이 아니라 gate ownership, drift check, release evidence의 계약으로 보는 방식.

도입 / Hook

CI에 도구를 많이 붙이는 것은 어렵지 않습니다. formatter, linter, unit test, integration test, vulnerability scanner, SBOM, signing, provenance를 순서대로 추가하면 화면은 그럴듯해집니다. 그런데 어떤 gate가 release를 막는지, 실패하면 어느 branch contract가 책임지는지, 문서의 gate matrix가 실제 workflow와 어긋나면 누가 잡는지 정하지 않으면 CI는 금방 장식이 됩니다.

ca-tmpl은 DevOps baseline을 “workflow 파일 몇 개”가 아니라 skeleton contract로 보려 했습니다. gate ownership matrix를 repo 안에 두고, Gradle custom task와 workflow job이 실제로 존재하는지 검사하며, dependency lock과 reproducible archive 설정, Cosign/SLSA 관련 workflow와 검증 스크립트를 둡니다. 단, hosted GitHub Actions에서 release를 실제 발행하고 Rekor/GHCR evidence까지 확인한 것은 아닙니다. 이 글은 구현된 local/repo-level gate와 live release 검증의 경계를 분리합니다.

본문 outline / Body outline

  1. CI gate는 tool list가 아니라 release contract다.
  2. gate matrix와 owner branch - 무엇이 실패하면 누가 고쳐야 하는가.
  3. Gradle baseline - static analysis, dependency locking, reproducible archive.
  4. supply-chain workflow - SBOM, Cosign, SLSA, Trivy를 증거 체인으로 묶는다.
  5. local/dev portability와 hosted release 검증의 차이를 분리한다.

본문 / Body

CI를 설계할 때 흔한 실수는 “무엇을 실행할지”만 정하는 것입니다. 실제로 더 중요한 질문은 “이 검사가 실패하면 release가 막히는가”, “누가 policy를 소유하는가”, “문서에 적힌 gate가 실제 workflow에 남아 있는가”입니다. ca-tmpl의 .github/ci-gate-matrix.yml은 이 질문에 답하기 위한 파일입니다. 각 gate에는 id, release blocking 여부, owner branch, mechanism, ref, workflow가 붙습니다.

이 matrix는 문서가 아니라 검사 대상입니다. verify-gate-matrix.sh는 matrix row를 읽고, mechanism별로 실제 존재 여부를 확인합니다. gradle-custom-task라면 tasks.register('<ref>')가 있어야 하고, contract-test라면 test class 파일이 있어야 하며, workflow-job이라면 workflow 안에 job id가 있어야 합니다. 이렇게 하면 “문서에는 gate가 있는데 CI에서는 빠진 상태”를 줄일 수 있습니다.

Gradle baseline도 여러 층으로 나뉩니다. src/build.gradle은 Spotless, Checkstyle, SpotBugs, ErrorProne을 subproject에 적용하고, dependency locking을 strict mode로 켭니다. archive task는 timestamp, file order, permission을 고정해 build artifact가 host 환경에 덜 흔들리도록 합니다. 이것은 production artifact reproducibility를 완전히 증명한다는 뜻이 아니라, skeleton에서 entropy source를 줄이는 baseline입니다.

Supply chain 쪽은 release evidence를 digest 중심으로 묶으려는 방향입니다. .github/workflows/build-release-supply-chain.yml에는 SBOM generation, Trivy image scan, Cosign sign/attest, SLSA provenance, verification, promotion step이 있습니다. .github/scripts/verify-supply-chain-contract.sh는 workflow와 policy file에 필요한 문자열과 job wiring이 남아 있는지 확인합니다. 예를 들어 cosign sign --yes, cosign attest --yes, --certificate-identity, --certificate-oidc-issuer, SLSA v1 predicate, exact builder identity 같은 조건을 검사합니다.

여기서 중요한 경계가 있습니다. ca-tmpl에 workflow와 검증 스크립트가 존재한다는 사실과, 실제 release artifact가 public registry에 올라갔고 Rekor/GHCR evidence로 검증됐다는 사실은 다릅니다. project canonical은 후자를 확인하지 않았다고 명시합니다. 따라서 이 글은 “supply-chain release를 운영했다”가 아니라 “supply-chain release contract를 repo-level workflow와 script로 고정했다”까지만 말합니다.

DX도 같은 관점입니다. ./gradlew bootstrap은 compile, Docker preflight, dependency/migration/startup, sample contract, HTTP smoke를 하나의 진입점으로 묶습니다. 이 명령이 모든 OS와 CI 환경을 보장한다는 뜻은 아닙니다. 대신 새 프로젝트를 받은 사람이 “무엇부터 실행해야 하는가”를 덜 고민하게 만들고, 실패 지점을 단계로 나누려는 목적입니다.

결국 ca-tmpl의 DevOps baseline은 “이 도구를 썼다”보다 “어떤 증거가 release를 통과시키는가”에 가깝습니다. gate matrix가 workflow와 drift 나지 않아야 하고, dependency lock이 조용히 풀리면 안 되며, vulnerability suppression은 사유와 만료일 없이 남으면 안 됩니다. 이 정도가 local/repo-level에서 검증된 범위입니다. 실제 hosted CI run, release publication, live Cosign/Rekor 검증은 별도의 근거가 생긴 뒤에만 말할 수 있습니다.

코드 예제 / Code samples (있다면)

# 출처: [[wiki/projects/ca-tmpl/devops-ci-supply-chain-dx]]
# 실제 파일: .github/ci-gate-matrix.yml, ca-tmpl @f6fbd4e196b4
gates:
  - id: architecture-test
    release_blocking: true
    owner_branch: feature-architecture-enforcement-rules
    mechanism: contract-test
    ref: app-bootstrap/src/test/java/dev/caskeleton/bootstrap/architecture/CleanArchitectureTest.java
    runs_in: ci-quality-gates
# 출처: [[wiki/projects/ca-tmpl/devops-ci-supply-chain-dx]]
# 실제 파일: .github/scripts/verify-gate-matrix.sh, ca-tmpl @f6fbd4e196b4
# Cross-checks every row of .github/ci-gate-matrix.yml against reality:
#   gradle-custom-task -> a tasks.register('<ref>') exists
#   contract-test      -> the <ref> test-class file exists under src/
#   workflow-job       -> the <ref> job id exists in .github/workflows/<runs_in>.yml
// 출처: [[wiki/projects/ca-tmpl/devops-ci-supply-chain-dx]]
// 실제 파일: src/build.gradle, ca-tmpl @f6fbd4e196b4
dependencyLocking {
    lockAllConfigurations()
    lockMode = LockMode.STRICT
}

tasks.withType(AbstractArchiveTask).configureEach {
    preserveFileTimestamps = false
    reproducibleFileOrder = true
}
# 출처: [[wiki/projects/ca-tmpl/devops-ci-supply-chain-dx]]
# 실제 파일: .github/scripts/verify-supply-chain-contract.sh, ca-tmpl @f6fbd4e196b4
require_fixed "${workflow}" 'cosign sign --yes' 'D6 keyless image signature'
require_fixed "${workflow}" 'cosign attest --yes' 'D4 digest-bound SBOM attestation'
require_fixed "${workflow}" '--certificate-identity' 'D12 signer identity verification'
require_fixed "${workflow}" '--certificate-oidc-issuer' 'D12 OIDC issuer verification'
require_fixed "${workflow}" 'generator_container_slsa3.yml@v2.1.0' 'D7 isolated SLSA generator'

Sources / 근거 (canonical 인용 필수, derived layer 의무)

사실 vs 의견 / Fact vs opinion 구분

  • 사실: ca-tmpl에는 CI workflow, .github/ci-gate-matrix.yml, gate matrix 검증 스크립트, supply-chain policy/script, Gradle dependency lock/reproducible archive 설정, 여러 custom verification task가 존재한다. 근거: wiki/projects/ca-tmpl/devops-ci-supply-chain-dx
  • 사실: ./gradlew check가 2026-07-02 기준 통과했고, local gate 검증이 project canonical에 기록되어 있다. 근거: wiki/projects/ca-tmpl/devops-ci-supply-chain-dx
  • 사실: hosted GitHub Actions run, 실제 release publication, live Rekor/GHCR/Cosign 검증은 확인하지 않았다. 근거: wiki/projects/ca-tmpl/devops-ci-supply-chain-dx
  • 의견: skeleton에서는 CI tool list보다 gate ownership matrix가 더 오래 남는 설계 자산이다.
  • 알지 못하는 것: public artifact 소비자, 실제 release incident, live registry rollback 경험.

답할 수 있는 범위 / Answer boundary

  • 자신 있게 답할 수 있는 후속 질문:
    • gate matrix가 왜 필요한가?
    • Gradle dependency locking과 reproducible archive 설정이 어떤 drift를 줄이는가?
    • Cosign/SLSA/Trivy workflow와 검증 스크립트가 repo-level에서 무엇을 고정하는가?
  • 다음 글로 넘길 부분:
    • 실제 release signing 운영.
    • public artifact distribution과 rollback manifest 운영.
    • SLSA level 달성 여부와 live provenance 검증.

게시 체크리스트 / Publish checklist

  • 모든 사실 주장에 canonical 링크 있음
  • 사실 vs 의견 분리 명시됨
  • 금지 마케팅 표현 없음
  • 코드 예제 출처 명시
  • 타깃 독자 가정과 톤 일치
  • /lint 통과
  • 게시 URL 기록 (게시 후):