while(1) work();
반응형

(vscode 사용자용)

방법

  1. codex 또는 copilot cli 설치: npm i -g @openai/codex
  2. 프로젝트 루트에서 codex 입력하여 계정 등 설정
  3. .git/hooks/post-commit에 아래 코드 저장
  4. 실행 권한 부여: chmod +x .git/hooks/post-commit

hook 코드

#!/bin/bash

################################################################################
# 설정
################################################################################

# 모델 설정
# LARGE_MODEL_LINE_THRESHOLD 이상의 변경이 있으면 대형 모델 사용, 그렇지 않으면 기본 모델 사용

# AGENT="copilot"
# DEFAULT_MODEL="gpt-5-mini"
# LARGE_CHANGE_MODEL="gpt-5.1-codex-mini"
# LARGE_MODEL_LINE_THRESHOLD=50

AGENT="codex"
DEFAULT_MODEL="gpt-5.3-codex"
LARGE_CHANGE_MODEL="gpt-5.3-codex"
LARGE_MODEL_LINE_THRESHOLD=50

# 사용할 디렉토리 및 파일명
REVIEW_DIR=".review"
PROMPT_FILE_NAME="prompt.md"
REVIEW_FILE_PREFIX="REVIEW"

# 유지할 리뷰 파일 개수
KEEP_COUNT=10

# 리뷰 프롬프트 (프롬프트 파일 없을 때 사용되는 기본값)
# $commit$ 은 마지막 커밋 해시로 치환됨
DEFAULT_REVIEW_PROMPT="내 커밋(hash: $commit$) 변경사항에 대해서 리뷰해줘. (커밋에 포함되지 않은 코드는 리뷰 대상 아님) 버그와 논리적 오류를 중점적으로 찾아줘."

# 리뷰 생략할 커밋 메시지 (아래 내용이 포함되는 경우 리뷰 생략)
SKIP_COMMIT_KEYWORD="--wip--"


################################################################################
# 실행
################################################################################

REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
GIT_DIR=$(git rev-parse --git-dir 2>/dev/null || echo "$REPO_ROOT/.git")
PROMPT_FILE="$REPO_ROOT/$REVIEW_DIR/$PROMPT_FILE_NAME"

# rebase 과정에서 생성되는 커밋에는 훅 실행 생략
if [ -d "$GIT_DIR/rebase-merge" ] || [ -d "$GIT_DIR/rebase-apply" ] || [[ "${GIT_REFLOG_ACTION:-}" == rebase* ]]; then
    exit 0
fi

COMMIT_ID=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown")
COMMIT_HASH=$(git rev-parse HEAD 2>/dev/null || echo "$COMMIT_ID")
TS=$(date +"%y%m%d-%H%M")

if [ -f "$PROMPT_FILE" ]; then
    REVIEW_PROMPT=$(cat "$PROMPT_FILE")
else
    REVIEW_PROMPT="$DEFAULT_REVIEW_PROMPT"
fi

# 리뷰 프롬프트 내 $commit$ 을을 마지막 커밋 해시로 치환
REVIEW_PROMPT="${REVIEW_PROMPT//\$commit\$/$COMMIT_HASH}"

REVIEW_DIR="$REPO_ROOT/$REVIEW_DIR"
mkdir -p "$REVIEW_DIR"

REVIEW_FILE_PATH="$REVIEW_DIR/$REVIEW_FILE_PREFIX-$TS-$COMMIT_ID.md"

# 마지막 커밋의 추가+삭제된 라인 수 합산
CHANGED_LINES=$(git show --numstat --pretty="" HEAD 2>/dev/null | awk '{a+=$1; d+=$2} END {print a+d+0}')
CHANGED_LINES=${CHANGED_LINES:-0}

case "${AGENT,,}" in
    copilot|codex) ;; 
    *)
        echo "Invalid AGENT value: '$AGENT'. Must be 'copilot' or 'codex'." >&2
        exit 1
        ;;
esac

# N줄 이상 변경이면 대형 모델 사용
if [ "$CHANGED_LINES" -ge "$LARGE_MODEL_LINE_THRESHOLD" ]; then
    MODEL="$LARGE_CHANGE_MODEL"
else
    MODEL="$DEFAULT_MODEL"
fi

# WIP 커밋이면 리뷰 생략
COMMIT_MSG=$(git log -1 --pretty=%B 2>/dev/null || true)
if echo "$COMMIT_MSG" | grep -qi -- "$SKIP_COMMIT_KEYWORD"; then
    echo "$SKIP_COMMIT_KEYWORD commit message detected; skipping Copilot review."
    exit 0
fi

# 파일 경로를 stdout에 출력
echo '----------------- CODE REVIEW ------------------'
echo "$REVIEW_FILE_PATH"
echo '------------------------------------------------'

# 헤더를 파일에 작성 (모델, 커밋 정보 등)
{
    echo "<!-- Copilot review started -->"
    echo "<!-- Date: $(date +"%Y-%m-%d %H:%M:%S") -->"
    echo "<!-- Model: $MODEL -->"
    echo "<!-- Commit: $COMMIT_ID -->"
    echo "<!-- Commit message: $(git log -1 --pretty=%B 2>/dev/null || true) -->"
} > "$REVIEW_FILE_PATH"

# 에디터로 최종 파일 열기
code "$REVIEW_FILE_PATH"


# 에이전트에 따라 분기해서 비동기(detached)로 실행
# 리뷰 종료 후에도 에디터로 열기
if [ "${AGENT,,}" = "copilot" ]; then
    setsid nohup bash -c "out=\$(copilot --model \"$MODEL\" -p '$REVIEW_PROMPT' 2>>\"$REVIEW_FILE_PATH\"); for i in \$(seq 1 20); do printf '\\n' >> \"$REVIEW_FILE_PATH\"; done; printf '%s' \"\$out\" >> \"$REVIEW_FILE_PATH\"; code --goto \"${REVIEW_FILE_PATH}:999999\"" >/dev/null 2>&1 &
elif [ "${AGENT,,}" = "codex" ]; then
    setsid nohup bash -c "out=\$(codex exec --model \"$MODEL\" '$REVIEW_PROMPT' 2>>\"$REVIEW_FILE_PATH\"); for i in \$(seq 1 20); do printf '\\n' >> \"$REVIEW_FILE_PATH\"; done; printf '%s' \"\$out\" >> \"$REVIEW_FILE_PATH\"; code --goto \"${REVIEW_FILE_PATH}:999999\"" >/dev/null 2>&1 &
fi

AGENT_PID=$!
echo "<!-- Agent PID: $AGENT_PID (stop agent: \`kill -9 -- -$AGENT_PID\`) -->" >> "$REVIEW_FILE_PATH"
echo "" >> "$REVIEW_FILE_PATH"

# 최신 KEEP_COUNT개의 리뷰만 보관
{
    # count 확인 및 삭제
    total=$(find "$REVIEW_DIR" -maxdepth 1 -type f -name "$REVIEW_FILE_PREFIX-*.md" | wc -l)
    if [ "$total" -gt "$KEEP_COUNT" ]; then
        find "$REVIEW_DIR" -maxdepth 1 -type f -name "$REVIEW_FILE_PREFIX-*.md" -printf '%T@ %p\n' | sort -rn | awk -v keep="$KEEP_COUNT" 'NR>keep{print $2}' | xargs -r rm -f
    fi
} &

exit 0
반응형

'기타' 카테고리의 다른 글

Google의 귀여운 실수  (0) 2022.03.10
profile

while(1) work();

@유호건

❤️댓글은 언제나 힘이 됩니다❤️ 궁금한 점이나 잘못된 내용이 있다면 댓글로 남겨주세요.

검색 태그