Skip to content

Commit 8f7252b

Browse files
committed
refactor: 청크 분리
1 parent 690b891 commit 8f7252b

File tree

1 file changed

+58
-70
lines changed

1 file changed

+58
-70
lines changed

.github/workflows/gemini_review.yml

Lines changed: 58 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -72,134 +72,121 @@ jobs:
7272
git fetch origin "${{ steps.pr_info.outputs.head }}"
7373
git diff "origin/${{ steps.pr_info.outputs.base }}"..."origin/${{ steps.pr_info.outputs.head }}" > diff.txt
7474
75-
- name: Run Gemini Review (Chunked)
75+
- name: Run Gemini Review with Chunking
7676
id: gemini_review
7777
uses: actions/github-script@v7
7878
env:
7979
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
8080
with:
8181
script: |
8282
const fs = require("fs");
83+
8384
const diff_output = fs.readFileSync("diff.txt", "utf8");
85+
if (!diff_output.trim()) {
86+
console.log("No code changes detected, skipping review.");
87+
fs.writeFileSync("review.json", "[]");
88+
return;
89+
}
8490
8591
const { GoogleGenerativeAI } = require("@google/generative-ai");
8692
const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY);
8793
const model = genAI.getGenerativeModel({ model: "gemini-2.5-flash" });
8894
89-
if (!diff_output.trim()) {
90-
fs.writeFileSync("review.json", "[]");
91-
return;
92-
}
95+
const CHUNK_SIZE = 90000;
96+
const chunks = [];
9397
94-
const CHUNK_SIZE = 30000;
95-
let chunks = [];
9698
for (let i = 0; i < diff_output.length; i += CHUNK_SIZE) {
97-
chunks.push(diff_output.slice(i, i + CHUNK_SIZE));
99+
chunks.push(diff_output.substring(i, i + CHUNK_SIZE));
98100
}
99-
console.log(`📦 청크 개수: ${chunks.length}`);
100-
101101
102-
async function askGemini(prompt) {
103-
const res = await model.generateContent(prompt);
104-
return res.response.text();
105-
}
102+
console.log(`📦 총 ${chunks.length}개의 청크로 분할됨`);
106103
107-
let merged = [];
104+
const finalReviews = [];
108105
109106
for (let idx = 0; idx < chunks.length; idx++) {
110107
const chunk = chunks[idx];
111108
109+
console.log(`▶ Gemini 요청 중... 청크 ${idx + 1}/${chunks.length}`);
110+
112111
const prompt = `
113112
Explain in Korean.
114113
115114
당신은 **시니어 프론트엔드 개발자**입니다.
116-
아래 git diff 조각(chunk ${idx+1}/${chunks.length})을 기반으로
117-
변경된 코드의 '변경된 줄'마다 리뷰 코멘트를 생성하세요.
115+
아래 git diff만을 기반으로 변경된 줄에 대한 코드 리뷰 코멘트를 JSON 배열로 작성하세요.
118116
119-
출력은 반드시 **JSON 배열만**:
117+
반드시 아래 형식으로만 출력하세요:
120118
121119
[
122120
{
123121
"path": "src/components/Example.tsx",
124122
"line": 123,
125-
"text": "리뷰 코멘트",
123+
"text": "코멘트",
126124
"side": "RIGHT"
127125
}
128126
]
129127
130128
규칙:
131-
- src 내부의 .ts / .tsx 파일만 리뷰
132-
- 성능 문제 판단
133-
- 타입스크립트 문법/타입 개선 지적
134-
- 변수명/함수명/주석 품질 평가
135-
- 중복 코드/리팩토링 포인트 제안
136-
- 각 코멘트는 1~2줄만 작성
137-
138-
매우 중요:
139-
- "@@ -a,b +c,d @@" 를 사용해 정확한 새 라인 번호 계산
140-
- JSON 코드블록 금지 (```json 포함 금지)
141-
- JSON 외 다른 텍스트를 절대 출력하지 말 것
142-
143-
<git diff>
129+
1. src 내부 .ts / .tsx 파일만 포함
130+
2. 청크에 없는 파일/라인 정보는 절대 작성 금지
131+
3. JSON 이외의 설명 텍스트 절대 금지
132+
133+
<git diff chunk>
144134
${chunk}
145-
</git diff>
135+
</git diff chunk>
146136
`;
147137
148-
console.log(`🤖 Gemini 요청: chunk ${idx+1}/${chunks.length}`);
149-
let raw = await askGemini(prompt);
138+
try {
139+
const result = await model.generateContent(prompt);
140+
let text = result.response.text().trim();
141+
142+
text = text.replace(/```json|```/g, "").trim();
143+
144+
let parsed = [];
145+
try {
146+
parsed = JSON.parse(text);
147+
if (!Array.isArray(parsed)) parsed = [];
148+
} catch (err) {
149+
console.log("⚠ JSON parse 실패 → 해당 청크는 건너뜀");
150+
continue;
151+
}
150152
151-
// 코드블록 제거
152-
raw = raw.replace(/```json/g, "").replace(/```/g, "").trim();
153+
finalReviews.push(...parsed);
153154
154-
try {
155-
const parsed = JSON.parse(raw);
156-
merged.push(...parsed);
157-
} catch (e) {
158-
console.log("❌ JSON 파싱 실패. 출력:");
159-
console.log(raw);
160-
throw e;
155+
} catch (error) {
156+
console.log("❌ Gemini 요청 실패:", error.message);
161157
}
162158
}
163159
164-
fs.writeFileSync("review.json", JSON.stringify(merged, null, 2));
165-
console.log("🎉 모든 청크 JSON 병합 완료");
160+
fs.writeFileSync("review.json", JSON.stringify(finalReviews, null, 2));
161+
console.log("🎉 모든 청크 처리 완료 → review.json 생성됨");
166162
167163
- name: Convert JSON to diff positions
168164
id: convert
169165
uses: actions/github-script@v7
170166
with:
171167
script: |
172168
const fs = require("fs");
173-
174169
let raw = fs.readFileSync("review.json", "utf8")
175-
raw = raw
170+
.trim()
176171
.replace(/```json/g, "")
177172
.replace(/```/g, "")
178-
.trim();
173+
.replace(/^\n+|\n+$/g, "");
179174
180-
const jsonMatch = raw.match(/\[[\s\S]*\]/);
175+
let review;
181176
182-
if (!jsonMatch) {
183-
console.log("❌ JSON 배열을 찾을 수 없음!");
177+
try {
178+
review = JSON.parse(raw);
179+
} catch (err) {
180+
console.log("Gemini JSON parse error");
184181
console.log("Raw output:");
185182
console.log(raw);
186-
throw new Error("Gemini JSON extraction failed");
183+
throw err;
187184
}
188185
189-
let jsonString = jsonMatch[0];
190-
191-
let review;
192-
try {
193-
review = JSON.parse(jsonString);
194-
} catch (e) {
195-
console.log("❌ JSON.parse 실패");
196-
console.log("원본 JSON 문자열:");
197-
console.log(jsonString);
198-
throw e;
199-
}
200186
const diff = fs.readFileSync("diff.txt", "utf8");
201187
202188
const output = [];
189+
203190
const fileBlocks = diff.split("diff --git").slice(1);
204191
205192
for (const block of fileBlocks) {
@@ -229,12 +216,12 @@ jobs:
229216
230217
if (line.startsWith("+")) {
231218
newLine++;
232-
const match = fileComments.find(c => c.line === newLine);
233-
if (match) {
219+
const comment = fileComments.find(c => c.line === newLine);
220+
if (comment) {
234221
output.push({
235222
path,
236223
position,
237-
body: match.text
224+
body: comment.text
238225
});
239226
}
240227
continue;
@@ -245,7 +232,8 @@ jobs:
245232
continue;
246233
}
247234
248-
oldLine++; newLine++;
235+
oldLine++;
236+
newLine++;
249237
}
250238
}
251239
@@ -258,7 +246,7 @@ jobs:
258246
const comments = JSON.parse(`${{ steps.convert.outputs.comments }}`);
259247
260248
if (!comments.length) {
261-
console.log("코멘트 없음 — 리뷰 생략");
249+
console.log("No review comments generated.");
262250
return;
263251
}
264252
@@ -270,4 +258,4 @@ jobs:
270258
comments
271259
});
272260
273-
console.log("라인별 코드 리뷰 제출 완료!");
261+
console.log("라인별 코드 리뷰 제출됨!");

0 commit comments

Comments
 (0)