Skip to content

Commit 2129134

Browse files
authored
Merge pull request #20 from DaleStudy/issue-7-synchronize-optimization
feat: synchronize ์ด๋ฒคํŠธ ์‹œ ๋ณ€๊ฒฝ๋œ ํŒŒ์ผ๋งŒ ํŒจํ„ด ์žฌ๋ถ„์„
2 parents d5fa7a4 + 73869b0 commit 2129134

File tree

2 files changed

+74
-12
lines changed

2 files changed

+74
-12
lines changed

โ€Žhandlers/tag-patterns.jsโ€Ž

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const MAX_FILE_SIZE = 20000; // 20K ๋ฌธ์ž ์ œํ•œ (OpenAI ํ† ํฐ ์•ˆ์ „์žฅ์น˜)
2323
* @param {object} prData - PR ๊ฐ์ฒด (draft, labels ํฌํ•จ)
2424
* @param {string} appToken - GitHub App installation token
2525
* @param {string} openaiApiKey
26+
* @param {string[]|null} [changedFilenames=null] - synchronize ์‹œ ๋ณ€๊ฒฝ๋œ ํŒŒ์ผ๋ช… ๋ชฉ๋ก (null์ด๋ฉด ์ „์ฒด ๋ถ„์„)
2627
*/
2728
export async function tagPatterns(
2829
repoOwner,
@@ -31,7 +32,8 @@ export async function tagPatterns(
3132
headSha,
3233
prData,
3334
appToken,
34-
openaiApiKey
35+
openaiApiKey,
36+
changedFilenames = null
3537
) {
3638
// 2-1. Skip ์กฐ๊ฑด
3739
if (prData.draft === true) {
@@ -58,22 +60,34 @@ export async function tagPatterns(
5860
}
5961

6062
const allFiles = await filesResponse.json();
61-
const solutionFiles = allFiles.filter(
63+
let solutionFiles = allFiles.filter(
6264
(f) =>
6365
(f.status === "added" || f.status === "modified") &&
6466
SOLUTION_PATH_REGEX.test(f.filename)
6567
);
6668

69+
// changedFilenames๊ฐ€ ์ œ๊ณต๋˜๋ฉด ํ•ด๋‹น ํŒŒ์ผ๋งŒ ๋Œ€์ƒ์œผ๋กœ ์ขํž˜ (synchronize ์ตœ์ ํ™”)
70+
if (changedFilenames !== null) {
71+
const changedSet = new Set(changedFilenames);
72+
solutionFiles = solutionFiles.filter((f) => changedSet.has(f.filename));
73+
console.log(
74+
`[tagPatterns] PR #${prNumber}: narrowed to ${solutionFiles.length} changed solution files`
75+
);
76+
}
77+
6778
console.log(
68-
`[tagPatterns] PR #${prNumber}: ${allFiles.length} files, ${solutionFiles.length} solution files`
79+
`[tagPatterns] PR #${prNumber}: ${allFiles.length} total files, ${solutionFiles.length} solution files to analyze`
6980
);
7081

7182
if (solutionFiles.length === 0) {
7283
return { skipped: "no-solution-files" };
7384
}
7485

75-
// 2-3. ๊ธฐ์กด Bot ํŒจํ„ด ํƒœ๊ทธ ์ฝ”๋ฉ˜ํŠธ ์‚ญ์ œ
76-
await deletePreviousPatternComments(repoOwner, repoName, prNumber, appToken);
86+
// 2-3. ๊ธฐ์กด Bot ํŒจํ„ด ํƒœ๊ทธ ์ฝ”๋ฉ˜ํŠธ ์‚ญ์ œ (๋ณ€๊ฒฝ ํŒŒ์ผ๋งŒ)
87+
const targetFilenames = solutionFiles.map((f) => f.filename);
88+
await deletePreviousPatternComments(
89+
repoOwner, repoName, prNumber, appToken, targetFilenames
90+
);
7791

7892
// 2-4. ํŒŒ์ผ๋ณ„ OpenAI ๋ถ„์„ + ์ฝ”๋ฉ˜ํŠธ ์ž‘์„ฑ (๊ฐ ํŒŒ์ผ try/catch ๋ž˜ํ•‘)
7993
const results = [];
@@ -101,13 +115,16 @@ export async function tagPatterns(
101115
}
102116

103117
/**
104-
* ๊ธฐ์กด Bot ํŒจํ„ด ํƒœ๊ทธ ์ฝ”๋ฉ˜ํŠธ ์‚ญ์ œ (๋‹ค๋ฅธ ์‚ฌ์šฉ์ž ์ฝ”๋ฉ˜ํŠธ๋Š” ์ ˆ๋Œ€ ๊ฑด๋“œ๋ฆฌ์ง€ ์•Š์Œ)
118+
* ๊ธฐ์กด Bot ํŒจํ„ด ํƒœ๊ทธ ์ฝ”๋ฉ˜ํŠธ ์‚ญ์ œ (๋Œ€์ƒ ํŒŒ์ผ๋งŒ, ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž ์ฝ”๋ฉ˜ํŠธ๋Š” ์ ˆ๋Œ€ ๊ฑด๋“œ๋ฆฌ์ง€ ์•Š์Œ)
119+
*
120+
* @param {string[]} targetFilenames - ์‚ญ์ œ ๋Œ€์ƒ ํŒŒ์ผ๋ช… ๋ชฉ๋ก
105121
*/
106122
async function deletePreviousPatternComments(
107123
repoOwner,
108124
repoName,
109125
prNumber,
110-
appToken
126+
appToken,
127+
targetFilenames
111128
) {
112129
const response = await fetch(
113130
`https://api.github.com/repos/${repoOwner}/${repoName}/pulls/${prNumber}/comments?per_page=100`,
@@ -122,8 +139,12 @@ async function deletePreviousPatternComments(
122139
}
123140

124141
const comments = await response.json();
142+
const targetSet = new Set(targetFilenames);
125143
const botPatternComments = comments.filter(
126-
(c) => c.user?.type === "Bot" && c.body?.includes(COMMENT_MARKER)
144+
(c) =>
145+
c.user?.type === "Bot" &&
146+
c.body?.includes(COMMENT_MARKER) &&
147+
targetSet.has(c.path)
127148
);
128149

129150
for (const comment of botPatternComments) {
@@ -149,7 +170,7 @@ async function deletePreviousPatternComments(
149170
}
150171

151172
console.log(
152-
`[tagPatterns] Deleted ${botPatternComments.length} previous pattern comments`
173+
`[tagPatterns] Deleted ${botPatternComments.length} previous pattern comments for ${targetFilenames.length} files`
153174
);
154175
}
155176

โ€Žhandlers/webhooks.jsโ€Ž

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,10 +204,35 @@ async function handleProjectsV2ItemEvent(payload, env) {
204204
});
205205
}
206206

207+
/**
208+
* Compare API๋กœ ๋‘ ์ปค๋ฐ‹ ์‚ฌ์ด์— ๋ณ€๊ฒฝ๋œ ํŒŒ์ผ๋ช… ๋ชฉ๋ก ์กฐํšŒ
209+
*
210+
* @param {string} repoOwner
211+
* @param {string} repoName
212+
* @param {string} baseSha - ์ด์ „ ์ปค๋ฐ‹ SHA
213+
* @param {string} headSha - ์ƒˆ ์ปค๋ฐ‹ SHA
214+
* @param {string} appToken
215+
* @returns {Promise<string[]|null>} ๋ณ€๊ฒฝ๋œ ํŒŒ์ผ๋ช… ๋ฐฐ์—ด (์‹คํŒจ ์‹œ null โ†’ ์ „์ฒด ๋ถ„์„ fallback)
216+
*/
217+
async function getChangedFilenames(repoOwner, repoName, baseSha, headSha, appToken) {
218+
const response = await fetch(
219+
`https://api.github.com/repos/${repoOwner}/${repoName}/compare/${baseSha}...${headSha}`,
220+
{ headers: getGitHubHeaders(appToken) }
221+
);
222+
223+
if (!response.ok) {
224+
console.error(`[getChangedFilenames] Compare API failed: ${response.status}`);
225+
return null;
226+
}
227+
228+
const data = await response.json();
229+
return (data.files || []).map((f) => f.filename);
230+
}
231+
207232
/**
208233
* Pull Request ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ
209-
* - opened/reopened: Week ์„ค์ • ์ฒดํฌ + ์•Œ๊ณ ๋ฆฌ์ฆ˜ ํŒจํ„ด ํƒœ๊น…
210-
* - synchronize: ์•Œ๊ณ ๋ฆฌ์ฆ˜ ํŒจํ„ด ํƒœ๊น…๋งŒ (Week ์ฒดํฌ ์Šคํ‚ต - ์ด๋ฏธ ์„ค์ •๋์„ ๊ฐ€๋Šฅ์„ฑ ๋†’์Œ)
234+
* - opened/reopened: Week ์„ค์ • ์ฒดํฌ + ์•Œ๊ณ ๋ฆฌ์ฆ˜ ํŒจํ„ด ํƒœ๊น… (์ „์ฒด ํŒŒ์ผ)
235+
* - synchronize: ์•Œ๊ณ ๋ฆฌ์ฆ˜ ํŒจํ„ด ํƒœ๊น…๋งŒ (๋ณ€๊ฒฝ๋œ ํŒŒ์ผ๋งŒ, Week ์ฒดํฌ ์Šคํ‚ต)
211236
*/
212237
async function handlePullRequestEvent(payload, env) {
213238
const action = payload.action;
@@ -256,14 +281,30 @@ async function handlePullRequestEvent(payload, env) {
256281
// ์•Œ๊ณ ๋ฆฌ์ฆ˜ ํŒจํ„ด ํƒœ๊น… (OPENAI_API_KEY ์žˆ์„ ๋•Œ๋งŒ)
257282
if (env.OPENAI_API_KEY) {
258283
try {
284+
// synchronize์ผ ๋•Œ๋งŒ ๋ณ€๊ฒฝ ํŒŒ์ผ ๋ชฉ๋ก ์ถ”์ถœ (์ตœ์ ํ™”: #7)
285+
let changedFilenames = null;
286+
if (action === "synchronize" && payload.before && payload.after) {
287+
changedFilenames = await getChangedFilenames(
288+
repoOwner,
289+
repoName,
290+
payload.before,
291+
payload.after,
292+
appToken
293+
);
294+
console.log(
295+
`[handlePullRequestEvent] synchronize: ${changedFilenames?.length ?? "fallback(all)"} files changed between ${payload.before.slice(0, 7)}...${payload.after.slice(0, 7)}`
296+
);
297+
}
298+
259299
await tagPatterns(
260300
repoOwner,
261301
repoName,
262302
prNumber,
263303
pr.head.sha,
264304
pr,
265305
appToken,
266-
env.OPENAI_API_KEY
306+
env.OPENAI_API_KEY,
307+
changedFilenames
267308
);
268309
} catch (error) {
269310
console.error(`[handlePullRequestEvent] tagPatterns failed: ${error.message}`);

0 commit comments

Comments
ย (0)