@@ -447,3 +447,103 @@ jobs:
447447 with :
448448 node_version : ${{ env.NODE_VERSION }}
449449 artifact_name : ${{ needs.setup.outputs.vsix_artifact_name }}-${{ matrix.vsix-target }}
450+
451+ report-failure :
452+ name : Report CI Failure
453+ if : |
454+ always() &&
455+ github.repository == 'microsoft/vscode-python' &&
456+ github.ref == 'refs/heads/main' &&
457+ (needs.build-vsix.result == 'failure' ||
458+ needs.lint.result == 'failure' ||
459+ needs.check-types.result == 'failure' ||
460+ needs.python-tests.result == 'failure' ||
461+ needs.tests.result == 'failure' ||
462+ needs.smoke-tests.result == 'failure')
463+ runs-on : ubuntu-latest
464+ needs : [build-vsix, lint, check-types, python-tests, tests, smoke-tests]
465+ permissions :
466+ issues : write
467+ steps :
468+ - name : Create Issue on Failure
469+ uses : actions/github-script@v7
470+ with :
471+ script : |
472+ const failedJobs = [];
473+ const jobs = {
474+ 'build-vsix': '${{ needs.build-vsix.result }}',
475+ 'lint': '${{ needs.lint.result }}',
476+ 'check-types': '${{ needs.check-types.result }}',
477+ 'python-tests': '${{ needs.python-tests.result }}',
478+ 'tests': '${{ needs.tests.result }}',
479+ 'smoke-tests': '${{ needs.smoke-tests.result }}'
480+ };
481+
482+ for (const [job, result] of Object.entries(jobs)) {
483+ if (result === 'failure') {
484+ failedJobs.push(job);
485+ }
486+ }
487+
488+ const title = `CI Failure on main: ${failedJobs.join(', ')}`;
489+ const body = `## CI Failure Report
490+
491+ The following jobs failed on the main branch:
492+ ${failedJobs.map(job => `- **${job}**`).join('\n')}
493+
494+ **Workflow Run:** ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
495+ **Commit:** ${{ github.sha }}
496+ **Commit Message:** ${{ github.event.head_commit.message }}
497+ **Author:** @${{ github.event.head_commit.author.username }}
498+
499+ Please investigate and fix the failure.
500+
501+ ---
502+ *This issue was automatically created by the CI system.*`;
503+
504+ // Check if there's already an open issue for CI failures
505+ const existingIssues = await github.rest.issues.listForRepo({
506+ owner: context.repo.owner,
507+ repo: context.repo.repo,
508+ state: 'open',
509+ labels: 'ci-failure',
510+ per_page: 100
511+ });
512+
513+ // Look for recent issues (within last 24 hours) to avoid duplicates
514+ const oneDayAgo = new Date(Date.now() - 24 * 60 * 60 * 1000);
515+ const recentIssue = existingIssues.data.find(issue => {
516+ const issueDate = new Date(issue.created_at);
517+ return issueDate > oneDayAgo && issue.title.includes('CI Failure on main');
518+ });
519+
520+ if (recentIssue) {
521+ // Add a comment to the existing issue instead of creating a new one
522+ await github.rest.issues.createComment({
523+ owner: context.repo.owner,
524+ repo: context.repo.repo,
525+ issue_number: recentIssue.number,
526+ body: `## Additional CI Failure
527+
528+ Another CI failure occurred:
529+ ${failedJobs.map(job => `- **${job}**`).join('\n')}
530+
531+ **Workflow Run:** ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
532+ **Commit:** ${{ github.sha }}
533+ **Commit Message:** ${{ github.event.head_commit.message }}
534+ **Author:** @${{ github.event.head_commit.author.username }}`
535+ });
536+
537+ console.log(`Added comment to existing issue #${recentIssue.number}`);
538+ } else {
539+ // Create a new issue
540+ const issue = await github.rest.issues.create({
541+ owner: context.repo.owner,
542+ repo: context.repo.repo,
543+ title: title,
544+ body: body,
545+ labels: ['ci-failure', 'bug', 'needs-triage']
546+ });
547+
548+ console.log(`Created issue #${issue.data.number}`);
549+ }
0 commit comments