Skip to content

Commit f5ba785

Browse files
authored
ci: update comment for auto retry (#18230)
1 parent 588d3c1 commit f5ba785

File tree

1 file changed

+95
-63
lines changed

1 file changed

+95
-63
lines changed

.github/scripts/retry_failed_jobs.js

Lines changed: 95 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,52 @@ async function findRelatedPR(github, context, core, workflowRun) {
251251
return null;
252252
}
253253

254+
async function findExistingRetryComment(github, context, core, pr) {
255+
try {
256+
// Get comments for the PR
257+
const { data: comments } = await github.rest.issues.listComments({
258+
owner: context.repo.owner,
259+
repo: context.repo.repo,
260+
issue_number: pr.number,
261+
per_page: 100
262+
});
263+
264+
// Look for our smart retry analysis comment
265+
const retryComment = comments.find(comment =>
266+
comment.user.type === 'Bot' &&
267+
comment.body.includes('## 🤖 Smart Auto-retry Analysis')
268+
);
269+
270+
if (retryComment) {
271+
core.info(`Found existing retry analysis comment: ${retryComment.id}`);
272+
return retryComment;
273+
}
274+
275+
core.info('No existing retry analysis comment found');
276+
return null;
277+
} catch (error) {
278+
core.warning(`Failed to find existing retry comment: ${error.message}`);
279+
return null;
280+
}
281+
}
282+
283+
function getRetryCount(existingComment) {
284+
if (!existingComment) return 0;
285+
286+
// Try to extract retry count from the title
287+
const titleMatch = existingComment.body.match(/## 🤖 Smart Auto-retry Analysis\s*(?:\(Retry #(\d+)\))?/);
288+
if (titleMatch && titleMatch[1]) {
289+
return parseInt(titleMatch[1], 10);
290+
}
291+
292+
// If no retry count in title, check if it's a retry by looking for retry indicators
293+
if (existingComment.body.includes('### ✅ **AUTO-RETRY INITIATED**')) {
294+
return 1; // This is likely the first retry
295+
}
296+
297+
return 0;
298+
}
299+
254300
async function addCommentToPR(github, context, core, runID, runURL, failedJobs, analyzedJobs, retryableJobsCount, priorityCancelled) {
255301
try {
256302
// Get workflow run to find the branch
@@ -268,107 +314,93 @@ async function addCommentToPR(github, context, core, runID, runURL, failedJobs,
268314
return;
269315
}
270316

271-
let comment = `## 🤖 Smart Auto-retry Analysis
317+
// Try to find existing retry comment
318+
const existingComment = await findExistingRetryComment(github, context, core, pr);
272319

273-
> **Workflow Run:** [\`${runID}\`](${runURL})
320+
// Get current retry count
321+
const currentRetryCount = getRetryCount(existingComment);
322+
const newRetryCount = retryableJobsCount > 0 ? currentRetryCount + 1 : currentRetryCount;
274323

275-
The workflow run has been analyzed for retryable errors using job annotations.
324+
// Build title with retry count
325+
const titleSuffix = newRetryCount > 0 ? ` (Retry #${newRetryCount})` : '';
276326

277-
---
327+
let comment = `## 🤖 Smart Auto-retry Analysis${titleSuffix}
278328
279-
### 📊 Analysis Summary
329+
> **Workflow:** [\`${runID}\`](${runURL})
280330
281-
| Metric | Count |
282-
|--------|-------|
283-
| **Total Failed/Cancelled Jobs** | \`${failedJobs.length}\` |
284-
| **Jobs with Retryable Errors** | \`${retryableJobsCount}\` |
285-
| **Jobs with Code/Test Issues** | \`${failedJobs.length - retryableJobsCount}\` |`;
331+
### 📊 Summary
332+
- **Failed Jobs:** ${failedJobs.length}
333+
- **Retryable:** ${retryableJobsCount}
334+
- **Code Issues:** ${failedJobs.length - retryableJobsCount}`;
286335

287336
if (priorityCancelled) {
288337
comment += `
289338
290-
### ⛔️ Retry Status: **CANCELLED**
291-
292-
> **Reason:** Higher priority request detected - retry has been cancelled to avoid resource conflicts.`;
339+
### ⛔️ **CANCELLED**
340+
Higher priority request detected - retry cancelled to avoid conflicts.`;
293341
} else if (retryableJobsCount > 0) {
294342
comment += `
295343
296-
### ✅ Retry Status: **AUTOMATIC RETRY INITIATED**
344+
### ✅ **AUTO-RETRY INITIATED**
345+
**${retryableJobsCount} job(s)** retried due to infrastructure issues (runner failures, timeouts, etc.)
297346
298-
> **${retryableJobsCount} job(s)** have been automatically retried due to infrastructure issues detected in annotations:
299-
> - Runner communication failures
300-
> - Network timeouts
301-
> - Resource exhaustion
302-
> - Other transient infrastructure problems
303-
304-
**📈 Monitor Progress:** [View in Actions](${runURL})`;
347+
[View Progress](${runURL})`;
305348
} else {
306349
comment += `
307350
308-
### ❌ Retry Status: **NO RETRY NEEDED**
309-
310-
> All failures appear to be **code or test related issues** that require manual fixes rather than automatic retries.`;
351+
### ❌ **NO RETRY NEEDED**
352+
All failures appear to be code/test issues requiring manual fixes.`;
311353
}
312354

313355
comment += `
314356
315-
---
316-
317-
### 🔍 Detailed Job Analysis
318-
357+
### 🔍 Job Details
319358
${analyzedJobs.map(job => {
320359
if (job.reason.includes('Analysis failed')) {
321-
return `#### ❓ **${job.name}**
322-
> **Status:** Analysis failed
323-
> **Reason:** ${job.reason}`;
360+
return `- ❓ **${job.name}**: Analysis failed`;
324361
}
325362
if (job.reason.includes('Cancelled by higher priority')) {
326-
return `#### ⛔️ **${job.name}**
327-
> **Status:** Cancelled by higher priority request
328-
> **Reason:** ${job.reason}`;
363+
return `- ⛔️ **${job.name}**: Cancelled by higher priority`;
329364
}
330365
if (job.reason.includes('No annotations found')) {
331-
return `#### ❓ **${job.name}**
332-
> **Status:** No annotations available
333-
> **Reason:** ${job.reason}`;
366+
return `- ❓ **${job.name}**: No annotations available`;
334367
}
335368
if (job.retryable) {
336-
return `#### 🔄 **${job.name}**
337-
> **Status:** ✅ **Retryable** (Infrastructure Issue)
338-
> **Reason:** ${job.reason}
339-
> **Annotations:** ${job.annotationCount} found`;
369+
return `- 🔄 **${job.name}**: ✅ Retryable (Infrastructure)`;
340370
} else {
341-
return `#### ❌ **${job.name}**
342-
> **Status:** Not retryable (Code/Test Issue)
343-
> **Reason:** ${job.reason}
344-
> **Annotations:** ${job.annotationCount} found`;
371+
return `- ❌ **${job.name}**: Not retryable (Code/Test)`;
345372
}
346-
}).join('\n\n')}
373+
}).join('\n')}
347374
348375
---
349376
350377
<details>
351-
<summary>🤖 About This Analysis</summary>
352-
353-
This is an **automated analysis and retry** triggered by the smart retry workflow using job annotations. The system analyzes failure patterns to distinguish between:
354-
355-
- **🔄 Infrastructure Issues:** Runner failures, network timeouts, resource exhaustion
356-
- **❌ Code/Test Issues:** Compilation errors, test failures, logic problems
357-
358-
Only infrastructure issues are automatically retried to avoid wasting resources on code problems that need manual fixes.
378+
<summary>🤖 About</summary>
359379
380+
Automated analysis using job annotations to distinguish infrastructure issues (auto-retried) from code/test issues (manual fixes needed).
360381
</details>`;
361382

362-
await github.rest.issues.createComment({
363-
owner: context.repo.owner,
364-
repo: context.repo.repo,
365-
issue_number: pr.number,
366-
body: comment
367-
});
368-
369-
core.info(`Added smart retry analysis comment to PR #${pr.number}`);
383+
if (existingComment) {
384+
// Update existing comment
385+
await github.rest.issues.updateComment({
386+
owner: context.repo.owner,
387+
repo: context.repo.repo,
388+
comment_id: existingComment.id,
389+
body: comment
390+
});
391+
core.info(`Updated existing smart retry analysis comment on PR #${pr.number} (Retry #${newRetryCount})`);
392+
} else {
393+
// Create new comment
394+
await github.rest.issues.createComment({
395+
owner: context.repo.owner,
396+
repo: context.repo.repo,
397+
issue_number: pr.number,
398+
body: comment
399+
});
400+
core.info(`Added new smart retry analysis comment to PR #${pr.number}`);
401+
}
370402
} catch (error) {
371-
core.error(`Failed to add comment to PR:`, error.message);
403+
core.error(`Failed to add/update comment to PR:`, error.message);
372404
}
373405
}
374406

0 commit comments

Comments
 (0)