| ํญ๋ชฉ | ๋ด์ฉ |
|---|---|
| Invoke | /pr:preflight |
| Aliases | /preflight, /pr:check |
| Category | kobic-development |
| Complexity | moderate |
| MCP Servers | patrol |
/pr:preflight โ PR ์ฌ๋ฆฌ๊ธฐ ์ ์๋ ์ ๊ฒ#
ํ๋ง๋๋ก#
PR(์ฝ๋ ํฉ์น๊ธฐ ์์ฒญ)์ ์ฌ๋ฆฌ๊ธฐ ์ ์ "๋ฐ๋ ๋ถ๋ถ์ด ์ ๋๋ก ๋์ํ๋์ง" ์๋์ผ๋ก ๊ฒ์ฌํด ์ฃผ๋ ๋ง์ง๋ง ๊ด๋ฌธ์ ๋๋ค. ๊ณต์ฅ์์ ์ ํ์ ์ถ๊ณ ํ๊ธฐ ์ ๋ง์ง๋ง ํ์ง ๊ฒ์ฌ๋ฅผ ํต๊ณผํด์ผ๋ง ๋ด๋ณด๋ด๋ ๊ฒ๊ณผ ๊ฐ์์. ๊ฒ์ฌ์ ์คํจํ๋ฉด PR ์์ฑ์ด ๋งํ๋๋ค.
๋๊ฐยท์ธ์ ์ฐ๋์#
- ๊ฐ๋ฐ์๊ฐ PR์ ์ฌ๋ฆฌ๊ธฐ ์ง์ ์ ์ง์ ์คํํ ๋
- ์๋ํ๋ ๊ฐ๋ฐ ํ๋ฆ(
/dev:run)์ด ์งํ ์ค ์๋์ผ๋ก ์ด ์ ๊ฒ์ ๋ถ๋ฅผ ๋ - ํ
์คํธ ์์ฑ ์์
(
/e2e:kick-off)์ ๋ง์น ๋ค์ ๋จ๊ณ๋ก ๋์ด๊ฐ ๋ - ์ฝ๋๋ฅผ ์๊ฒฉ์ ์ฌ๋ฆฌ๋ ์๊ฐ(push) ์๋์ผ๋ก ๊ฑธ๋ฆฌ๋๋ก ์ค์ ํด ๋ ๊ฒฝ์ฐ(์ ํ ์ฌํญ)
๋ฌด์์ ํด์ฃผ๋์#
์ด๋ฒ์ ๋ฐ๋ ์ฝ๋ ๋ฌถ์(ํจํค์ง)๋ง ์๋์ผ๋ก ์ฐพ์๋ด์ด, 3๋จ๊ณ ๊ฒ์ฌ๋ฅผ ์ฐจ๋ก๋ก ๋๋ฆฝ๋๋ค.
- 1๋จ๊ณ โ ๊ฐ์ฅ ์์ ๋จ์์ ๋์ ๊ฒ์ฌ(unit)
- 2๋จ๊ณ โ ํ๋ฉด ์กฐ๊ฐ์ด ์ ๋๋ก ๊ทธ๋ ค์ง๋์ง ๊ฒ์ฌ(widget)
- 3๋จ๊ณ โ ์ค์ ์ฌ์ฉ ํ๋ฆ์ด ๋๊น์ง ์ด์ด์ง๋์ง ๊ฒ์ฌ(integration)
๊ฒ์ฌ ๊ฒฐ๊ณผ๋ ์ฌ๋์ด ์ฝ์ ์ ์๋ ์์ฝ ๋ณด๊ณ ์๋ก ๋์ค๊ณ , ํ์ํ๋ฉด ํ์ผ๋ก๋ ์ ์ฅ๋ฉ๋๋ค(.claude/preflight-report-{์๊ฐ}.json). ์ ์ฒด ํต๊ณผ(PASS)ํ๋ฉด PR์ ์งํํด๋ ์ข๋ค๋ ์ ํธ๋ฅผ, ํ๋๋ผ๋ ์คํจํ๋ฉด PR์ ๋ง๋ ์ ํธ๋ฅผ ๋๋ ค์ค๋๋ค.
์ด๋ป๊ฒ ์ฐ๋์#
# ๊ธฐ๋ณธ โ ๋ฐ๋ ํจํค์ง๋ฅผ ์๋์ผ๋ก ์ฐพ์ unit + widget ๊ฒ์ฌ + ๊ฐ๋ฒผ์ด integration(@smoke)
/pr:preflight
# ๋น๊ต ๊ธฐ์ค์ด ๋๋ base ๋ธ๋์น๋ฅผ ์ง์ ์ง์
/pr:preflight --base development
# ํน์ ํจํค์ง๋ง ๊ณจ๋ผ์ ๊ฒ์ฌ
/pr:preflight --scope feature_common_auth,feature_application_store
# integration(์ค์ ์ฌ์ฉ ํ๋ฆ) ๊ฒ์ฌ ํฌํจ
/pr:preflight --with-integration # ํต์ฌ๋ง ๋น ๋ฅด๊ฒ(@smoke, ๊ธฐ๋ณธ)
/pr:preflight --with-integration=full # ๋ฐ๋ ํจํค์ง์ ์ ์ฒด ํ๋ฆ ๊ฒ์ฌ
# ๊ฒฐ๊ณผ๋ฅผ ๋ฆฌํฌํธ ํ์ผ๋ก ์ ์ฅ
/pr:preflight --save-report
# ์คํจํ ๋ถ๋ถ์ ์์ธํ ๋ณด๊ธฐ
/pr:preflight --verbose
# ์ค์ ๋ก ๋๋ฆฌ์ง ์๊ณ " ๋ฌด์์ ๊ฒ์ฌํ ์ง " ๊ณํ๋ง ๋ฏธ๋ฆฌ ๋ณด๊ธฐ
/pr:preflight --dry-run
# ์์ธ โ ๊ธด๊ธ ์์ (hotfix)์ผ ๋๋ง, ์ฌ์ ๋ฅผ ์ ๊ณ ์ ์ฒด ๊ฑด๋๋ฐ๊ธฐ
/pr:preflight --skip-all --reason " ํ๋ก๋์
๊ฒฐ์ ํฌ๋์ ์๊ธ ํจ์น "
์ฐธ๊ณ ๋ก ๊ฐ์ฅ ๊ธฐ๋ณธ ๋จ์์ธ unit/widget ๊ฒ์ฌ๋ ์์๋ก ๊ฑด๋๋ธ ์ ์์ต๋๋ค(--skip-unit, --skip-widget์ ์ ์ฑ
์ ๊ฑฐ๋ถ๋๋ฉฐ ๊ด๋ฆฌ์ ์น์ธ์ด ํ์). ์ ์ฒด๋ฅผ ๊ฑด๋๋ฐ๋
--skip-all์ ๊ธด๊ธ ์ํฉ ์ ์ฉ์ผ๋ก, ๋ฐ๋์ ์ฌ์ (--reason)๋ฅผ ์ ์ด์ผ ํ๊ณ ๊ธฐ๋ก์ด ๋จ์ต๋๋ค.
์์์ ๋ฌด์จ ์ผ์ด ๋ฒ์ด์ง๋์#
- ๋ฌด์๊ณผ ๋น๊ตํ ์ง ์ ํ๊ธฐ โ ๊ธฐ์ค์ด ๋๋ base ๋ธ๋์น๋ฅผ ์๋์ผ๋ก(๋๋ ์ง์ ํ ๋๋ก) ๊ฒฐ์ ํฉ๋๋ค.
- ๋ฐ๋ ๋ถ๋ถ ์ฐพ์๋ด๊ธฐ โ ๊ธฐ์ค ๋๋น ์ด๋ค ํ์ผ์ด ๋ฐ๋์๋์ง ๋ฝ์, ๊ทธ ํ์ผ์ด ์ํ ์ฝ๋ ๋ฌถ์(ํจํค์ง)์ ์์๋ ๋๋ค. ์๋ ์์ฑ๋ ํ์ผ์ด๋ ๋ฐ๋ ์ฝ๋๊ฐ ์ ํ ์์ผ๋ฉด ์ผ์ฐ ๋ง์นฉ๋๋ค.
- 3๋จ๊ณ ๊ฒ์ฌ ์คํ โ ์์ ๋จ์ ๊ฒ์ฌ(unit) โ ํ๋ฉด ์กฐ๊ฐ ๊ฒ์ฌ(widget) โ ์ค์ ํ๋ฆ ๊ฒ์ฌ(integration)๋ฅผ ์์๋๋ก ๋๋ฆฝ๋๋ค. ์ค๊ฐ์ ํ๋๋ผ๋ ์คํจํ๋ฉด ๊ฑฐ๊ธฐ์ ๋ฉ์ถ๊ณ ๋ณด๊ณ ํฉ๋๋ค. ํ ์คํธํ ๊ธฐ๊ธฐ๊ฐ ์์ผ๋ฉด ํ๋ฆ ๊ฒ์ฌ๋ ๊ฑด๋๋ฐ๊ณ ๊ฒฝ๊ณ ๋ง ๋จ๊น๋๋ค.
- ๊ฒฐ๊ณผ ์ ๋ฆฌยท์ ํธ ๋ฐํ โ ๋จ๊ณ๋ณ ํต๊ณผ/์คํจ, ๋ฐ๋ ํจํค์ง ๋ชฉ๋ก, ๋ค์์ ํ ์ผ์ ์์ฝํด ๋ณด์ฌ์ฃผ๊ณ , PR์ ์งํํด๋ ๋๋์ง(ํ์ฉ/์ฐจ๋จ)๋ฅผ ์๋ ค์ค๋๋ค.
โ๏ธ ์์ธ ์ต์ ยท์คํ ๋ช ์ธ (๊ฐ๋ฐ์ / AI ์์ด์ ํธ์ฉ)
Triggers#
- PR ์ฌ๋ฆฌ๊ธฐ ์ง์ ์๋ ์คํ
/dev:runStep 8 ์๋ ํธ์ถ/e2e:kick-off์๋ฃ ํ ๋ค์ ๋จ๊ณ- lefthook
pre-pushํ ์์ ํธ์ถ (์ ํ)
์ฌ์ฉ๋ฒ#
# ๊ธฐ๋ณธ โ ๋ณ๊ฒฝ ํจํค์ง ์๋ ๊ฐ์ง, unit + widget ํ์ + @smoke integration
/pr:preflight
# base ๋ธ๋์น ๋ช
์
/pr:preflight --base development
# ํน์ ํจํค์ง๋ง
/pr:preflight --scope feature_common_auth,feature_application_store
# integration ํฌํจ
/pr:preflight --with-integration # @smoke ๋ง (๊ธฐ๋ณธ)
/pr:preflight --with-integration=full # ๋ณ๊ฒฝ ํจํค์ง์ ์ ์ฒด integration
# ๋ฆฌํฌํธ ์ ์ฅ
/pr:preflight --save-report
# ์คํจ ์์ธ (verbose)
/pr:preflight --verbose
# Dry run โ ์คํ ๊ณํ๋ง ์ถ๋ ฅ
/pr:preflight --dry-run
# ์์ธ โ hotfix
/pr:preflight --skip-all --reason " ํ๋ก๋์
๊ฒฐ์ ํฌ๋์ ์๊ธ ํจ์น "ํ๋ผ๋ฏธํฐ#
| ํ๋ผ๋ฏธํฐ | ํ์ | ์ค๋ช | ๊ธฐ๋ณธ |
|---|---|---|---|
--base | โ | base ๋ธ๋์น | auto (upstream โ development) |
--scope | โ | ํจํค์ง scope ์๋ ์ง์ (์ฝค๋ง) | auto (git diff ๊ฐ์ง) |
--with-integration[=smoke|full] | โ | integration ๋ ์ด์ด ์คํ | 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,.widget_test.dart,.patrol_test.dart)์ ๋ถ์ ๋ณ๊ฒฝ์ผ๋ก ๋ถ๋ฅ - ๋ณ๊ฒฝ ์์ โ ์กฐ๊ธฐ ์ข ๋ฃ (PR ์ ์ฝ๋ ๋ณ๊ฒฝ ์์)
- ํ์ผ ๊ฒฝ๋ก โ ์๋ก ์ฌ๋ผ๊ฐ๋ฉฐ
- ๋ ์ด์ด 1: Unit ์คํ โ
melos exec --scope=... -- flutter test --exclude-tags=integration- FAIL โ ์ค๋จ, ๋ฆฌํฌํธ, exitโ 0
- ๋ ์ด์ด 2: Widget ์คํ โ ์ ๋ช
๋ น์ BDD
.widget_test.dartํฌํจ๋จ- FAIL โ ์ค๋จ, ๋ฆฌํฌํธ, exitโ 0
- ๋ ์ด์ด 3: Integration ์คํ (์กฐ๊ฑด๋ถ)
--with-integration=smoke(๊ธฐ๋ณธ) โ@smokeํ๊ทธ Patrol ์๋๋ฆฌ์ค--with-integration=fullโ ๋ณ๊ฒฝ ํจํค์ง์ ๋ชจ๋ integration- ๋๋ฐ์ด์ค ์์ โ skip + ๊ฒฝ๊ณ
- 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 + ๋๋ ํ ๋ฆฌ ์ค์บ ํด๋ฐฑ |
bdd_test_gen ์์ฑ๋ฌผ ๋๋ฝ | dart run build_runner build ์๋ ์คํ ํ ์ฌ์๋ |
| ๋๋ฐ์ด์ค ์์ (integration ์์ฒญ ์) | skip + ๊ฒฝ๊ณ / ๋๋ --skip-integration ๊ถ์ |
| ์๋ ์์ฑ ํ์ผ๋ง ๋ณ๊ฒฝ | ํจํค์ง scope ์์ ์ ์ธ, ์๋ด |
--skip-all --reason ๋ฏธ์ ๊ณต | ์ ์ฑ ์๋ฐ exit |
๊ด๋ จ#
- ์คํฌ ๋ณธ์ฒด:
skills/pr/SKILL.md - ์ ์ฑ
:
rules/pr-preflight-policy.md - ์ฐ๊ณ ์ปค๋งจ๋:
/dev:run(Step 8 ์๋ ํธ์ถ),/e2e:kick-off - ์กฐ์ง ํ
์คํธ ํ์ค:
cc-uiux/skills/unit-testing,widget-testing,bdd-testing,integration-testing