/cc-dev:pr:preflight — PR 올리기 전 자동 점검#
| 항목 | 내용 |
|---|---|
| 실행 명령 | /cc-dev:pr:preflight |
| 분류 | 개발 |
| 난이도 | ●●○ 보통 |
| MCP 서버 | patrol |
한마디로#
PR(코드 합치기 요청)을 올리기 전에 "바뀐 부분이 제대로 동작하는지" 자동으로 검사해 주는 마지막 관문입니다. 공장에서 제품을 출고하기 전 마지막 품질 검사를 통과해야만 내보내는 것과 같아요. 검사에 실패하면 PR 생성이 막힙니다.
누가·언제 쓰나요#
- 개발자가 PR을 올리기 직전에 직접 실행할 때
- 자동화된 개발 흐름(
/cc-dev:run)이 진행 중 자동으로 이 점검을 부를 때 - 테스트 작성 작업(
/cc-e2e:kick-off)을 마친 다음 단계로 넘어갈 때 - 코드를 원격에 올리는 순간(push) 자동으로 걸리도록 설정해 둔 경우(선택 사항)
무엇을 해주나요#
이번에 바뀐 코드 묶음(패키지)만 자동으로 찾아내어, 3단계 검사를 차례로 돌립니다.
- 1단계 — 가장 작은 단위의 동작 검사(unit)
- 2단계 — 화면 조각이 제대로 그려지는지 검사(widget)
- 3단계 — 실제 사용 흐름이 끝까지 이어지는지 검사(integration)
검사 결과는 사람이 읽을 수 있는 요약 보고서로 나오고, 필요하면 파일로도 저장됩니다(.claude/preflight-report-{시각}.json). 전체 통과(PASS)하면 PR을 진행해도 좋다는 신호를, 하나라도 실패하면 PR을 막는 신호를 돌려줍니다.
어떻게 쓰나요#
# 기본 — 바뀐 패키지를 자동으로 찾아 unit + widget 검사 + 가벼운 integration(@smoke)
/cc-dev:pr:preflight
# 비교 기준이 되는 base 브랜치를 직접 지정
/cc-dev:pr:preflight --base development
# 특정 패키지만 골라서 검사
/cc-dev:pr:preflight --scope feature_common_auth,feature_application_store
# integration(실제 사용 흐름) 검사 포함
/cc-dev:pr:preflight --with-integration # 핵심만 빠르게(@smoke, 기본)
/cc-dev:pr:preflight --with-integration=full # 바뀐 패키지의 전체 흐름 검사
# 결과를 리포트 파일로 저장
/cc-dev:pr:preflight --save-report
# 실패한 부분을 자세히 보기
/cc-dev:pr:preflight --verbose
# 실제로 돌리지 않고 " 무엇을 검사할지 " 계획만 미리 보기
/cc-dev:pr:preflight --dry-run
# 예외 — 긴급 수정(hotfix)일 때만, 사유를 적고 전체 건너뛰기
/cc-dev:pr:preflight --skip-all --reason " 프로덕션 결제 크래시 응급 패치 "
참고로 가장 기본 단위인 unit/widget 검사는 임의로 건너뛸 수 없습니다(--skip-unit, --skip-widget은 정책상 거부되며 관리자 승인이 필요). 전체를 건너뛰는
--skip-all은 긴급 상황 전용으로, 반드시 사유(--reason)를 적어야 하고 기록이 남습니다.
안에서 무슨 일이 벌어지나요#
- 무엇과 비교할지 정하기 — 기준이 되는 base 브랜치를 자동으로(또는 지정한 대로) 결정합니다.
- 바뀐 부분 찾아내기 — 기준 대비 어떤 파일이 바뀌었는지 뽑아, 그 파일이 속한 코드 묶음(패키지)을 알아냅니다. 자동 생성된 파일이나 바뀐 코드가 전혀 없으면 일찍 마칩니다.
- 3단계 검사 실행 — 작은 단위 검사(unit) → 화면 조각 검사(widget) → 실제 흐름 검사(integration)를 순서대로 돌립니다. 중간에 하나라도 실패하면 거기서 멈추고 보고합니다. 테스트할 기기가 없으면 흐름 검사는 건너뛰고 경고만 남깁니다.
- 결과 정리·신호 반환 — 단계별 통과/실패, 바뀐 패키지 목록, 다음에 할 일을 요약해 보여주고, PR을 진행해도 되는지(허용/차단)를 알려줍니다.
⚙️ 상세 옵션·실행 명세 (개발자 / AI 에이전트용)
Triggers#
- PR 올리기 직전 수동 실행
/cc-dev:runStep 8 자동 호출/cc-e2e:kick-off완료 후 다음 단계- lefthook
pre-push훅에서 호출 (선택)
사용법#
# 기본 — 변경 패키지 자동 감지, unit + widget 필수 + @smoke integration
/cc-dev:pr:preflight
# base 브랜치 명시
/cc-dev:pr:preflight --base development
# 특정 패키지만
/cc-dev:pr:preflight --scope feature_common_auth,feature_application_store
# integration 포함
/cc-dev:pr:preflight --with-integration # @smoke 만 (기본)
/cc-dev:pr:preflight --with-integration=full # 변경 패키지의 전체 integration
# 리포트 저장
/cc-dev:pr:preflight --save-report
# 실패 상세 (verbose)
/cc-dev:pr:preflight --verbose
# Dry run — 실행 계획만 출력
/cc-dev:pr:preflight --dry-run
# 예외 — hotfix
/cc-dev:pr:preflight --skip-all --reason " 프로덕션 결제 크래시 응급 패치 "파라미터#
| 파라미터 | 필수 | 설명 | 기본 |
|---|---|---|---|
--base | ❌ | base 브랜치 | auto (upstream → development) |
--scope | ❌ | 패키지 scope 수동 지정 (콤마) | auto (git diff 감지) |
--with-integration[=smoke|full] | ❌ | integration 레이어 실행 (⚠️ Patrol 은 --flavor staging = 공유 백엔드 — 아래 참고) | smoke (로컬) |
--skip-integration | ❌ | integration 명시 skip | default 행동과 동일 |
--skip-unit / --skip-widget | ❌ | 정책상 거부 — 관리자 승인 필요 | false |
--skip-all | ❌ | 전량 skip (hotfix 전용) | false |
--reason | ⚠️ | --skip-all 시 필수 사유 | — |
--save-report | ❌ | 리포트 JSON 저장 | false |
--verbose | ❌ | 실패 상세 덤프 | false |
--dry-run | ❌ | 계획만 출력 | false |
--from-hook | ❌ | lefthook 호출 표시 (리포트 간결) | false |
실행 단계#
- Base 브랜치 결정 — 우선순위:
--base→ upstream → development → main - 변경 파일 추출 —
git diff --name-only "$BASE"..HEAD - 변경 패키지 매핑
- 파일 경로 → 위로 올라가며
pubspec.yaml을 만난 첫 디렉토리 - 자동 생성 파일(
.g.dart,.freezed.dart)은 부수 변경으로 분류. ⛔.patrol_test.dart는 손으로 쓴 테스트 소스라 여기 포함하지 않는다 — 다른 실제 소스 변경과 동일하게 취급 - 변경 없음 → 조기 종료 (PR 에 코드 변경 없음)
- 파일 경로 → 위로 올라가며
- 레이어 1: Unit 실행 —
melos exec --scope=... -- flutter test --exclude-tags=integration- FAIL → 중단, 리포트, exit≠0
- 레이어 2: Widget 실행 — 위 명령에 포함됨 (일반 Flutter 위젯 테스트만 해당; BDD 시나리오는 Widget 레이어를 생성/실행하지 않고 Patrol E2E 로만 검증한다)
- FAIL → 중단, 리포트, exit≠0
- 레이어 3: Integration 실행 (조건부)
--with-integration=smoke(기본) →@smoke태그 Patrol 시나리오--with-integration=full→ 변경 패키지의 모든 integration- 디바이스 없음 → skip + 경고
- ⚠️ 환경 확인이 디바이스 확인과 함께 온다: Patrol 은
--flavor staging으로 공유 백엔드에 쓴다 (cc-flutter:integration-testing의TestAccount는 팀 공유 계정이다). 실행 전cc-quality:qa-environment-hygiene의 환경 등급을 판정하고, 공유 스테이징(E1)이면 변이 전 원본 캡처(CBM)를 전제로 실행한 뒤/cc-quality:cleanup으로 정리한다. 로컬 격리(E0)로 대체 가능하면 그쪽을 먼저 쓴다 (cc-dev:parallel-test-env) - FAIL → 중단, 리포트, exit≠0
- 집계 리포트 — 레이어별 PASS/FAIL, 변경 패키지 목록, 다음 단계 안내
- PR 진행 허용/차단 플래그 반환
출력#
- stdout 리포트 (사람 읽기용)
- (선택)
.claude/preflight-report-{timestamp}.json - (skip 시)
.claude/preflight-skip.log - exit code (0 PASS, 1 FAIL, 2 POLICY VIOLATION)
Skip 정책#
--skip-unit, --skip-widget 은 항상 정책 위반 으로 reject.
--skip-all 은 --reason 필수 + 감사 로그 기록 + CI 가 강한 게이트로 대체 실행.
정책 상세: rules/pr-preflight-policy.md
실패 케이스#
| 원인 | 대응 |
|---|---|
| Base 브랜치 추정 실패 | --base 명시 안내 후 중단 |
| melos 없음 | flutter test + 디렉토리 스캔 폴백 |
scenarios/*_test.dart 컴파일 실패 (step 이름 불일치) | 코드 생성기가 없으므로 재실행이 아니라 dart analyze 로 원인 확인 후 직접 수정 |
| 디바이스 없음 (integration 요청 시) | skip + 경고 / 또는 --skip-integration 권유 |
| 자동 생성 파일만 변경 | 패키지 scope 에서 제외, 안내 |
--skip-all --reason 미제공 | 정책 위반 exit |
관련#
- 스킬 본체:
skills/pr/SKILL.md - 정책:
rules/pr-preflight-policy.md - 연계 커맨드:
/cc-dev:run(Step 8 자동 호출),/cc-e2e:kick-off - 조직 테스트 표준:
cc-flutter/skills/unit-testing,widget-testing,bdd-testing,integration-testing