feat(phase3): NAS post-receive hook + 설치가이드 (PD님 수작업 대기)
- scripts/nas_post_receive.sh: NAS bare repo hooks/에 배치할 bash 스크립트 · main push 도달 시 변경 파일 경로 패턴 분석 · 4채널 Discord webhook으로 실시간 알림 발송 · post-receive-env 파일로 webhook URL 관리 (C6 준수, chmod 600) - 공유/조직공지/2026-04-15_Phase3_NAS_post_receive_설치가이드.md: · Discord 서버·채널·webhook 준비 절차 · NAS hook 배치·환경변수·테스트 절차 · 트러블슈팅·보안 가이드 - Phase 3은 PD님 수작업(Discord 준비·NAS 배치) 후 테스트 커밋으로 가동 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
9a6ef2fab0
commit
7312657b3e
|
|
@ -0,0 +1,119 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# ─────────────────────────────────────────────────────────────
|
||||||
|
# NerdNavis — NAS git 서버측 post-receive hook
|
||||||
|
# Phase 3 (2026-04-15 PD님 승인)
|
||||||
|
#
|
||||||
|
# 목적: git push 도달 즉시 Discord 채널로 실시간 알림 발송
|
||||||
|
# → 부서 세션이 구동되지 않은 상태에서도 PD님·PM·부서가 push 이벤트를 즉시 인지
|
||||||
|
#
|
||||||
|
# 배치 위치: <NAS bare repo 경로>/hooks/post-receive
|
||||||
|
# 예: /volume1/git-repos/NerdNavisAi.git/hooks/post-receive
|
||||||
|
# 배치 후: chmod +x post-receive
|
||||||
|
#
|
||||||
|
# 환경변수 파일: 같은 hooks/ 디렉토리에 post-receive-env 파일 생성 후 다음 변수 정의
|
||||||
|
# PM_WEBHOOK_URL — #pm-inbox Discord webhook URL
|
||||||
|
# DEV_WEBHOOK_URL — #dev-inbox
|
||||||
|
# PLAN_WEBHOOK_URL — #plan-inbox
|
||||||
|
# ALL_WEBHOOK_URL — #core-rules (전 조직 공지·코어룰 변경)
|
||||||
|
#
|
||||||
|
# 예:
|
||||||
|
# PM_WEBHOOK_URL="https://discord.com/api/webhooks/1234.../abcd..."
|
||||||
|
# DEV_WEBHOOK_URL="https://discord.com/api/webhooks/5678.../efgh..."
|
||||||
|
# PLAN_WEBHOOK_URL="https://discord.com/api/webhooks/9012.../ijkl..."
|
||||||
|
# ALL_WEBHOOK_URL="https://discord.com/api/webhooks/3456.../mnop..."
|
||||||
|
#
|
||||||
|
# chmod 600 post-receive-env (읽기 권한 제한, C6 준수)
|
||||||
|
# ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
HOOK_DIR=$(dirname "$0")
|
||||||
|
ENV_FILE="$HOOK_DIR/post-receive-env"
|
||||||
|
[ -f "$ENV_FILE" ] && source "$ENV_FILE"
|
||||||
|
|
||||||
|
# 로그 파일 (디버깅용)
|
||||||
|
LOG_FILE="$HOOK_DIR/post-receive.log"
|
||||||
|
|
||||||
|
log() {
|
||||||
|
echo "[$(date -Iseconds)] $*" >> "$LOG_FILE" 2>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
send_discord() {
|
||||||
|
local URL="$1"
|
||||||
|
local TITLE="$2"
|
||||||
|
local DESC="$3"
|
||||||
|
local COLOR="${4:-3447003}" # 기본 파란색
|
||||||
|
|
||||||
|
[ -z "$URL" ] && return
|
||||||
|
|
||||||
|
# Discord embed payload
|
||||||
|
local PAYLOAD
|
||||||
|
PAYLOAD=$(cat <<EOF
|
||||||
|
{
|
||||||
|
"embeds": [{
|
||||||
|
"title": "$TITLE",
|
||||||
|
"description": "$DESC",
|
||||||
|
"color": $COLOR,
|
||||||
|
"footer": {"text": "너드나비스 git server · post-receive"}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
|
||||||
|
curl -s -X POST "$URL" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "$PAYLOAD" > /dev/null 2>&1
|
||||||
|
|
||||||
|
log "sent to $TITLE"
|
||||||
|
}
|
||||||
|
|
||||||
|
json_escape() {
|
||||||
|
# 최소한의 JSON 이스케이프 (backslash, quote, newline)
|
||||||
|
printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g' | tr '\n' ' '
|
||||||
|
}
|
||||||
|
|
||||||
|
while read oldrev newrev refname; do
|
||||||
|
# main 브랜치 push만 처리
|
||||||
|
branch=$(git rev-parse --symbolic --abbrev-ref "$refname" 2>/dev/null)
|
||||||
|
[ "$branch" != "main" ] && continue
|
||||||
|
|
||||||
|
# 최초 push (oldrev가 0...0) 스킵
|
||||||
|
[[ "$oldrev" =~ ^0+$ ]] && continue
|
||||||
|
|
||||||
|
# 변경 파일 목록
|
||||||
|
CHANGED=$(git diff --name-only "$oldrev" "$newrev" 2>/dev/null)
|
||||||
|
[ -z "$CHANGED" ] && continue
|
||||||
|
|
||||||
|
# 최근 커밋 요약
|
||||||
|
COMMIT_MSG=$(git log -1 --format="%s" "$newrev" 2>/dev/null)
|
||||||
|
AUTHOR=$(git log -1 --format="%an" "$newrev" 2>/dev/null)
|
||||||
|
SHORT_SHA=$(git rev-parse --short "$newrev" 2>/dev/null)
|
||||||
|
COMMIT_COUNT=$(git rev-list --count "$oldrev..$newrev" 2>/dev/null)
|
||||||
|
|
||||||
|
# 채널별 알림 분기 플래그
|
||||||
|
TO_PM=0; TO_DEV=0; TO_PLAN=0; TO_ALL=0
|
||||||
|
|
||||||
|
while IFS= read -r FILE; do
|
||||||
|
case "$FILE" in
|
||||||
|
공유/소통/PM→개발실/*|공유/소통/개발실→PM/*)
|
||||||
|
TO_PM=1; TO_DEV=1 ;;
|
||||||
|
공유/소통/PM→기획실/*|공유/소통/기획실→PM/*)
|
||||||
|
TO_PM=1; TO_PLAN=1 ;;
|
||||||
|
공유/소통/기획실→개발실/*)
|
||||||
|
TO_DEV=1 ;;
|
||||||
|
공유/소통/개발실→기획실/*)
|
||||||
|
TO_PLAN=1 ;;
|
||||||
|
공유/조직공지/*|공유/공통_업무_규칙.md)
|
||||||
|
TO_ALL=1 ;;
|
||||||
|
esac
|
||||||
|
done <<< "$CHANGED"
|
||||||
|
|
||||||
|
# 알림 발송
|
||||||
|
MSG_ESC=$(json_escape "$COMMIT_MSG")
|
||||||
|
DESC="**${MSG_ESC}**\\n\\n커밋: \`${SHORT_SHA}\` (${COMMIT_COUNT}건) by ${AUTHOR}"
|
||||||
|
|
||||||
|
[ $TO_PM -eq 1 ] && send_discord "$PM_WEBHOOK_URL" "📬 PM 수신 채널 변경" "$DESC" 3447003
|
||||||
|
[ $TO_DEV -eq 1 ] && send_discord "$DEV_WEBHOOK_URL" "📬 개발실 수신 채널 변경" "$DESC" 5763719
|
||||||
|
[ $TO_PLAN -eq 1 ]&& send_discord "$PLAN_WEBHOOK_URL" "📬 기획실 수신 채널 변경" "$DESC" 15105570
|
||||||
|
[ $TO_ALL -eq 1 ] && send_discord "$ALL_WEBHOOK_URL" "📜 코어룰/조직공지 변경" "$DESC" 15548997
|
||||||
|
done
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
|
@ -0,0 +1,159 @@
|
||||||
|
---
|
||||||
|
from: 총괄PM
|
||||||
|
to: PD님
|
||||||
|
type: 설치가이드
|
||||||
|
subject: Phase 3 — NAS post-receive hook + Discord webhook 설치 가이드
|
||||||
|
status: 준비대기
|
||||||
|
priority: normal
|
||||||
|
created: 2026-04-15
|
||||||
|
ref_phase: Phase 3
|
||||||
|
---
|
||||||
|
|
||||||
|
# Phase 3 설치 가이드 — NAS post-receive + Discord 실시간 알림
|
||||||
|
|
||||||
|
## 목적
|
||||||
|
|
||||||
|
git push가 NAS 저장소에 도달하는 **그 순간**에 Discord webhook으로 알림을 발송하여, 부서 세션이 열려있지 않은 상태에서도 PD님·PM·부서가 이벤트를 즉시 인지한다. Claude 세션 간 통신의 근본 한계(세션 간 직접 통신 불가, 5분 throttle 지연)를 우회하는 **실시간 계층**.
|
||||||
|
|
||||||
|
## 동작 개요
|
||||||
|
|
||||||
|
```
|
||||||
|
어느 세션이든 push 발생
|
||||||
|
↓
|
||||||
|
NAS bare repo의 hooks/post-receive 실행 (bash)
|
||||||
|
↓
|
||||||
|
변경 파일 경로 패턴 분석
|
||||||
|
↓
|
||||||
|
채널별 Discord webhook 호출
|
||||||
|
├─ 공유/소통/PM↔개발실/* → #pm-inbox + #dev-inbox
|
||||||
|
├─ 공유/소통/PM↔기획실/* → #pm-inbox + #plan-inbox
|
||||||
|
├─ 공유/소통/개발실↔기획실/* → #dev-inbox 또는 #plan-inbox
|
||||||
|
└─ 공유/조직공지/* 또는 공유/공통_업무_규칙.md → #core-rules
|
||||||
|
↓
|
||||||
|
PD님·PM·부서 담당자 Discord 알림 즉시 수신 (모바일 포함)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 준비물 (PD님 수작업 필요)
|
||||||
|
|
||||||
|
### 1. Discord 서버·채널·webhook 준비
|
||||||
|
|
||||||
|
**추천 채널 구조:**
|
||||||
|
```
|
||||||
|
너드나비스 서버
|
||||||
|
├── #pm-inbox ← PM 수신 알림
|
||||||
|
├── #dev-inbox ← 개발실 수신 알림
|
||||||
|
├── #plan-inbox ← 기획실 수신 알림
|
||||||
|
└── #core-rules ← 조직공지·코어룰 변경 전 조직 알림
|
||||||
|
```
|
||||||
|
|
||||||
|
**각 채널의 webhook URL 발급 방법:**
|
||||||
|
1. Discord 채널 우클릭 → 채널 편집 → 연동(Integrations)
|
||||||
|
2. Webhook 만들기 → 이름 지정 (예: "너드나비스-git") → 복사 URL
|
||||||
|
3. 4개 채널 각각 반복, 총 4개 URL 수집
|
||||||
|
|
||||||
|
### 2. NAS 저장소 접근
|
||||||
|
|
||||||
|
SSH 또는 NAS 관리 콘솔로 bare repo 경로 접근 가능해야 함.
|
||||||
|
- Gitea 기본 경로 예시: `/volume1/gitea-repos/NerdNavis/NerdNavisAi.git/`
|
||||||
|
- 또는 `/var/lib/gitea/repositories/NerdNavis/NerdNavisAi.git/`
|
||||||
|
|
||||||
|
정확한 경로는 NAS Gitea 관리자 페이지의 저장소 설정에서 확인.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 설치 절차 (PD님 실행)
|
||||||
|
|
||||||
|
### STEP 1 — 스크립트 배치
|
||||||
|
레포 루트에 이미 커밋된 `scripts/nas_post_receive.sh` 를 NAS로 복사:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 옵션 A: NAS에 SSH 접속해서 git pull
|
||||||
|
ssh admin@burning.i234.me
|
||||||
|
cd /path/to/local-clone
|
||||||
|
git pull origin main
|
||||||
|
cp scripts/nas_post_receive.sh /volume1/gitea-repos/NerdNavis/NerdNavisAi.git/hooks/post-receive
|
||||||
|
chmod +x /volume1/gitea-repos/NerdNavis/NerdNavisAi.git/hooks/post-receive
|
||||||
|
|
||||||
|
# 옵션 B: Gitea 관리 UI에 git hook 직접 붙여넣기
|
||||||
|
# 관리자 → Site Administration → Repositories → NerdNavisAi → Git Hooks → post-receive
|
||||||
|
# → scripts/nas_post_receive.sh 내용 전체 붙여넣기 → Update
|
||||||
|
```
|
||||||
|
|
||||||
|
### STEP 2 — 환경변수 파일 생성
|
||||||
|
webhook URL 보관 파일 생성. **본 파일은 절대 commit 금지** (C6 데이터 보호):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cat > /volume1/gitea-repos/NerdNavis/NerdNavisAi.git/hooks/post-receive-env <<'EOF'
|
||||||
|
PM_WEBHOOK_URL="https://discord.com/api/webhooks/..."
|
||||||
|
DEV_WEBHOOK_URL="https://discord.com/api/webhooks/..."
|
||||||
|
PLAN_WEBHOOK_URL="https://discord.com/api/webhooks/..."
|
||||||
|
ALL_WEBHOOK_URL="https://discord.com/api/webhooks/..."
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod 600 /volume1/gitea-repos/NerdNavis/NerdNavisAi.git/hooks/post-receive-env
|
||||||
|
```
|
||||||
|
|
||||||
|
※ Gitea 관리 UI만 허용되는 환경이면 nas_post_receive.sh 내부 `source "$ENV_FILE"` 대신 직접 상단에 4개 URL을 변수로 하드코딩. 단 이 경우 script 파일 자체의 권한을 600으로 제한 필수.
|
||||||
|
|
||||||
|
### STEP 3 — 테스트
|
||||||
|
NerdNavisAi 저장소에 **의미 없는 테스트 커밋** push:
|
||||||
|
```bash
|
||||||
|
cd E:\NerdNavisAi
|
||||||
|
echo "" >> 공유/조직공지/.test_phase3.md
|
||||||
|
git add 공유/조직공지/.test_phase3.md
|
||||||
|
git commit -m "test(phase3): post-receive webhook 검증"
|
||||||
|
git push origin main
|
||||||
|
|
||||||
|
# 기대 결과: Discord #core-rules 채널에 즉시 알림 도착 ✅
|
||||||
|
|
||||||
|
# 테스트 커밋 원복
|
||||||
|
git rm 공유/조직공지/.test_phase3.md
|
||||||
|
git commit -m "revert: phase3 테스트 커밋"
|
||||||
|
git push origin main
|
||||||
|
```
|
||||||
|
|
||||||
|
### STEP 4 — 설치 완료 보고
|
||||||
|
PD님이 다음 경로로 완료 보고 파일을 작성·커밋:
|
||||||
|
- `공유/소통/PD→PM/2026-MM-DD_Phase3_설치완료.md` (또는 기존 PD 로그)
|
||||||
|
- 제가 fetch 확인 후 Phase 3 가동 확정.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 트러블슈팅
|
||||||
|
|
||||||
|
| 증상 | 원인 | 해결 |
|
||||||
|
|------|------|------|
|
||||||
|
| Discord에 메시지 안 옴 | webhook URL 잘못 | hooks/post-receive.log 확인, curl 수동 테스트 |
|
||||||
|
| 한글 파일명 깨짐 | NAS locale 설정 | `LC_ALL=ko_KR.UTF-8` 를 post-receive 상단 추가 |
|
||||||
|
| 모든 변경에 알림 안 감 | 경로 패턴 미매치 | nas_post_receive.sh 의 case 절 경로를 실제 변경 파일로 조정 |
|
||||||
|
| curl 명령 없음 | NAS busybox 환경 | wget 또는 nc(netcat) 기반으로 변환 필요. 별도 안건 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 보안·C6 준수
|
||||||
|
|
||||||
|
- `post-receive-env` 파일은 **절대 commit 금지**. `.gitignore` 무관 (NAS bare repo 파일)
|
||||||
|
- webhook URL 유출 시 즉시 Discord 채널 편집 → Webhook 삭제·재발급
|
||||||
|
- Discord 서버 자체의 사용자 초대·역할 관리는 PD님 전적 관리
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 연관
|
||||||
|
- **Phase 1** (a556d6a): 공유/소통/ 허브 6축 — 본 알림의 입력
|
||||||
|
- **Phase 2** (9a6ef2f): SessionStart inbox_scan — 세션 내 알림
|
||||||
|
- **Phase 3** (본 문서): NAS 서버측 실시간 알림 — 세션 외 알림
|
||||||
|
- **C21**(초안): C21-1 즉시 push 의무 → Phase 3 알림 실효성의 전제
|
||||||
|
- **C22**: 본 가이드의 용어(Phase 3, inbox, webhook)는 이후 변경 금지
|
||||||
|
|
||||||
|
## 상태
|
||||||
|
|
||||||
|
- [x] scripts/nas_post_receive.sh 커밋 완료
|
||||||
|
- [x] 본 설치 가이드 커밋 완료
|
||||||
|
- [ ] PD님: Discord 서버·채널·webhook URL 4개 준비
|
||||||
|
- [ ] PD님: NAS에 hook 스크립트 배치 + env 파일 생성
|
||||||
|
- [ ] PD님: 테스트 커밋 1건 push → Discord 수신 확인
|
||||||
|
- [ ] 총괄PM: 수신 확인 보고 수령 후 Phase 3 가동 확정
|
||||||
|
|
||||||
|
**준비 완료 시 본 문서의 status 를 `완료` 로 갱신 후 commit·push 부탁드립니다.**
|
||||||
Loading…
Reference in New Issue