16 KiB
title, source_type, status, confidence, tags, related_projects, last_reviewed
| title | source_type | status | confidence | tags | related_projects | last_reviewed | ||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| DevOps Baseline (CI + Supply chain + DX) | llm-generated | draft | medium |
|
|
2026-05-22 |
DevOps Baseline (CI + Supply chain + DX)
Layer:
wiki/concepts/— 일반 개념. 내 프로젝트 사실은project-template/ project 문서 사용.
Summary
운영 가능한 백엔드 skeleton의 DevOps baseline은 세 축으로 구성된다.
(1) CI quality gate — GitHub Actions needs: + if: success()로 contract test ↔ release-blocking 의존성을 단일 yaml에서 강제하고, flaky test는 14일 sunset 기한이 붙은 quarantine bucket으로 분리한다.
(2) Build / release supply chain — Cosign keyless signing (Sigstore Fulcio + Rekor transparency log)으로 artifact를 서명하고, SLSA provenance attestation으로 build 출처를 검증하며, Gradle dependency-locking으로 transitive 버전 drift를 차단한다.
(3) Developer experience — ./gradlew bootstrap 같은 단일 진입점 + Testcontainers @ServiceConnection 기반 integration test + .tool-versions로 핀된 JDK LTS로 새 개발자가 clean clone 직후 smoke까지 5단계로 도달한다.
Standard (공식 정의)
CI quality gate
- GitHub Actions (
docs.github.com/en/actions/): YAML workflow의jobs.<id>.needs의존성과if: success() | failure()조건으로 단계별 gate를 표현. job status가failure이면 workflow status도failure. - GitLab CI/CD (
docs.gitlab.com/ee/ci/pipelines/):stages+jobs+needs:+rules:키워드로 같은 모델을 구성.parallel: matrix:키워드로 matrix job. - Jenkins Declarative Pipeline (
jenkins.io/doc/book/pipeline/syntax/):agent디렉티브 +post { failure { ... } }block으로 실패 처리. - CircleCI configuration reference (
circleci.com/docs/configuration-reference/): orbs + workflow + job 모델. - Tekton Pipelines (
tekton.dev/docs/pipelines/):Pipeline=Tasks의 모음, 각Task는 Kubernetes Pod로 실행.
Supply chain
- Sigstore Cosign (
docs.sigstore.dev/cosign/signing/overview/): OIDC identity token으로 Fulcio가 단명(10분) 서명 cert 발급, 서명 직후 private key 파기. 서명 이벤트는 Rekor transparency log에 immutable 기록. 검증 측은cosign verify --certificate-identity=... --certificate-oidc-issuer=...로 issuer와 identity를 함께 강제. - SLSA v1.0 spec (
slsa.dev/spec/v1.0/): "Supply-chain Levels for Software Artifacts". provenance는 build platform, top-level build invocation, materials(sources + dependencies)를 최소 식별. Build L1 = provenance 존재, L2 = hosted build platform, L3 = hardened/hermetic build. - in-toto attestation (
github.com/in-toto/attestation): 인증된 statement = subject(artifact digest 목록) + predicate(예: SLSA Provenance). DSSE envelope으로 서명되며 Cosign이 같은 envelope을 서명한다. - Gradle dependency locking (
docs.gradle.org/current/userguide/dependency_locking.html):dependencyLocking { lockAllConfigurations() }+--write-locks로 lockfile 생성.lockMode = STRICT일 때 lock state와 다른 해석은 build fail. - Maven Enforcer Plugin
dependencyConvergence룰: transitive lockfile은 부재. 부분 대응만 가능.
Developer experience
- Testcontainers for Java (
java.testcontainers.org/): Docker container 기반 throwaway dependency. Spring Boot 3.1+@ServiceConnectionannotation으로 JDBC URL, credentials, host, port가 ApplicationContext에 자동 주입. reuse 옵션은 CI 금지, 로컬만. - Devcontainer spec (
containers.dev/implementors/spec/):.devcontainer/devcontainer.json이 VSCode/Codespaces용 dev container 정의. tool version과 OS-level dep을 통일하지만 첫 진입점/smoke/migration 순서는 별도 필요. - mise / asdf (
mise.jdx.dev/,asdf-vm.com/) —.tool-versions형식이 사실상 표준. SDKMAN! (sdkman.io/)은 별도.sdkmanrc사용. - Eclipse Temurin 21 LTS (
adoptium.net/temurin/releases/?version=21): 2028-09까지 무료 LTS 보안 패치.
한계 / 주의점
CI
- GitHub Actions는 vendor lock-in(workflow yaml 문법, OIDC issuer URL, marketplace action 등)과 hosted runner 비용 모델이 다른 provider와 다르다. provider-agnostic하게 gate를 정의하지 않으면 이식 비용이 크다.
- Jenkins / Tekton은 인프라(k8s cluster, plugin ecosystem)에 대한 의존도가 커서 skeleton 단계에서는 과한 선택일 수 있다.
- Flaky test quarantine은 Spotify/Google/Microsoft가 운영 도구로 인정한 반면 Martin Fowler는 *"Eradicating Non-Determinism in Tests"*에서 quarantine 자체를 anti-pattern으로 본다. "Spotify가 한다 = 공식 best practice"로 표현 금지. 14일 sunset 같은 절충은 어느 한쪽도 공식이 아니라는 인정이다.
- OpenAPI snapshot diff (springdoc + openapi-diff/oasdiff)는 controller annotation을 정적 추출하므로 dynamic routing(예: webflux functional routes)이 있으면 누락된다. "ground truth"는 이 범위 안에서만 참.
Supply chain
- Cosign keyless의 "signature 누락 시 deploy block"만으로는 부족하다.
--certificate-identity+--certificate-oidc-issuer로 identity 매칭 정책을 별도로 명시해야 임의의 OIDC identity가 만든 서명도 통과되는 사고를 막을 수 있다. Sigstore 공식은 키리스 모드에서 두 flag를 검증 진입 전제 조건으로 강제하며(--certificate-identity ... is required for verification in keyless mode), GitHub Actions OIDC 환경의 expected identity는https://github.com/<ORG>/<REPO>/.github/workflows/<file>@refs/heads/<branch>형식, issuer는https://token.actions.githubusercontent.com이다. 클러스터 측 강제는 policy-controller / KyvernoverifyImages등 admission controller에서 expected identity/issuer를 정책으로 선언. —needs-confirmation: 정책 표현 형식은 조직별로 다름. - SLSA v1.0 spec의 실제 필드명은 두 최상위 객체로 구성된다.
buildDefinition.{buildType, externalParameters, internalParameters, resolvedDependencies}+runDetails.{builder.id, builder.version, builder.builderDependencies, metadata.invocationId, metadata.startedOn, metadata.finishedOn, byproducts}. in-toto Statement 래퍼는_type(https://in-toto.io/Statement/v1) +subject[*].digest+predicateType(https://slsa.dev/provenance/v1) +predicate. 약식 표현(build.config.source,build.invocation,materials)은 spec 필드명과 다르므로 slsa-verifier가--builder-id↔runDetails.builder.id등의 필드를 찾지 못해 검증이 실패한다. provenance 생성 단계에서 spec 필드명을 그대로 사용해야 한다. — 출처: raw/official-docs/slsa-v1-provenance-schema. - SLSA Build L3 (hardened build, hermetic, tamper-resistant builder)는 GitHub Actions hosted runner만으로는 도달 불가. 실무적으로는 L2(hosted build platform)가 현실적 목표지점.
- Gradle dependency-locking이 있어도 plugin 버전과 toolchain(JDK)은 별도 핀이 필요.
.tool-versions/gradle/wrapper/gradle-wrapper.properties핀과 함께 봐야 reproducible build가 완성된다. - Maven에는 transitive lockfile이 1급 시민으로 존재하지 않는다. Maven 기반 프로젝트에서 같은 수준의 reproducibility를 요구하면 추가 도구가 필요.
Developer experience
.tool-versions(asdf/mise) vs.sdkmanrc(SDKMAN) 포맷 차이. 두 파일을 동시에 두면 drift 위험. 단일 source로 좁히는 편이 안전하다.- Devcontainer는 VSCode/Codespaces에 의존한다. IntelliJ + 로컬 JDK 사용자에게는 중복 환경이 되며 bootstrap 단일 진입점/smoke는 devcontainer 안에서도 별도로 정의되어야 한다.
- Testcontainers는 Apple Silicon(arm64) 환경에서 일부 image가 emulation(amd64) 위에서 동작해 bootstrap 시간이 늘어날 수 있다.
- Testcontainers reuse 옵션은 CI에서는 반드시 비활성화. test 간 isolation을 깬다.
- Bootstrap 한 줄 명령은 ergonomic 강점이 있으나 단계가 합쳐져 있어 어느 단계에서 실패했는지 추적이 어려울 수 있다. 실패 단계별 exit code 또는 step 출력 분리가 필요.
Project Application
-
wiki/projects/ca-tmpl/devops-ci-supply-chain-dx — ca-tmpl 의사결정 기록 (현재
documented-only, Phase C2 미진입). 실제 구현 여부는 project 문서 참조. 내 프로젝트(ca-skeleton)에서 이 개념과 관련된 문서로 링크. 실제 구현 여부·검증 등급은 해당 project / branch 문서에서 판정 (concept 문서는 등급을 직접 매기지 않음). -
raw/project-notes/ca-skeleton-operational-contract — §29 G-E (외부 근거 / 대안 조사 인덱스, DevOps / CI).
-
raw/branch-notes/feature-ci-quality-gates-contract — Gate ↔ Branch Contract Test 소유권 매트릭스 20행, flaky quarantine 14d sunset SSOT, OpenAPI snapshot diff.
-
raw/branch-notes/feature-build-release-supply-chain-contract — Cosign keyless 의무, SLSA provenance attestation 의무, Gradle dependency-locking, SemVer + git sha suffix, reproducibility.
-
raw/branch-notes/feature-developer-experience-contract —
./gradlew bootstrap5단계, Temurin 21 LTS, Testcontainers integration, markdown-link-check.
Interview Questions
- "CI에서 Gate ↔ Branch Contract Test 소유권 매트릭스란 무엇이고 왜 필요한가? 누가 어떤 gate를 깨질 때 책임지는지 어떻게 표현하는가?"
- "Flaky test quarantine bucket에 sunset deadline을 14일로 두는 근거는 무엇인가? quarantine 자체를 반대하는 입장(Fowler)과 어떻게 절충하는가?"
- "Cosign keyless signing이 GPG signing과 비교해 어떤 운영 비용을 제거하고, 어떤 새 의존성(OIDC IdP, Rekor 가용성)을 추가하는가?"
- "SLSA build level L1/L2/L3가 각각 무엇을 보장하는가? skeleton 단계에서 현실적으로 도달 가능한 level은 어디까지인가?"
- "Gradle dependency-locking이 필요한 이유는 무엇이고, Maven에는 왜 같은 수준의 lockfile이 없으며 어떻게 대체하는가?"
- "Integration test backend로 Testcontainers를 H2 같은 in-memory DB 대신 선택하는 이유는 무엇인가? 그 비용은 무엇인가?"
Do Not Overclaim
- "Cosign signature 누락만 차단하면 supply chain이 안전하다"고 단정 금지. identity 매칭 정책(
--certificate-identity+--certificate-oidc-issuer)이 없으면 임의 OIDC identity가 만든 서명도 통과될 수 있다. - "SLSA Build L3를 달성했다"고 단정 금지. ca-skeleton 단계에서 L3는 hermetic build / tamper-resistant builder를 요구하며 GitHub Actions hosted runner만으로는 도달 어렵다. branch note의 약식 매핑(
build.config.source등)은 spec 실제 필드명(buildDefinition.externalParameters)과 다르므로 정정 필요. - "Google/Spotify/Microsoft가 flaky test quarantine을 운영하므로 공식 best practice다"라고 표현 금지. 이들은 company-tech-blog 등급이며 Fowler의 반대 입장이 함께 존재한다.
- "GitHub Actions가 CI provider의 정답이다"로 단정 금지. ca-skeleton은
needs:+if: success()모델이 contract gate에 맞물려 채택된 것이며, gate 정의 자체는 provider-agnostic하게 작성되어야 이식 가능하다. - "
./gradlew bootstrap한 줄이 끝났다 = 모든 게 정상이다"로 표현 금지. 5단계(compileTestJava → docker compose up → Flyway migrate → sample profile seed → smoke) 중 어디서 실패했는지 step 단위 검증이 필요. - "Devcontainer가 있으면 bootstrap이 필요 없다"로 표현 금지. devcontainer는 tool version과 OS-level dep만 통일하며, 진입점/smoke/migration 순서는 별도로 정의되어야 한다.
- LLM 생성 문서이므로 본 concept 문서의 모든 진술은
confidence: medium. 검증 전 high confidence로 분류 금지.
Sources
공식 문서 / spec
- GitHub Actions — Migrating from GitLab CI/CD / GitLab CI/CD pipelines / Jenkins Declarative Pipeline / CircleCI configuration reference / Tekton Pipelines overview — CI provider 모델 비교.
- Sigstore Cosign overview + Fulcio + Rekor — keyless signing 체인.
- SLSA v1.0 spec + Build levels + Provenance schema + in-toto attestation — supply chain provenance.
- Gradle dependency locking + Maven Enforcer dependencyConvergence — dependency lockfile 정책.
- Testcontainers for Java + reuse + Spring Boot Testcontainers support — integration test backend.
- Devcontainer spec + VS Code Dev Containers + GitHub Codespaces — dev environment 통일.
- mise + asdf + SDKMAN! + Adoptium Temurin 21 — tool versioning + JDK LTS.
- springdoc-openapi + OpenAPITools/openapi-diff + Tufin/oasdiff + OpenAPI 3.1 — OpenAPI snapshot diff.
Raw 원본 (저장소 내 발췌)
- raw/official-docs/ci-github-actions-vs-gitlab-comparison — GitHub Actions
needs:+if: success()가 contract gate 매트릭스에 맞물리는 근거, Jenkins/Tekton의 k8s 인프라 부담. - raw/official-docs/ci-openapi-snapshot-diff-tooling — springdoc 런타임 추출 + openapi-diff/oasdiff CI 실패 조건, dynamic routing 함정.
- raw/company-tech-blogs/ci-flaky-test-quarantine-spotify-google — Spotify/Google/MS quarantine 인정 vs Fowler 반대 양립, 14d sunset은 절충.
- raw/official-docs/supply-chain-cosign-keyless-sigstore — Fulcio 단명 cert + Rekor transparency log + identity 매칭 정책 필요성.
- raw/official-docs/cosign-keyless-identity-verification-policy —
--certificate-identity+--certificate-oidc-issuer키리스 검증 강제 (Sigstore docs / cosign issue #3671), GitHub Actions OIDC identity 포맷. - raw/official-docs/supply-chain-slsa-provenance-framework — SLSA v1.0 build levels, provenance 최소 필드, in-toto attestation, 약식 매핑 정정 필요.
- raw/official-docs/slsa-v1-provenance-schema — SLSA v1.0 provenance 실제 필드명 표(
buildDefinition.*/runDetails.*) + in-toto Statement v1 래퍼 + slsa-verifier 검사 동작. ca-tmpl 약식 명명 정정 근거. - raw/official-docs/supply-chain-gradle-vs-maven-dependency-locking — Gradle
lockMode = STRICT, Maven transitive lockfile 부재. - raw/official-docs/dx-testcontainers-java-best-practices — Spring Boot 3.1+
@ServiceConnection, singleton 패턴, CI에서 reuse 금지. - raw/official-docs/dx-mise-asdf-tool-versioning —
.tool-versions사실상 표준,.sdkmanrc와의 drift 위험, Temurin 21 LTS. - raw/official-docs/dx-devcontainer-spring-boot — devcontainer가 보장하는 것/보장하지 않는 것, IDE 종속성.
Canonical 참조
- raw/project-notes/ca-skeleton-operational-contract §29 Group G-E — DevOps / CI / Supply chain / DX 대안 조사 인덱스.