@@ -101,6 +101,19 @@ jobs:
101101 break;
102102 }
103103
104+ const changedLines = files.reduce((sum, file) => sum + file.additions + file.deletions, 0);
105+ let priority = 'Medium';
106+ if (labels.has('data') && (files.length >= 25 || changedLines >= 1000)) {
107+ priority = 'High';
108+ } else if (labels.has('data') || labels.has('app') || title.startsWith('fix')) {
109+ priority = 'High';
110+ } else if (labels.size === 1 && labels.has('documentation')) {
111+ priority = 'Low';
112+ } else if (changedLines <= 25 && !labels.has('ci')) {
113+ priority = 'Low';
114+ }
115+ core.exportVariable('TRIAGE_PRIORITY', priority);
116+
104117 const trackingIssuesByLabel = new Map([
105118 ['data', 1],
106119 ['site', 19],
@@ -131,20 +144,97 @@ jobs:
131144 body: updatedBody,
132145 });
133146 }
134- }
135147
136- const changedLines = files.reduce((sum, file) => sum + file.additions + file.deletions, 0);
137- let priority = 'Medium';
138- if (labels.has('data') && (files.length >= 25 || changedLines >= 1000)) {
139- priority = 'High';
140- } else if (labels.has('data') || labels.has('app') || title.startsWith('fix')) {
141- priority = 'High';
142- } else if (labels.size === 1 && labels.has('documentation')) {
143- priority = 'Low';
144- } else if (changedLines <= 25 && !labels.has('ci')) {
145- priority = 'Low';
148+ const changedByTopLevel = new Map();
149+ const changedData = new Map([
150+ ['brand', { added: 0, modified: 0, deleted: 0 }],
151+ ['soc', { added: 0, modified: 0, deleted: 0 }],
152+ ['smartphone', { added: 0, modified: 0, deleted: 0 }],
153+ ['gpu', { added: 0, modified: 0, deleted: 0 }],
154+ ['cpu', { added: 0, modified: 0, deleted: 0 }],
155+ ]);
156+ for (const file of files) {
157+ const top = file.filename.split('/')[0] || '(root)';
158+ changedByTopLevel.set(top, (changedByTopLevel.get(top) || 0) + 1);
159+ const parts = file.filename.split('/');
160+ if (parts[0] === 'data' && changedData.has(parts[1])) {
161+ const bucket = changedData.get(parts[1]);
162+ const status = file.status === 'removed'
163+ ? 'deleted'
164+ : file.status === 'added'
165+ ? 'added'
166+ : 'modified';
167+ bucket[status] += 1;
168+ }
169+ }
170+
171+ const dataRows = [...changedData.entries()]
172+ .filter(([, counts]) => counts.added || counts.modified || counts.deleted)
173+ .map(([category, counts]) => `| ${category} | ${counts.added} | ${counts.modified} | ${counts.deleted} |`)
174+ .join('\n') || '| none | 0 | 0 | 0 |';
175+ const topRows = [...changedByTopLevel.entries()]
176+ .sort((a, b) => b[1] - a[1])
177+ .slice(0, 8)
178+ .map(([area, count]) => `| ${area} | ${count} |`)
179+ .join('\n');
180+ const labelText = [...labels].sort().map((label) => `\`${label}\``).join(', ') || 'none';
181+ const trackerComment = [
182+ `<!-- techapi-tracking-issue-pr-${issue_number} -->`,
183+ `## Linked PR update: ${pr.title} #${issue_number}`,
184+ '',
185+ `- PR: ${pr.html_url}`,
186+ `- Branch: \`${pr.head.ref}\``,
187+ `- Author: @${pr.user.login}`,
188+ `- Labels: ${labelText}`,
189+ `- Priority: ${priority}`,
190+ `- Files changed: ${files.length}`,
191+ `- Lines changed: +${files.reduce((sum, file) => sum + file.additions, 0)} / -${files.reduce((sum, file) => sum + file.deletions, 0)}`,
192+ '',
193+ '### Changed Data',
194+ '',
195+ '| Category | Added | Modified | Deleted |',
196+ '| --- | ---: | ---: | ---: |',
197+ dataRows,
198+ '',
199+ '### Changed Areas',
200+ '',
201+ '| Area | Files |',
202+ '| --- | ---: |',
203+ topRows || '| none | 0 |',
204+ '',
205+ '### Notes',
206+ '',
207+ '- This is an automatic tracking comment for the long-running issue.',
208+ '- PR validation details are posted on the PR by TechEngineBot.',
209+ '- The tracker issue remains open even when the PR uses `Closes #...` for GitHub Development linking.',
210+ ].join('\n');
211+
212+ for (const issueNumber of trackingIssues) {
213+ const comments = await github.paginate(github.rest.issues.listComments, {
214+ owner,
215+ repo,
216+ issue_number: issueNumber,
217+ per_page: 100,
218+ });
219+ const marker = `<!-- techapi-tracking-issue-pr-${issue_number} -->`;
220+ const existing = comments.find((comment) => comment.body?.includes(marker));
221+ if (existing) {
222+ await github.rest.issues.updateComment({
223+ owner,
224+ repo,
225+ comment_id: existing.id,
226+ body: trackerComment,
227+ });
228+ } else {
229+ await github.rest.issues.createComment({
230+ owner,
231+ repo,
232+ issue_number: issueNumber,
233+ body: trackerComment,
234+ });
235+ }
236+ }
146237 }
147- core.exportVariable('TRIAGE_PRIORITY', priority);
148238
149239 - name : Add PR to configured projects
150240 if : env.TRIAGE_PROJECT_URLS != '' && env.PROJECT_TOKEN != ''
0 commit comments