commit-msg 훅 정본을 PIKI-Infra 로 이관#711
Conversation
- 훅 정본(SSOT)이 PIKI-Infra hooks/commit-msg 로 이동함에 따라, 이 repo 의 체크인 복사본(.claude/hooks/commit-msg)은 정본과 어긋날 수 있는 잔재라 삭제 - SessionStart 배선을 로컬 cp 에서 원격 fetch(gh api raw)로 교체. 설치 경로를 .git/hooks 직접 참조 대신 git rev-parse --git-common-dir 로 풀어 worktree(.git 이 파일)에서도 동작하게 정정. fetch 실패 시 기존 설치본 유지라 오프라인 안전 - commit.md 의 허용 타입 열거를 정본 참조로 교체 - 목록을 여기 두면 훅과 두 곳이 되어 한쪽만 바뀌는 drift 가 가능했음. 현재 타입은 설치된 훅을 읽어 확인 - 배선 검증 실측: 새 명령 exit 0, 설치본이 정본과 바이트 동일
|
Discord 스레드 연동용 메타데이터입니다. discord-pr-bot 워크플로가 자동 생성하며, 수정·삭제하면 PR 과 Discord 알림 연동이 끊깁니다. |
Walkthrough커밋 메시지 훅의 정본을 원격 저장소로 옮기고, 세션 시작 시 로컬 설치 방식도 원격 스크립트 실행 방식으로 바꿨다. 문서는 이제 허용 타입 목록을 직접 열거하지 않고, 설치된 훅과 정본 위치를 기준으로 확인하도록 안내한다. Changes커밋 훅 SSOT 전환
Sequence Diagram(s)sequenceDiagram
participant ClaudeSession
participant SettingsJson
participant GitHubAPI
participant GitHooksDir
ClaudeSession->>SettingsJson: SessionStart 이벤트 발생
SettingsJson->>GitHubAPI: gh api contents/install.sh 요청
GitHubAPI-->>SettingsJson: install.sh 원문 반환
SettingsJson->>GitHooksDir: bash로 실행해 .git/hooks/commit-msg 설치
SettingsJson-->>ClaudeSession: exit 0
Estimated code review effort: 2 (Simple) | ~10 minutes 🚥 Pre-merge checks | ✅ 2✅ Passed checks (2 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
- 직전 배선은 자산 경로·설치 로직이 SessionStart 명령에 문장째 박혀, 자산이 늘면 소비 repo 전부를 다시 고쳐야 했다 - 부트스트랩은 'PIKI-Infra install.sh 를 받아 실행' 한 줄로 축소. 이 repo 에 남는 상수는 repo 좌표 1개 - 검증 실측: 설치본 제거 후 부트스트랩 실행으로 원격 정본 설치(바이트 동일)
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
.claude/settings.json (1)
12-12: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win원격 정본을 고정하지 않고 검증 없이 바로 실행권한을 부여합니다.
매 세션마다 default branch 기준으로 fetch하고 문법 검사 없이
install -m 755로 즉시 실행 가능한 훅으로 설치합니다. PIKI-Infrahooks/commit-msg에 문법 오류가 있는 커밋이 잠깐이라도 올라가면, 그 시점에 세션을 시작한 모든 팀원의 로컬 커밋이 막힐 수 있습니다.bash -n "$tmp"같은 최소 문법 검증을 install 전에 추가하거나, 릴리즈 태그/커밋 SHA로 ref를 고정하는 방식을 고려해보세요. 아울러 PIKI-Infra 저장소에 브랜치 보호 규칙이 걸려 있는지도 한 번 확인해두면 안심될 것 같습니다.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.claude/settings.json at line 12, The hook bootstrap command in the settings entry installs the fetched PIKI-Infra commit-msg script without validating it or pinning a stable ref. Update the command to verify the downloaded script before installation (for example by running a shell syntax check) and prefer a fixed tag or commit SHA instead of the default branch when calling gh api. Keep the existing flow around the command string, mktemp handling, and install step, but ensure only validated, pinned content can be made executable as the local commit-msg hook.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.claude/settings.json:
- Line 12: The hook install command in the settings entry does not guard the
`git rev-parse --git-common-dir` failure case, so an empty result can produce a
bad install target path. Update the `command` logic to capture and validate the
output of `git rev-parse --git-common-dir` before using it, and only run
`install` when that path is non-empty and valid. Keep the existing `gh api`
success check, and make the `commit-msg` hook installation fail-safe in the same
chained shell flow.
---
Nitpick comments:
In @.claude/settings.json:
- Line 12: The hook bootstrap command in the settings entry installs the fetched
PIKI-Infra commit-msg script without validating it or pinning a stable ref.
Update the command to verify the downloaded script before installation (for
example by running a shell syntax check) and prefer a fixed tag or commit SHA
instead of the default branch when calling gh api. Keep the existing flow around
the command string, mktemp handling, and install step, but ensure only
validated, pinned content can be made executable as the local commit-msg hook.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro Plus
Run ID: 4675966c-f553-4e64-b7a7-38e7cd1b106c
📒 Files selected for processing (3)
.claude/commands/commit.md.claude/hooks/commit-msg.claude/settings.json
💤 Files with no reviewable changes (1)
- .claude/hooks/commit-msg
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.claude/settings.json:
- Line 12: The current `command` in the `.claude/settings.json` entry runs a
remote `install.sh` directly through `bash`, which is unsafe. Update this
command to avoid piping fetched content straight into execution by using the
existing GitHub API call in a safer flow: pin the `gh api` request with a
specific `ref` (SHA or tag), write the script to a temporary file, verify its
contents or checksum, and only then execute it. Keep the change localized to the
settings command so the startup behavior remains the same but no unverified
remote script is executed inline.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro Plus
Run ID: 66fb7bde-43f0-4c8c-9c4c-a8dc4b5dee9b
📒 Files selected for processing (1)
.claude/settings.json
| { | ||
| "type": "command", | ||
| "command": "[ -f .claude/hooks/commit-msg ] && cp .claude/hooks/commit-msg .git/hooks/commit-msg && chmod +x .git/hooks/commit-msg || true" | ||
| "command": "bash -c 'gh api -H \"Accept: application/vnd.github.raw\" repos/TeamPiKi/PIKI-Infra/contents/install.sh 2>/dev/null | bash; exit 0'" |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# gh CLI 버전 및 raw contents + ref 파라미터 동작 확인
gh --version
gh api -H "Accept: application/vnd.github.raw" \
"repos/TeamPiKi/PIKI-Infra/contents/install.sh?ref=HEAD" 2>&1 | head -c 200Repository: TeamPiKi/PIKI-Server
Length of output: 389
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== .claude/settings.json ==\n'
cat -n .claude/settings.json | sed -n '1,40p'
printf '\n== related files ==\n'
git ls-files | rg '(^|/)(commit\.md|settings\.json|install\.sh)$'
printf '\n== commit.md (if present) ==\n'
if [ -f commit.md ]; then
wc -l commit.md
cat -n commit.md | sed -n '1,120p'
fi
if [ -f .claude/commit.md ]; then
wc -l .claude/commit.md
cat -n .claude/commit.md | sed -n '1,120p'
fi
if [ -f docs/commit.md ]; then
wc -l docs/commit.md
cat -n docs/commit.md | sed -n '1,120p'
fiRepository: TeamPiKi/PIKI-Server
Length of output: 1336
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== gh api raw contents behavior ==\n'
python3 - <<'PY'
import subprocess, shlex, sys
cmds = [
r'gh api -H "Accept: application/vnd.github.raw" repos/TeamPiKi/PIKI-Infra/contents/install.sh',
r'gh api -H "Accept: application/vnd.github.raw" "repos/TeamPiKi/PIKI-Infra/contents/install.sh?ref=main"',
]
for c in cmds:
print(f"\n$ {c}")
p = subprocess.run(c, shell=True, text=True, capture_output=True)
print("rc =", p.returncode)
out = (p.stdout + p.stderr).strip()
print(out[:800] if out else "<no output>")
PYRepository: TeamPiKi/PIKI-Server
Length of output: 715
원격 install.sh를 바로 bash로 넘기지 마세요. .claude/settings.json:12처럼 세션 시작마다 외부 스크립트를 즉시 실행하면 공급망 위험이 생깁니다. ref를 특정 SHA/tag로 고정하고, 임시 파일로 받은 뒤 내용/체크섬을 확인한 다음 실행하는 쪽이 안전합니다. GitHub Contents API의 ref 옵션과 bash 파이프 실행 위험도 같이 보세요.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.claude/settings.json at line 12, The current `command` in the
`.claude/settings.json` entry runs a remote `install.sh` directly through
`bash`, which is unsafe. Update this command to avoid piping fetched content
straight into execution by using the existing GitHub API call in a safer flow:
pin the `gh api` request with a specific `ref` (SHA or tag), write the script to
a temporary file, verify its contents or checksum, and only then execute it.
Keep the change localized to the settings command so the startup behavior
remains the same but no unverified remote script is executed inline.
There was a problem hiding this comment.
부분 반영했습니다.
수용 (가용성 가드): 문법 깨진 정본이 전파되는 리스크는 실재합니다. install.sh 가 자산 설치 전 bash -n 검증을 하도록 했고(PIKI-Infra 59e02b6), 부트스트랩도 파이프 대신 임시파일로 받아 bash -n 통과 시에만 실행합니다 (82636af7). 실패 시 기존 설치본을 유지합니다.
기각 (SHA/tag pin + 체크섬): 이 배선의 존재 이유가 '정본 갱신이 소비 repo 무변경으로 전파'입니다. ref 를 SHA 로 고정하면 자산이 바뀔 때마다 소비 repo 전부의 pin 을 갱신해야 해, 이 PR 이 제거한 복제 문제가 그대로 되돌아옵니다. 신뢰 모델상 PIKI-Infra 는 같은 org 의 private repo 로 push 권한자와 훅 실행자가 동일 신뢰 도메인이며, main 을 오염시킬 수 있는 공격자는 소비 repo 자체도 오염시킬 수 있어 pin 의 보안 이득이 사실상 없습니다. 체크섬은 같은 repo 에 두면 무의미하고, 밖에 두면 N-repo 갱신 문제를 재도입합니다.
There was a problem hiding this comment.
@m-a-king 좋습니다, 판단 근거가 명확해서 이해가 잘 됩니다.
가용성 가드(temp file + bash -n + 실패 시 기존 설치본 유지): 이건 정확히 필요했던 수정입니다. 파이프로 바로 bash에 넘기던 것과 비교하면, 문법이 깨진 정본이 배포돼도 세션이 깨지지 않고 fail-safe로 동작하니 가용성 리스크가 실질적으로 줄었습니다. 👍
SHA/tag pin + 체크섬 기각: 논리에 동의합니다. PIKI-Infra가 같은 org의 private repo이고 push 권한자 집합이 소비 repo와 동일한 신뢰 도메인이라면, pin은 "정본 변경 → 전체 소비 repo 갱신 필요"라는, 이 PR이 없애려던 문제를 그대로 되돌리는 셈이고 실질적 보안 이득도 없습니다. 체크섬도 같은 저장소에 두면 자기 증명이 안 되고, 외부에 두면 N-repo 갱신 문제를 재도입한다는 것도 맞는 지적입니다. 이건 "핀을 걸 수 없는 게 아니라, 이 신뢰 모델에서는 핀이 실질적 방어선이 아니다"라는 트레이드오프 판단이고, 근거가 타당합니다.
참고로 한 가지만 짚자면: bash -n은 문법 검증만 하고 악의적이지만 문법상 올바른 스크립트는 걸러내지 못합니다. 다만 이는 이미 말씀하신 신뢰 모델(정본을 오염시킬 수 있는 공격자는 소비 repo도 오염시킬 수 있음) 안에서 감당하기로 한 리스크이므로 추가 조치를 요구하진 않겠습니다. 굳이 더 다듬고 싶다면, 실패 시 exit 0로 조용히 넘어가는 대신 stderr에 짧은 경고 로그를 남기는 정도는 디버깅 편의상 고려해볼 만합니다 (강제 사항 아님).
참고로 Contents API의 ref 파라미터나 GitHub API 인증 관련 세부 사항이 필요하면 GitHub REST API 문서를 참고하시면 됩니다.
ヽ(・∀・)ノ
✏️ Learnings added
Learnt from: m-a-king
Repo: TeamPiKi/PIKI-Server PR: 711
File: .claude/settings.json:0-0
Timestamp: 2026-07-09T19:31:40.973Z
Learning: In TeamPiKi/PIKI-Server (and related repos like PIKI-Extractor, PIKI-HeadlessBrowser), the commit-msg hook SSOT lives in the private `TeamPiKi/PIKI-Infra` repo's `install.sh`/`hooks/commit-msg`. The `.claude/settings.json` SessionStart hook fetches `install.sh` via `gh api -H "Accept: application/vnd.github.raw" repos/TeamPiKi/PIKI-Infra/contents/install.sh`, writes it to a temp file, validates it with `bash -n` before execution, and keeps the existing installed hook unchanged if fetch/validation fails. The team intentionally rejected pinning to a specific SHA/tag and content checksumming: PIKI-Infra is a private repo within the same org/trust domain as push access to the consuming repos, so pinning would reintroduce the duplication problem this design removes (every consumer repo would need pin updates on each infra change) without meaningful security benefit, and checksums are either circular (stored in the same repo) or reintroduce the N-repo update problem (stored elsewhere).
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
- CodeRabbit 가용성 지적 수용분: install.sh 를 파이프로 바로 실행하면 문법 깨진 정본이 부분 실행될 수 있음. tmp 로 받아 bash -n 통과 시에만 실행 (실패 시 조용히 스킵, exit 0) - 검증 로직은 자산과 무관하게 안정적이라 '자산 추가 시 소비 repo 무변경' 속성은 유지 - SHA pin·체크섬 제안은 기각 (배선의 존재 이유인 무전파 갱신 파괴 + 동일 신뢰 도메인) - 사유는 PR thread reply 에
- Updates 섹션의 증분 항목이 (a) 살아있는 본문 원칙으로 이미 고쳐진 본문, (b) 커밋 메시지와 삼중 중복임이 실사용(PR #711 갱신)에서 드러남. 본문만 어지럽혀 제거 - 증분 원장 역할은 PR 커밋 탭·본문 edit history 로 이양 (스쿼시 머지 후에도 PR 페이지에 남음). 리뷰어 증분 알림이 필요하면 본문이 아니라 PR 코멘트(타임라인)로 - 해시 dedup(이미 반영된 커밋 대조)은 '본문이 전체 diff 의 최종 상태를 반영하는가' 검사로 대체 - stateless 라 더 견고 - 표적 수정·남의 본문 보존·봇 마커 유지·전환 서사의 STAR 흡수 원칙은 유지. 옛 Updates 섹션이 남은 PR 은 갱신 시 이행 정리 - 3-B 단계 번호 재정렬(1-9) + 상호 참조(10단계 표기) 정리
Situation
Task
Action
.claude/hooks/commit-msg체크인hooks/commit-msg(SSOT, 복사본 삭제)install.sh(정본 설치기)를 받아 실행하는 한 줄 부트스트랩TeamPiKi/PIKI-Infra) 1개.git/hooks직접 참조git rev-parse --git-common-dir/hooks (install.sh 소관)commit.md에 9개 타입 열거 (훅과 두 곳).git이 파일이라 조용히 실패했다. 설치기가git-common-dir로 풀어 메인 체크아웃과 worktree 양쪽에서 동작한다.bash -n문법 검증 실패 시 실행·설치를 스킵하고 기존 설치본을 유지, exit 0. 실패나 깨진 정본이 기존 훅을 덮지 않는다 (문법 가드는 CodeRabbit 가용성 지적 수용).commit.md의 허용 타입 열거는 훅과 목록이 두 곳이 되는 값 중복이라 삭제하고, 정본 참조로 교체했다.Result
연관 이슈
Summary by CodeRabbit
New Features
Bug Fixes