From 39070c4f905d829c6c446d25af50f947837f617d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Jul 2026 18:31:08 +0000 Subject: [PATCH 01/17] chore: add workflow failure issue reporting Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com> --- .../workflows/report-workflow-failures.yml | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 .github/workflows/report-workflow-failures.yml diff --git a/.github/workflows/report-workflow-failures.yml b/.github/workflows/report-workflow-failures.yml new file mode 100644 index 00000000000..62e13f905d1 --- /dev/null +++ b/.github/workflows/report-workflow-failures.yml @@ -0,0 +1,62 @@ +name: Report workflow failures + +on: + workflow_run: + workflows: + - Codespaces Prebuilds + types: + - completed + +permissions: {} + +jobs: + create-issue: + if: ${{ github.event.workflow_run.conclusion == 'failure' }} + runs-on: ubuntu-latest + permissions: + actions: read + issues: write + steps: + - name: Create issue + uses: actions/github-script@5c56fde4671bc2d3592fb0f2c5b5bab9ddae03b1 + with: + script: | + const workflowRun = context.payload.workflow_run; + const workflow = await github.rest.actions.getWorkflow({ + owner: context.repo.owner, + repo: context.repo.repo, + workflow_id: workflowRun.workflow_id, + }); + const jobs = await github.paginate( + github.rest.actions.listJobsForWorkflowRun, + { + owner: context.repo.owner, + repo: context.repo.repo, + run_id: workflowRun.id, + filter: 'latest', + per_page: 100, + }, + ); + const failedJobs = jobs.filter((job) => job.conclusion === 'failure'); + const failedWorkflows = failedJobs.map( + (job) => `- [${workflow.data.name}: ${job.name}](${job.html_url})`, + ); + + if (failedWorkflows.length === 0) { + failedWorkflows.push( + `- [${workflow.data.name}](${workflowRun.html_url})`, + ); + } + + const body = [ + ...failedWorkflows, + '', + '@github/primer-engineering, please investigate and fix.', + ].join('\n'); + + await github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: 'Investigate GitHub workflow failure', + body, + }); From a0b0f88d4c06e962e718c5f08f13f02cafa3e570 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Jul 2026 18:34:42 +0000 Subject: [PATCH 02/17] chore: refine workflow failure issue details Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com> --- .github/workflows/report-workflow-failures.yml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/.github/workflows/report-workflow-failures.yml b/.github/workflows/report-workflow-failures.yml index 62e13f905d1..03386557691 100644 --- a/.github/workflows/report-workflow-failures.yml +++ b/.github/workflows/report-workflow-failures.yml @@ -18,7 +18,7 @@ jobs: issues: write steps: - name: Create issue - uses: actions/github-script@5c56fde4671bc2d3592fb0f2c5b5bab9ddae03b1 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | const workflowRun = context.payload.workflow_run; @@ -38,18 +38,16 @@ jobs: }, ); const failedJobs = jobs.filter((job) => job.conclusion === 'failure'); - const failedWorkflows = failedJobs.map( - (job) => `- [${workflow.data.name}: ${job.name}](${job.html_url})`, + const failedJobLinks = failedJobs.map( + (job) => `[${job.name}](${job.html_url})`, ); - if (failedWorkflows.length === 0) { - failedWorkflows.push( - `- [${workflow.data.name}](${workflowRun.html_url})`, - ); + if (failedJobLinks.length === 0) { + failedJobLinks.push(`[Failed run](${workflowRun.html_url})`); } const body = [ - ...failedWorkflows, + `- ${workflow.data.name}: ${failedJobLinks.join(', ')}`, '', '@github/primer-engineering, please investigate and fix.', ].join('\n'); From 28cc6ee374e2a41e1061b61ff9a0f7c44dca8f09 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Jul 2026 18:48:00 +0000 Subject: [PATCH 03/17] chore: manage workflow failure issue lifecycle Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com> --- .../workflows/report-workflow-failures.yml | 68 +++++++++++++++++-- 1 file changed, 62 insertions(+), 6 deletions(-) diff --git a/.github/workflows/report-workflow-failures.yml b/.github/workflows/report-workflow-failures.yml index 03386557691..8f041b26d64 100644 --- a/.github/workflows/report-workflow-failures.yml +++ b/.github/workflows/report-workflow-failures.yml @@ -9,24 +9,71 @@ on: permissions: {} +concurrency: + group: ${{ github.workflow }}-${{ github.event.workflow_run.workflow_id }} + jobs: - create-issue: - if: ${{ github.event.workflow_run.conclusion == 'failure' }} + update-issue: + if: ${{ contains(fromJSON('["failure", "success"]'), github.event.workflow_run.conclusion) }} runs-on: ubuntu-latest permissions: actions: read issues: write steps: - - name: Create issue + - name: Update issue uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | const workflowRun = context.payload.workflow_run; + const latestRuns = await github.rest.actions.listWorkflowRuns({ + owner: context.repo.owner, + repo: context.repo.repo, + workflow_id: workflowRun.workflow_id, + status: 'completed', + per_page: 1, + }); + const latestRun = latestRuns.data.workflow_runs[0]; + + if ( + !latestRun || + latestRun.id !== workflowRun.id || + latestRun.run_attempt !== workflowRun.run_attempt + ) { + return; + } + const workflow = await github.rest.actions.getWorkflow({ owner: context.repo.owner, repo: context.repo.repo, workflow_id: workflowRun.workflow_id, }); + const title = `Investigate ${workflow.data.name} workflow failure`; + const issues = await github.paginate( + github.rest.issues.listForRepo, + { + owner: context.repo.owner, + repo: context.repo.repo, + state: 'open', + per_page: 100, + }, + ); + const failureIssues = issues.filter( + (issue) => !issue.pull_request && issue.title === title, + ); + + if (workflowRun.conclusion === 'success') { + for (const issue of failureIssues) { + await github.rest.issues.update({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue.number, + state: 'closed', + state_reason: 'completed', + }); + } + return; + } + const jobs = await github.paginate( github.rest.actions.listJobsForWorkflowRun, { @@ -52,9 +99,18 @@ jobs: '@github/primer-engineering, please investigate and fix.', ].join('\n'); - await github.rest.issues.create({ + const issue = { owner: context.repo.owner, repo: context.repo.repo, - title: 'Investigate GitHub workflow failure', + title, body, - }); + }; + + if (failureIssues.length > 0) { + await github.rest.issues.update({ + ...issue, + issue_number: failureIssues[0].number, + }); + } else { + await github.rest.issues.create(issue); + } From 43f306d76d114ce838598742014d559d5b430426 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Jul 2026 18:51:07 +0000 Subject: [PATCH 04/17] chore: harden workflow issue deduplication Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com> --- .../workflows/report-workflow-failures.yml | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/.github/workflows/report-workflow-failures.yml b/.github/workflows/report-workflow-failures.yml index 8f041b26d64..9bdb1466ebe 100644 --- a/.github/workflows/report-workflow-failures.yml +++ b/.github/workflows/report-workflow-failures.yml @@ -34,8 +34,12 @@ jobs: }); const latestRun = latestRuns.data.workflow_runs[0]; + if (!latestRun) { + core.warning('No completed workflow run found'); + return; + } + if ( - !latestRun || latestRun.id !== workflowRun.id || latestRun.run_attempt !== workflowRun.run_attempt ) { @@ -48,6 +52,7 @@ jobs: workflow_id: workflowRun.workflow_id, }); const title = `Investigate ${workflow.data.name} workflow failure`; + const issueMarker = ``; const issues = await github.paginate( github.rest.issues.listForRepo, { @@ -58,7 +63,8 @@ jobs: }, ); const failureIssues = issues.filter( - (issue) => !issue.pull_request && issue.title === title, + (issue) => + !issue.pull_request && issue.body?.includes(issueMarker), ); if (workflowRun.conclusion === 'success') { @@ -94,6 +100,8 @@ jobs: } const body = [ + issueMarker, + '', `- ${workflow.data.name}: ${failedJobLinks.join(', ')}`, '', '@github/primer-engineering, please investigate and fix.', @@ -111,6 +119,15 @@ jobs: ...issue, issue_number: failureIssues[0].number, }); + for (const duplicate of failureIssues.slice(1)) { + await github.rest.issues.update({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: duplicate.number, + state: 'closed', + state_reason: 'not_planned', + }); + } } else { await github.rest.issues.create(issue); } From 18a9a13109f33487e0c10c1938bfbf8205567c30 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Jul 2026 18:54:19 +0000 Subject: [PATCH 05/17] chore: finalize workflow issue lifecycle Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com> --- .../workflows/report-workflow-failures.yml | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/.github/workflows/report-workflow-failures.yml b/.github/workflows/report-workflow-failures.yml index 9bdb1466ebe..f527e49811a 100644 --- a/.github/workflows/report-workflow-failures.yml +++ b/.github/workflows/report-workflow-failures.yml @@ -34,11 +34,6 @@ jobs: }); const latestRun = latestRuns.data.workflow_runs[0]; - if (!latestRun) { - core.warning('No completed workflow run found'); - return; - } - if ( latestRun.id !== workflowRun.id || latestRun.run_attempt !== workflowRun.run_attempt @@ -119,15 +114,17 @@ jobs: ...issue, issue_number: failureIssues[0].number, }); - for (const duplicate of failureIssues.slice(1)) { - await github.rest.issues.update({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: duplicate.number, - state: 'closed', - state_reason: 'not_planned', - }); - } + await Promise.all( + failureIssues.slice(1).map((duplicate) => + github.rest.issues.update({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: duplicate.number, + state: 'closed', + state_reason: 'not_planned', + }), + ), + ); } else { await github.rest.issues.create(issue); } From 232677f070abea167e83b00dffabb11c7b517cb1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Jul 2026 18:57:21 +0000 Subject: [PATCH 06/17] chore: guard workflow run lookup Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com> --- .github/workflows/report-workflow-failures.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/report-workflow-failures.yml b/.github/workflows/report-workflow-failures.yml index f527e49811a..8d7b551cf5d 100644 --- a/.github/workflows/report-workflow-failures.yml +++ b/.github/workflows/report-workflow-failures.yml @@ -35,8 +35,8 @@ jobs: const latestRun = latestRuns.data.workflow_runs[0]; if ( - latestRun.id !== workflowRun.id || - latestRun.run_attempt !== workflowRun.run_attempt + latestRun?.id !== workflowRun.id || + latestRun?.run_attempt !== workflowRun.run_attempt ) { return; } From 44672e39974d73c9639875148f8ae0623bc456b8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Jul 2026 19:00:25 +0000 Subject: [PATCH 07/17] chore: preserve canonical workflow issue Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com> --- .github/workflows/report-workflow-failures.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/report-workflow-failures.yml b/.github/workflows/report-workflow-failures.yml index 8d7b551cf5d..5296042c49d 100644 --- a/.github/workflows/report-workflow-failures.yml +++ b/.github/workflows/report-workflow-failures.yml @@ -57,10 +57,12 @@ jobs: per_page: 100, }, ); - const failureIssues = issues.filter( - (issue) => - !issue.pull_request && issue.body?.includes(issueMarker), - ); + const failureIssues = issues + .filter( + (issue) => + !issue.pull_request && issue.body?.includes(issueMarker), + ) + .sort((a, b) => a.number - b.number); if (workflowRun.conclusion === 'success') { for (const issue of failureIssues) { From 3dd27f184b6bf92db699325847da67adb225c500 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Jul 2026 19:14:45 +0000 Subject: [PATCH 08/17] chore: split workflow issue lifecycle jobs Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com> --- .../workflows/report-workflow-failures.yml | 72 ++++++++++++++----- 1 file changed, 56 insertions(+), 16 deletions(-) diff --git a/.github/workflows/report-workflow-failures.yml b/.github/workflows/report-workflow-failures.yml index 5296042c49d..307e9c5cd3a 100644 --- a/.github/workflows/report-workflow-failures.yml +++ b/.github/workflows/report-workflow-failures.yml @@ -13,14 +13,14 @@ concurrency: group: ${{ github.workflow }}-${{ github.event.workflow_run.workflow_id }} jobs: - update-issue: - if: ${{ contains(fromJSON('["failure", "success"]'), github.event.workflow_run.conclusion) }} + create-or-update-issue: + if: ${{ github.event.workflow_run.conclusion == 'failure' }} runs-on: ubuntu-latest permissions: actions: read issues: write steps: - - name: Update issue + - name: Create or update issue uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | @@ -64,19 +64,6 @@ jobs: ) .sort((a, b) => a.number - b.number); - if (workflowRun.conclusion === 'success') { - for (const issue of failureIssues) { - await github.rest.issues.update({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issue.number, - state: 'closed', - state_reason: 'completed', - }); - } - return; - } - const jobs = await github.paginate( github.rest.actions.listJobsForWorkflowRun, { @@ -130,3 +117,56 @@ jobs: } else { await github.rest.issues.create(issue); } + + close-issue: + if: ${{ github.event.workflow_run.conclusion == 'success' }} + runs-on: ubuntu-latest + permissions: + actions: read + issues: write + steps: + - name: Close issue + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const workflowRun = context.payload.workflow_run; + const latestRuns = await github.rest.actions.listWorkflowRuns({ + owner: context.repo.owner, + repo: context.repo.repo, + workflow_id: workflowRun.workflow_id, + status: 'completed', + per_page: 1, + }); + const latestRun = latestRuns.data.workflow_runs[0]; + + if ( + latestRun?.id !== workflowRun.id || + latestRun?.run_attempt !== workflowRun.run_attempt + ) { + return; + } + + const issueMarker = ``; + const issues = await github.paginate( + github.rest.issues.listForRepo, + { + owner: context.repo.owner, + repo: context.repo.repo, + state: 'open', + per_page: 100, + }, + ); + const failureIssues = issues.filter( + (issue) => + !issue.pull_request && issue.body?.includes(issueMarker), + ); + + for (const issue of failureIssues) { + await github.rest.issues.update({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue.number, + state: 'closed', + state_reason: 'completed', + }); + } From 6b9c990df4cdadb6ac36441c34444c0b0bde6634 Mon Sep 17 00:00:00 2001 From: Josh Black Date: Fri, 17 Jul 2026 14:23:57 -0500 Subject: [PATCH 09/17] Update failure notification message in workflow --- .github/workflows/report-workflow-failures.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/report-workflow-failures.yml b/.github/workflows/report-workflow-failures.yml index 307e9c5cd3a..cb1dbae90a5 100644 --- a/.github/workflows/report-workflow-failures.yml +++ b/.github/workflows/report-workflow-failures.yml @@ -85,10 +85,11 @@ jobs: const body = [ issueMarker, + 'The following jobs are failing in this workflow:' '', - `- ${workflow.data.name}: ${failedJobLinks.join(', ')}`, + ...failedJobLinks.map((link) => `- ${link}`).join('\n') '', - '@github/primer-engineering, please investigate and fix.', + 'cc @github/primer-engineering to investigate and fix', ].join('\n'); const issue = { From 7b2353abbc28e38720316225f7c09e8d3b05d004 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Jul 2026 19:36:55 +0000 Subject: [PATCH 10/17] chore: harden workflow failure issue handling Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com> --- .../workflows/report-workflow-failures.yml | 70 ++++++++++++------- 1 file changed, 45 insertions(+), 25 deletions(-) diff --git a/.github/workflows/report-workflow-failures.yml b/.github/workflows/report-workflow-failures.yml index cb1dbae90a5..0ace790c682 100644 --- a/.github/workflows/report-workflow-failures.yml +++ b/.github/workflows/report-workflow-failures.yml @@ -47,16 +47,18 @@ jobs: workflow_id: workflowRun.workflow_id, }); const title = `Investigate ${workflow.data.name} workflow failure`; - const issueMarker = ``; - const issues = await github.paginate( - github.rest.issues.listForRepo, - { - owner: context.repo.owner, - repo: context.repo.repo, - state: 'open', - per_page: 100, - }, - ); + const issueMarkerText = `workflow-failure:${workflowRun.workflow_id}`; + const issueMarker = ``; + const issues = await github.paginate(github.rest.search.issuesAndPullRequests, { + q: [ + `repo:${context.repo.owner}/${context.repo.repo}`, + 'is:issue', + 'is:open', + `"${issueMarkerText}"`, + 'in:body', + ].join(' '), + per_page: 100, + }); const failureIssues = issues .filter( (issue) => @@ -75,8 +77,10 @@ jobs: }, ); const failedJobs = jobs.filter((job) => job.conclusion === 'failure'); + const escapeMarkdownLinkText = (text) => text.replace(/[\\[\]]/g, '\\$&'); const failedJobLinks = failedJobs.map( - (job) => `[${job.name}](${job.html_url})`, + (job) => + `[${escapeMarkdownLinkText(job.name)}](${job.html_url})`, ); if (failedJobLinks.length === 0) { @@ -85,9 +89,9 @@ jobs: const body = [ issueMarker, - 'The following jobs are failing in this workflow:' + 'The following jobs are failing in this workflow:', '', - ...failedJobLinks.map((link) => `- ${link}`).join('\n') + ...failedJobLinks.map((link) => `- ${link}`), '', 'cc @github/primer-engineering to investigate and fix', ].join('\n'); @@ -99,11 +103,14 @@ jobs: body, }; + let issueNumber; + if (failureIssues.length > 0) { await github.rest.issues.update({ ...issue, issue_number: failureIssues[0].number, }); + issueNumber = failureIssues[0].number; await Promise.all( failureIssues.slice(1).map((duplicate) => github.rest.issues.update({ @@ -116,7 +123,19 @@ jobs: ), ); } else { - await github.rest.issues.create(issue); + const createdIssue = await github.rest.issues.create(issue); + issueNumber = createdIssue.data.number; + } + + try { + await github.rest.issues.addAssignees({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + assignees: ['copilot'], + }); + } catch (error) { + core.warning(`Unable to assign Copilot: ${error.message}`); } close-issue: @@ -135,7 +154,6 @@ jobs: owner: context.repo.owner, repo: context.repo.repo, workflow_id: workflowRun.workflow_id, - status: 'completed', per_page: 1, }); const latestRun = latestRuns.data.workflow_runs[0]; @@ -147,16 +165,18 @@ jobs: return; } - const issueMarker = ``; - const issues = await github.paginate( - github.rest.issues.listForRepo, - { - owner: context.repo.owner, - repo: context.repo.repo, - state: 'open', - per_page: 100, - }, - ); + const issueMarkerText = `workflow-failure:${workflowRun.workflow_id}`; + const issueMarker = ``; + const issues = await github.paginate(github.rest.search.issuesAndPullRequests, { + q: [ + `repo:${context.repo.owner}/${context.repo.repo}`, + 'is:issue', + 'is:open', + `"${issueMarkerText}"`, + 'in:body', + ].join(' '), + per_page: 100, + }); const failureIssues = issues.filter( (issue) => !issue.pull_request && issue.body?.includes(issueMarker), From 7f254ad64a78b4a245166f1ae77074d344aba9bc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Jul 2026 19:40:16 +0000 Subject: [PATCH 11/17] chore: address workflow review feedback Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com> --- .github/workflows/report-workflow-failures.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/report-workflow-failures.yml b/.github/workflows/report-workflow-failures.yml index 0ace790c682..7e84b894394 100644 --- a/.github/workflows/report-workflow-failures.yml +++ b/.github/workflows/report-workflow-failures.yml @@ -77,21 +77,23 @@ jobs: }, ); const failedJobs = jobs.filter((job) => job.conclusion === 'failure'); - const escapeMarkdownLinkText = (text) => text.replace(/[\\[\]]/g, '\\$&'); + const escapeMarkdownLinkTextBrackets = (text) => + text.replace(/[\\[\]]/g, '\\$&'); const failedJobLinks = failedJobs.map( (job) => - `[${escapeMarkdownLinkText(job.name)}](${job.html_url})`, + `[${escapeMarkdownLinkTextBrackets(job.name)}](${job.html_url})`, ); if (failedJobLinks.length === 0) { failedJobLinks.push(`[Failed run](${workflowRun.html_url})`); } + const failedJobListItems = failedJobLinks.map((link) => `- ${link}`); const body = [ issueMarker, 'The following jobs are failing in this workflow:', '', - ...failedJobLinks.map((link) => `- ${link}`), + ...failedJobListItems, '', 'cc @github/primer-engineering to investigate and fix', ].join('\n'); @@ -135,7 +137,7 @@ jobs: assignees: ['copilot'], }); } catch (error) { - core.warning(`Unable to assign Copilot: ${error.message}`); + core.warning(`Unable to assign Copilot: ${error?.message ?? String(error)}`); } close-issue: From 6398df3feba8ae15dcb6a04630ffd2bc484946aa Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Jul 2026 19:43:25 +0000 Subject: [PATCH 12/17] chore: polish workflow failure issue script Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com> --- .github/workflows/report-workflow-failures.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/report-workflow-failures.yml b/.github/workflows/report-workflow-failures.yml index 7e84b894394..98862067588 100644 --- a/.github/workflows/report-workflow-failures.yml +++ b/.github/workflows/report-workflow-failures.yml @@ -77,23 +77,23 @@ jobs: }, ); const failedJobs = jobs.filter((job) => job.conclusion === 'failure'); - const escapeMarkdownLinkTextBrackets = (text) => + const escapeMarkdownBrackets = (text) => text.replace(/[\\[\]]/g, '\\$&'); const failedJobLinks = failedJobs.map( (job) => - `[${escapeMarkdownLinkTextBrackets(job.name)}](${job.html_url})`, + `[${escapeMarkdownBrackets(job.name)}](${job.html_url})`, ); if (failedJobLinks.length === 0) { failedJobLinks.push(`[Failed run](${workflowRun.html_url})`); } - const failedJobListItems = failedJobLinks.map((link) => `- ${link}`); + const failedJobList = failedJobLinks.map((link) => `- ${link}`).join('\n'); const body = [ issueMarker, 'The following jobs are failing in this workflow:', '', - ...failedJobListItems, + failedJobList, '', 'cc @github/primer-engineering to investigate and fix', ].join('\n'); From dad1c76c6bb438835c845d885d79552bd804a996 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Jul 2026 19:46:37 +0000 Subject: [PATCH 13/17] chore: clarify workflow issue warnings Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com> --- .github/workflows/report-workflow-failures.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/report-workflow-failures.yml b/.github/workflows/report-workflow-failures.yml index 98862067588..e8cc6192dfc 100644 --- a/.github/workflows/report-workflow-failures.yml +++ b/.github/workflows/report-workflow-failures.yml @@ -77,11 +77,11 @@ jobs: }, ); const failedJobs = jobs.filter((job) => job.conclusion === 'failure'); - const escapeMarkdownBrackets = (text) => + const escapeMarkdownSpecialChars = (text) => text.replace(/[\\[\]]/g, '\\$&'); const failedJobLinks = failedJobs.map( (job) => - `[${escapeMarkdownBrackets(job.name)}](${job.html_url})`, + `[${escapeMarkdownSpecialChars(job.name)}](${job.html_url})`, ); if (failedJobLinks.length === 0) { @@ -137,7 +137,9 @@ jobs: assignees: ['copilot'], }); } catch (error) { - core.warning(`Unable to assign Copilot: ${error?.message ?? String(error)}`); + core.warning( + `Unable to assign Copilot to issue #${issueNumber}: ${error?.message ?? String(error)}`, + ); } close-issue: From bb64f3e42725f089d16d455258c8846777c09e56 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Jul 2026 19:49:38 +0000 Subject: [PATCH 14/17] chore: finalize workflow issue automation Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com> --- .github/workflows/report-workflow-failures.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/report-workflow-failures.yml b/.github/workflows/report-workflow-failures.yml index e8cc6192dfc..706a5b114f7 100644 --- a/.github/workflows/report-workflow-failures.yml +++ b/.github/workflows/report-workflow-failures.yml @@ -77,11 +77,9 @@ jobs: }, ); const failedJobs = jobs.filter((job) => job.conclusion === 'failure'); - const escapeMarkdownSpecialChars = (text) => - text.replace(/[\\[\]]/g, '\\$&'); const failedJobLinks = failedJobs.map( (job) => - `[${escapeMarkdownSpecialChars(job.name)}](${job.html_url})`, + `[${job.name.replace(/[\\[\]]/g, '\\$&')}](${job.html_url})`, ); if (failedJobLinks.length === 0) { @@ -138,7 +136,7 @@ jobs: }); } catch (error) { core.warning( - `Unable to assign Copilot to issue #${issueNumber}: ${error?.message ?? String(error)}`, + `Unable to assign Copilot to issue #${issueNumber}. This may be expected if Copilot issue assignment is unavailable for the repository: ${error?.message ?? String(error)}`, ); } From d69e98e33d44fe78de27e43542b79d298231177a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Jul 2026 19:52:42 +0000 Subject: [PATCH 15/17] chore: harden workflow failure issue formatting Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com> --- .github/workflows/report-workflow-failures.yml | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/.github/workflows/report-workflow-failures.yml b/.github/workflows/report-workflow-failures.yml index 706a5b114f7..84c6325aa3b 100644 --- a/.github/workflows/report-workflow-failures.yml +++ b/.github/workflows/report-workflow-failures.yml @@ -77,21 +77,26 @@ jobs: }, ); const failedJobs = jobs.filter((job) => job.conclusion === 'failure'); - const failedJobLinks = failedJobs.map( + const escapeHtml = (text) => + text + .replaceAll('&', '&') + .replaceAll('<', '<') + .replaceAll('>', '>') + .replaceAll('"', '"'); + const failedJobListItems = failedJobs.map( (job) => - `[${job.name.replace(/[\\[\]]/g, '\\$&')}](${job.html_url})`, + `- ${escapeHtml(job.name)}`, ); - if (failedJobLinks.length === 0) { - failedJobLinks.push(`[Failed run](${workflowRun.html_url})`); + if (failedJobListItems.length === 0) { + failedJobListItems.push(`- Failed run`); } - const failedJobList = failedJobLinks.map((link) => `- ${link}`).join('\n'); const body = [ issueMarker, 'The following jobs are failing in this workflow:', '', - failedJobList, + ...failedJobListItems, '', 'cc @github/primer-engineering to investigate and fix', ].join('\n'); From f8490ca06a649e9e8f57e6be8b804f52b8cc6355 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Jul 2026 19:55:43 +0000 Subject: [PATCH 16/17] chore: finalize workflow issue escaping Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com> --- .github/workflows/report-workflow-failures.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/report-workflow-failures.yml b/.github/workflows/report-workflow-failures.yml index 84c6325aa3b..5c848d7e7a2 100644 --- a/.github/workflows/report-workflow-failures.yml +++ b/.github/workflows/report-workflow-failures.yml @@ -82,7 +82,8 @@ jobs: .replaceAll('&', '&') .replaceAll('<', '<') .replaceAll('>', '>') - .replaceAll('"', '"'); + .replaceAll('"', '"') + .replaceAll("'", '''); const failedJobListItems = failedJobs.map( (job) => `- ${escapeHtml(job.name)}`, @@ -141,7 +142,7 @@ jobs: }); } catch (error) { core.warning( - `Unable to assign Copilot to issue #${issueNumber}. This may be expected if Copilot issue assignment is unavailable for the repository: ${error?.message ?? String(error)}`, + `Failed to assign @copilot to issue #${issueNumber}. This is expected if Copilot assignment is not enabled for this repository. Error: ${error?.message ?? String(error)}`, ); } From 8fa314dcabf317da5d5cb5ff18f4d347c9f8ae69 Mon Sep 17 00:00:00 2001 From: Josh Black Date: Mon, 20 Jul 2026 10:54:18 -0500 Subject: [PATCH 17/17] Apply suggestion from @jonrohan Co-authored-by: Jon Rohan --- .github/workflows/report-workflow-failures.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/report-workflow-failures.yml b/.github/workflows/report-workflow-failures.yml index 5c848d7e7a2..8c367668552 100644 --- a/.github/workflows/report-workflow-failures.yml +++ b/.github/workflows/report-workflow-failures.yml @@ -162,6 +162,7 @@ jobs: owner: context.repo.owner, repo: context.repo.repo, workflow_id: workflowRun.workflow_id, + status: 'completed', per_page: 1, }); const latestRun = latestRuns.data.workflow_runs[0];