Repository navigation
PR 전 로컬 리뷰 강제 #10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
PR 전 로컬 리뷰 강제 #10
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
42f827d
chore(hooks): PR 전 로컬 리뷰 강제
UHeeJoon 9c64166
test(coupon): 자유형 생성자 대신 always 팩토리
UHeeJoon b610fae
refactor(allocation): 배분기를 도메인 서비스로
UHeeJoon 6afcc2d
test(allocation): 구현과 독립인 공정성 성질
UHeeJoon 02518df
chore(rules): 죽은 예외 주석 제거
UHeeJoon 583ff1d
fix(hooks): 자기검증이 덮고 있던 결함 셋
UHeeJoon 89f1439
docs(journal): 훅이 못 본 파일들 기록
UHeeJoon b6acb35
fix(ci): 자기검증이 저장소 상태에 안 흔들리게
UHeeJoon cbf0507
fix(hooks): 리뷰 지적 6건 반영
UHeeJoon 2f1bbdb
fix(hooks): 리뷰 지적 3건 반영
UHeeJoon File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| --- | ||
| description: PR 을 올리기 전 로컬 리뷰. 기계 검사 + 영역별 리뷰 에이전트 | ||
| --- | ||
|
|
||
| PR 을 올리기 전에 **CodeRabbit 이 볼 것을 먼저 본다.** 원격에서 지적받고 고치는 | ||
| 왕복은 비싸고, 무엇보다 그 사이에 잘못된 코드가 브랜치에 남는다. | ||
|
|
||
| ## 1. 기계 검사 | ||
|
|
||
| ```bash | ||
| .claude/hooks/review-branch.sh ${1:-origin/develop} | ||
| ``` | ||
|
|
||
| 이 스크립트는 `check-java.sh`·`check-lua.sh` 를 **브랜치 변경 전체**에 태운다. | ||
| 두 훅은 `Write|Edit` 도구로 쓴 파일만 보므로, 힙독이나 스크립트로 만든 파일은 | ||
| 그냥 지나간다 — 실제로 그렇게 들어간 위반이 CodeRabbit 까지 간 적이 있다. | ||
|
|
||
| 위반이 나오면 **고치고 다시 돌린다.** 통과할 때까지 2번으로 넘어가지 않는다. | ||
|
|
||
| ## 2. 빌드와 품질 임계 | ||
|
|
||
| ```bash | ||
| ./gradlew build jacocoTestCoverageVerification pitest --no-daemon -q | ||
| ``` | ||
|
|
||
| 도메인 분기 100%, 뮤테이션 생존 ≤10%. 생존 뮤턴트가 나오면 **숫자만 보지 말고 | ||
| 어디가 살아남았는지** 본다 — 임계를 통과해도 이미 버그가 났던 자리에 몰려 | ||
| 있으면 그건 통과가 아니다. | ||
|
|
||
| ## 3. 영역별 리뷰 에이전트 | ||
|
|
||
| 변경 경로에 따라 `.claude/agents/` 에서 고른다. 1번 스크립트가 마지막에 | ||
| 어느 에이전트를 돌릴지 알려준다. | ||
|
|
||
| | 변경 | 에이전트 | | ||
| |---|---| | ||
| | `domain/**` | `domain-guardian` | | ||
| | `*.lua` · `redis/**` | `redis-cluster-checker` | | ||
| | 장애·회복·서킷·리트라이 | `resilience-auditor` | | ||
| | `src/test/**` · `src/testFixtures/**` | `test-quality-reviewer` | | ||
| | 전 영역 (항상) | `style-enforcer` | | ||
|
|
||
| 각 에이전트에게 **변경 범위를 명시**해서 넘긴다 — 저장소 전체를 훑게 하면 | ||
| 이번 변경과 무관한 지적이 섞여 진짜 지적이 묻힌다. | ||
|
|
||
| ## 4. 사람이 볼 것 | ||
|
|
||
| 기계도 에이전트도 못 보는 것이 남는다. | ||
|
|
||
| - **판정 순서를 바꿨다면** 계획서의 사다리 표도 함께 고쳤는가 (PK-A4) | ||
| - **계획서와 구현이 어긋난다면** 어느 쪽이 목표에 가까운가. 계획서가 스스로 | ||
| 모순인 경우가 있다 (AIJ-0012) | ||
| - **테스트 이름이 실제로 검증하는 것과 같은가.** 이름만 맞고 내용이 다른 | ||
| 테스트는 통과하면서 버그를 덮는다 | ||
|
|
||
| ## 5. 그다음 | ||
|
|
||
| - 저널이 필요한 변경인가 — `src/**`·`*.gradle`·`.github/workflows/**` | ||
| - 커밋 제목이 50칸 이내 명사형인가, 푸터에 `Refs: CY-###` 가 있는가 | ||
| - 푸시 전에 **무엇을 바꿨는지 요약**한다 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| #!/usr/bin/env bash | ||
| # PR 을 올리기 전에 로컬 리뷰를 강제한다. | ||
| # | ||
| # **왜 차단인가.** "올리기 전에 돌려라" 는 규범은 잊힌다. 실제로 잊었고, | ||
| # CodeRabbit 이 두 라운드에 걸쳐 14건을 지적했는데 그중 셋은 우리 자신의 | ||
| # MUST 규칙 위반이었다 — 로컬에서 1초면 잡히는 것들이다. | ||
| # | ||
| # PreToolUse(Bash) 훅. `gh pr create` 를 만나면 기계 검사를 돌리고 | ||
| # 위반이 있으면 exit 2 로 막는다. | ||
|
|
||
| set -uo pipefail | ||
|
|
||
| input=$(cat) | ||
| cmd=$(printf '%s' "$input" | jq -r '.tool_input.command // empty') | ||
|
|
||
| # PR 생성이 아니면 통과 | ||
| [[ "$cmd" != *"gh pr create"* ]] && exit 0 | ||
|
|
||
| # **검사를 못 돌리면 막는다.** 통과시키면 게이트가 인프라 오류 한 번에 | ||
| # 조용히 사라진다 — 가드는 fail closed 여야 한다. | ||
| if ! ROOT=$(git rev-parse --show-toplevel 2>/dev/null); then | ||
| echo "git 저장소가 아니라 로컬 리뷰를 돌릴 수 없다. PR 은 저장소 안에서 연다." >&2 | ||
| exit 2 | ||
| fi | ||
| RUNNER="$ROOT/.claude/hooks/review-branch.sh" | ||
| if [[ ! -x "$RUNNER" ]]; then | ||
| echo "로컬 리뷰 러너를 실행할 수 없다: $RUNNER" >&2 | ||
| echo " chmod +x .claude/hooks/*.sh" >&2 | ||
| exit 2 | ||
| fi | ||
|
|
||
| # base 를 명령에서 뽑는다. 없으면 develop | ||
| # **명령 문자열 전체를 훑지 않는다.** `--title "--base release"` 처럼 인용부호 | ||
| # 안에 들어간 값을 옵션으로 착각한다. 인자를 토큰으로 쪼갠 뒤 옵션 자리만 본다. | ||
| # | ||
| # 실행하지 않고 쪼갠다 — `xargs` 는 셸 인용 규칙을 그대로 따르면서 명령을 | ||
| # 부르지 않는다. | ||
| base="" | ||
| mapfile -t args < <(printf '%s' "$cmd" | xargs -n1 printf '%s\n' 2>/dev/null) | ||
| for ((i = 0; i < ${#args[@]}; i++)); do | ||
| case "${args[i]}" in | ||
| --base=*) base="${args[i]#--base=}"; break ;; | ||
| -B=*) base="${args[i]#-B=}"; break ;; | ||
| --base|-B) | ||
| base="${args[i + 1]:-}" | ||
| break ;; | ||
| esac | ||
| done | ||
| base="${base:-develop}" | ||
| # 이미 접두가 붙어 있으면 겹치지 않게 둔다. origin/origin/develop 이 되면 | ||
| # 러너가 폴백을 타고, 폴백마저 없으면 브랜치 커밋을 하나도 안 보고 통과한다. | ||
| [[ "$base" != origin/* ]] && base="origin/$base" | ||
|
|
||
| out=$("$RUNNER" "$base" 2>&1) | ||
| status=$? | ||
|
|
||
| if ((status != 0)); then | ||
| { | ||
| echo "PR 을 올리기 전에 로컬 리뷰가 통과해야 한다." | ||
| echo | ||
| # 전체를 보여 준다. 걸러내면 정작 필요한 줄이 빠진다. | ||
| printf '%s\n' "$out" | ||
| echo | ||
| echo "고친 뒤 다시 시도한다. 수동 실행: .claude/hooks/review-branch.sh $base" | ||
| echo "전체 절차: /review" | ||
| } >&2 | ||
| exit 2 | ||
| fi | ||
|
|
||
| # 통과했어도 기계가 못 보는 것이 남는다 — 막지는 않고 알린다. | ||
| { | ||
| echo "로컬 기계 검사 통과. 아직 안 한 것이 있는지 본다:" | ||
| echo " · ./gradlew build jacocoTestCoverageVerification pitest" | ||
| printf '%s\n' "$out" | sed -n '/사람·에이전트가 볼 것/,$p' | sed 's/^/ /' | ||
| } >&2 | ||
| exit 0 |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.