CI 개선 — 운영 자동화 + Prepare 파일럿 (PR1)
주요 결정
Architect 주도 재매칭
초안은 Gatekeeper 중심이었으나 .claude-team.json 상 CI/CD는 Architect 본업. Gatekeeper(인증/API Gateway)는 영역 밖으로 판명. Oracle이 Sprint 102 전반을 Architect 주도로 재조정.
옵션 다 (안전 3건 파일럿)
30건 일괄 auto-merge 검증은 대량 merge 리스크·커밋 스팸·CI 분 소비 대비 이득이 낮음. 3건(#85 dev dep gateway patch · #80 dev dep github-worker patch · #65 dev dep frontend patch)만 rebase 트리거 후 나머지는 월요일 dependabot 스케줄에 위임. 실제로는 dependabot이 grouping을 감지하여 기존 PR 자동 close + 그룹 PR로 재생성하는 경로를 택했고, 이는 정상 동작.
pull_request_target + no-checkout 패턴 채택
pull_request는 포크 PR에서 secrets 접근 불가. pull_request_target은 코드 인젝션 위험이 있으나 actions/checkout 제거로 PR 코드 실행을 zero로 만들고, job-level actor 검증 + step-level update-type 검증의 3중 방어로 상쇄.
Branch Protection 필수 체크 최소화
조건부 실행되는 Quality/Audit/Test/Build 잡은 skip 시 block되므로 필수에서 제외. 항상 실행되는 Secret Scan + Detect Changes만 지정.
enforce_admins=false 유지
Oracle 긴급 수정 경로 보존. 단 이번 스프린트 내에서는 admin merge 우회 사용하지 않음.
PR2/PR3 이월
컨텍스트 관리 + 각 PR의 독립 가치 보존을 위해 Sprint 103으로 이어감.
배경
채널톡 백엔드 CI 리팩토링 레퍼런스(36.6분 → 15분 38초) 분석 후 Sprint 102~105 4스프린트 로드맵을 수립했다. 원리 ⑤ "작은 서비스에서 먼저 검증 후 확장"을 스프린트 단위로 승격하여, 102는 파일럿·운영 자동화에 집중하고 103에서 전 서비스 확산한다.
이번 스프린트 개시 시점에 .planning에 누적된 문제는 두 가지였다:
- Dependabot 대기 PR 30건 — 주간 생성 PR이 수동 squash-merge 부담을 누적 중
- quality/audit/test 매트릭스 중복 — Node 서비스마다
setup-node + cache + npm ci가 3~4벌 반복
PR1은 (1)을 해결하고, PR2는 (2)를 해결하도록 설계했다. 본 ADR은 PR1 완료분만 기록한다. PR2/PR3는 Sprint 103에서 이어간다.
목표
- Dependabot PR 운영 자동화 — 그룹화 + patch/minor 자동 병합
- main 브랜치 보호 + 저장소 설정 강화로 자동 병합의 안전 경계 확립
- 안전 3건 파일럿으로 auto-merge 경로 실증
- 채널톡 원리 ⑤를 PR 단위에도 적용 — 30건 일괄이 아닌 3건 파일럿
작업 요약
| 커밋 | 담당 | 내용 |
|---|---|---|
46aeb73 (PR #102) | Architect + Scribe | Dependabot 그룹화 + patch/minor auto-merge 워크플로 신설 (Sprint 102-1) |
0d57816 (PR #104) | Dependabot + Auto-merge 워크플로 | github-worker-minor-patch 그룹 PR 자동 병합 (auto-merge 실증) |
f98ce25 (PR #103) | Scribe | Sprint 101 ADR status/교훈 확정 (잔재 정리) |
수정 내용
신규/변경 파일 (PR #102)
.github/dependabot.yml— 8개 ecosystem에{service}-minor-patchgroups 블록 추가 (Docker 2건 제외).github/workflows/dependabot-automerge.yml— 신규 생성- 트리거:
pull_request_target(secrets 접근 필요, no-checkout 패턴으로 코드 인젝션 방어) - 조건 (AND):
github.actor == 'dependabot[bot]'+dependabot/fetch-metadata@v2update-type이 patch/minor +gh pr merge --auto예약 - major는 명시적
exit 0스킵 - permissions:
contents: write,pull-requests: write(최소 원칙)
- 트리거:
.github/pull_request_template.md—## 변경 유형아래 Dependabot Auto-merge 조건 섹션 삽입
저장소 설정 변경 (Oracle 직접 gh API)
| 대상 | 설정 |
|---|---|
repos/tpals0409/AlgoSu | allow_auto_merge: true, delete_branch_on_merge: true |
branches/main/protection | strict: true, 필수 checks = ["Secret & Env Scan", "Detect Changed Services"], allow_force_pushes: false, allow_deletions: false, required_conversation_resolution: true |
잔재 정리 (PR #103)
docs/adr/sprints/sprint-101.md— statusin-progress→completed, 작업 요약 테이블에 실제 commit SHA 반영, 주요 교훈 섹션 추가
검증 결과
| 항목 | 결과 |
|---|---|
| PR #102 CI 전체 | ✅ 26 success / 10 skipped / 0 failure |
| PR #103 CI 전체 | ✅ 27 success / 9 skipped / 0 failure |
| Auto-merge 워크플로 실행 | ✅ 7/7 success (PR #104~#110) |
| 실제 자동 병합 실증 | ✅ PR #104 (github-worker 3 updates) — app/github-actions merger 확인 |
| Dependabot 대기 PR | 30건 → 2건 (28건이 그룹 PR 7개로 재편, 1건 merge, 6건 auto-merge 예약) |
| Branch Protection 실효 | ✅ main 직접 push 차단, strict 모드에서 최신 base 요구 |
결정
- Architect 주도 재매칭: 초안은 Gatekeeper 중심이었으나
.claude-team.json상 CI/CD는 Architect 본업. Gatekeeper(인증/API Gateway)는 영역 밖으로 판명. Oracle이 Sprint 102 전반을 Architect 주도로 재조정. - 옵션 다 (안전 3건 파일럿): 30건 일괄 auto-merge 검증은 대량 merge 리스크·커밋 스팸·CI 분 소비 대비 이득이 낮음. 3건(#85 dev dep gateway patch · #80 dev dep github-worker patch · #65 dev dep frontend patch)만 rebase 트리거 후 나머지는 월요일 dependabot 스케줄에 위임. 실제로는 dependabot이 grouping을 감지하여 기존 PR 자동 close + 그룹 PR로 재생성하는 경로를 택했고, 이는 정상 동작.
- pull_request_target + no-checkout 패턴 채택:
pull_request는 포크 PR에서 secrets 접근 불가.pull_request_target은 코드 인젝션 위험이 있으나actions/checkout제거로 PR 코드 실행을 zero로 만들고, job-level actor 검증 + step-level update-type 검증의 3중 방어로 상쇄. - Branch Protection 필수 체크 최소화: 조건부 실행되는 Quality/Audit/Test/Build 잡은 skip 시 block되므로 필수에서 제외. 항상 실행되는 Secret Scan + Detect Changes만 지정.
- enforce_admins=false 유지: Oracle 긴급 수정 경로 보존. 단 이번 스프린트 내에서는 admin merge 우회 사용하지 않음.
- PR2/PR3 이월: 컨텍스트 관리 + 각 PR의 독립 가치 보존을 위해 Sprint 103으로 이어감.
레퍼런스
- 채널톡 백엔드 CI 리팩토링: https://channel.io/ko/team/blog/articles/backend-ci-refactoring-73fca77d
- 4스프린트 로드맵: project-ci-refactoring-roadmap.md