refactor: 라인별 코드리뷰로 변경 #61
Workflow file for this run
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
| name: Gemini Automated Code Review | |
| on: | |
| pull_request: | |
| types: [opened, synchronize, reopened] | |
| branches: [main] | |
| push: | |
| branches: | |
| - main | |
| workflow_dispatch: | |
| inputs: | |
| pr_number: | |
| description: "리뷰할 PR 번호 (수동 실행 시 필수)" | |
| required: true | |
| jobs: | |
| code-review: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Install GitHub CLI | |
| run: sudo apt-get install -y gh jq | |
| - name: Set up Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| - name: Install GoogleGenerativeAI SDK | |
| run: npm install @google/generative-ai@latest | |
| - name: Get git diff for PR | |
| if: github.event_name == 'pull_request' | |
| run: | | |
| echo "EVENT_TYPE=pull_request" >> $GITHUB_ENV | |
| echo "PR_NUMBER=${{ github.event.pull_request.number }}" >> $GITHUB_ENV | |
| git fetch origin "${{ github.event.pull_request.base.ref }}" | |
| git fetch origin "${{ github.event.pull_request.head.ref }}" | |
| git diff --unified=0 "origin/${{ github.event.pull_request.base.ref }}" "origin/${{ github.event.pull_request.head.ref }}" > diff.txt | |
| - name: Get git diff for manual PR review | |
| if: github.event_name == 'workflow_dispatch' | |
| run: | | |
| PR_NUMBER="${{ github.event.inputs.pr_number }}" | |
| echo "EVENT_TYPE=pull_request" >> $GITHUB_ENV | |
| echo "PR_NUMBER=$PR_NUMBER" >> $GITHUB_ENV | |
| BASE=$(gh pr view $PR_NUMBER --json baseRefName -q .baseRefName) | |
| HEAD=$(gh pr view $PR_NUMBER --json headRefName -q .headRefName) | |
| git fetch origin $BASE | |
| git fetch origin $HEAD | |
| git diff --unified=0 origin/$BASE origin/$HEAD > diff.txt | |
| - name: Detect PR for push event | |
| if: github.event_name == 'push' | |
| run: | | |
| PR_NUMBER=$(gh pr list --state open --json number,headRefName \ | |
| --jq ".[] | select(.headRefName==\"${GITHUB_REF_NAME}\") | .number") | |
| if [ -z "$PR_NUMBER" ]; then | |
| echo "Push된 커밋과 연결된 PR을 찾을 수 없습니다." | |
| exit 1 | |
| fi | |
| echo "EVENT_TYPE=pull_request" >> $GITHUB_ENV | |
| echo "PR_NUMBER=$PR_NUMBER" >> $GITHUB_ENV | |
| BASE=$(gh pr view $PR_NUMBER --json baseRefName -q .baseRefName) | |
| HEAD=$(gh pr view $PR_NUMBER --json headRefName -q .headRefName) | |
| git fetch origin $BASE | |
| git fetch origin $HEAD | |
| git diff --unified=0 origin/$BASE origin/$HEAD > diff.txt | |
| - name: Run Gemini Review (File-based Chunking) | |
| id: gemini_review | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const fs = require("fs"); | |
| const { GoogleGenerativeAI } = require("@google/generative-ai"); | |
| const rawDiff = fs.readFileSync("diff.txt", "utf8"); | |
| const fileDiffs = rawDiff | |
| .split("diff --git") | |
| .slice(1) | |
| .map(block => "diff --git" + block); | |
| const tsDiffs = fileDiffs.filter(block => | |
| /a\/src\/.*\.(ts|tsx)/.test(block) | |
| ); | |
| console.log("Filtered ts/tsx files:", tsDiffs.length); | |
| const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY); | |
| const model = genAI.getGenerativeModel({ model: "gemini-2.5-flash" }); | |
| let allComments = []; | |
| for (let i = 0; i < tsDiffs.length; i++) { | |
| const diffBlock = tsDiffs[i]; | |
| const prompt = ` | |
| 당신은 시니어 프론트엔드 개발자입니다. | |
| 아래는 특정 파일의 diff입니다. | |
| **src/ 내부의 .ts / .tsx 파일만 리뷰합니다.** | |
| JSON 배열 형식만 출력하세요: | |
| [ | |
| { | |
| "path": "파일경로", | |
| "line": 라인번호, | |
| "text": "리뷰내용", | |
| "side": "RIGHT" | |
| } | |
| ] | |
| JSON 외 텍스트 금지. | |
| <file diff ${i + 1}/${tsDiffs.length}> | |
| ${diffBlock} | |
| </file diff> | |
| `; | |
| console.log("Reviewing file " + (i + 1)); | |
| try { | |
| const result = await model.generateContent(prompt); | |
| const text = result.response.text(); | |
| const parsed = JSON.parse(text); | |
| allComments.push(...parsed); | |
| } catch (err) { | |
| console.log("⚠️ Gemini error for file", i + 1); | |
| console.log(err); | |
| } | |
| } | |
| fs.writeFileSync("review_result.txt", JSON.stringify(allComments, null, 2)); | |
| console.log("Review saved!"); | |
| - name: Add PR Review Comments | |
| uses: nbaztec/add-pr-review-comment@v1.0.7 | |
| with: | |
| comments: ${{ steps.gemini_review.outputs.comment }} | |
| repo-token: ${{ secrets.GITHUB_TOKEN }} | |
| repo-token-user-login: "github-actions[bot]" | |
| allow-repeats: false |