@@ -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 */
2728export 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 */
106122async 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
0 commit comments