From f5d3cc2f1fe475e0a5977f10554eeb9a3e284f33 Mon Sep 17 00:00:00 2001 From: Claude Code Bot Date: Mon, 13 Jul 2026 21:47:13 -0500 Subject: [PATCH 1/5] fix(fleet-monitor): auto-close resolved fleet-tracker issues (#1203) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The monitor creates/updates a fleet-tracker issue per (repo × workflow) above 10% failure, but never closed them when the workflow recovered or was deleted — so 107 stale alerts accumulated (some with 'Last updated' stamps ~55 days old while the monitor runs daily; 4 for the deleted claude.yml #456). Add a step that closes any open fleet-tracker issue whose 'Last updated on ' stamp is older than STALE_DAYS (default 3 = 3 missed daily runs), with a ✅ Auto-resolved comment. It reopens automatically (fresh issue) if the workflow crosses the threshold again — same lifecycle as org-scorecard. Safety: gated on fleet_high_failure.json existing (a failed scan can't mass-close); staleness uses each issue's own stamp, not the current run, so a single bad-scan day never false-closes; comment + close are each guarded so a comment-capped issue still closes. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01Juznz5V6su81ffSND8fg7s --- .github/workflows/actions-fleet-monitor.yml | 64 +++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/.github/workflows/actions-fleet-monitor.yml b/.github/workflows/actions-fleet-monitor.yml index aaf16d5d6..ccd0e99f3 100644 --- a/.github/workflows/actions-fleet-monitor.yml +++ b/.github/workflows/actions-fleet-monitor.yml @@ -353,6 +353,70 @@ jobs: } + - name: Close resolved fleet-tracker issues + # The tracking step stamps "Last updated ... on " on an issue every + # run its workflow is still above threshold. A workflow that recovers (≤10%) + # or is deleted stops being updated, so its stamp goes stale — but nothing + # closed the issue, so fleet-tracker issues accumulated forever (#711-class + # bot backlog). Close any fleet-tracker issue whose stamp is older than + # STALE_DAYS daily runs. Gated on fleet_high_failure.json existing so a + # failed scan cannot mass-close; staleness (per-issue stamp, not the current + # run) means a single bad-scan day never false-closes. + if: hashFiles('fleet_high_failure.json') != '' + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + ORG: ${{ env.ORG }} + STALE_DAYS: '3' + with: + # Use GH_PAT_WORKFLOWS for cross-repo issues:write on target repos + github-token: ${{ secrets.GH_PAT_WORKFLOWS }} + script: | + const org = process.env.ORG; + const staleDays = parseInt(process.env.STALE_DAYS, 10); + const cutoffMs = staleDays * 24 * 60 * 60 * 1000; + const now = Date.now(); + + const found = await github.paginate(github.rest.search.issuesAndPullRequests, { + q: `org:${org} is:issue is:open label:fleet-tracker`, + per_page: 100, + }); + + let closed = 0, kept = 0, skipped = 0; + for (const issue of found) { + const rm = (issue.repository_url || '').match(/repos\/([^/]+)\/([^/]+)$/); + const dm = (issue.body || '').match(/updated by \[Fleet Monitor run\]\([^)]*\) on (\d{4}-\d{2}-\d{2})/); + // No repo match or no stamp → not a monitor-managed body; leave it alone. + if (!rm || !dm) { skipped++; continue; } + const [ , owner, repo ] = rm; + const ageMs = now - Date.parse(`${dm[1]}T00:00:00Z`); + if (ageMs <= cutoffMs) { kept++; continue; } // still fresh → workflow still failing + const days = Math.floor(ageMs / 86400000); + const body = [ + `✅ **Auto-resolved by Fleet Monitor.** This workflow's failure rate has`, + `been below the 10% threshold (or the workflow was removed) since ${dm[1]}`, + `(${days} days) — the monitor stopped flagging it. Closing. It will reopen`, + `automatically if the workflow crosses the threshold again.`, + ].join(' '); + try { + await github.rest.issues.createComment({ + owner, repo, issue_number: issue.number, body, + }); + } catch (err) { + core.warning(`comment failed on ${owner}/${repo}#${issue.number}: ${err.message}`); + } + try { + await github.rest.issues.update({ + owner, repo, issue_number: issue.number, + state: 'closed', state_reason: 'completed', + }); + closed++; + } catch (err) { + core.warning(`close failed on ${owner}/${repo}#${issue.number}: ${err.message}`); + } + } + core.notice(`fleet-tracker auto-close: closed=${closed} kept=${kept} skipped=${skipped} (stale>${staleDays}d)`); + + - name: Dispatch dev-lead for critical items if: env.HIGH_FAILURE_COUNT != '' && env.HIGH_FAILURE_COUNT != '0' env: From 418b4be2603670aa26b8967b401750bd319dcada Mon Sep 17 00:00:00 2001 From: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com> Date: Tue, 14 Jul 2026 02:56:14 +0000 Subject: [PATCH 2/5] fix(reviews): address review comments [skip ci-relay] --- .github/workflows/actions-fleet-monitor.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/actions-fleet-monitor.yml b/.github/workflows/actions-fleet-monitor.yml index ccd0e99f3..df7d5df67 100644 --- a/.github/workflows/actions-fleet-monitor.yml +++ b/.github/workflows/actions-fleet-monitor.yml @@ -367,9 +367,10 @@ jobs: env: ORG: ${{ env.ORG }} STALE_DAYS: '3' + GH_PAT_WORKFLOWS: ${{ secrets.GH_PAT_WORKFLOWS }} with: # Use GH_PAT_WORKFLOWS for cross-repo issues:write on target repos - github-token: ${{ secrets.GH_PAT_WORKFLOWS }} + github-token: ${{ env.GH_PAT_WORKFLOWS }} script: | const org = process.env.ORG; const staleDays = parseInt(process.env.STALE_DAYS, 10); From f6f83ebf9ff83f6647aad6e0b62e9d800fe5aa91 Mon Sep 17 00:00:00 2001 From: Claude Code Bot Date: Mon, 13 Jul 2026 22:15:39 -0500 Subject: [PATCH 3/5] fix(fleet-monitor): close prior daily digests instead of accumulating them MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 'workflow failures detected ' digest embeds the date in its title, so issues.create ran unconditionally every day — 42 open digests had piled up. Close the prior open digests (health-check label, matching title prefix) before opening today's, so only the current snapshot stays open. Complements the fleet-tracker auto-close in this PR; both stop the monitor accumulating stale issues. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01Juznz5V6su81ffSND8fg7s --- .github/workflows/actions-fleet-monitor.yml | 23 ++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/.github/workflows/actions-fleet-monitor.yml b/.github/workflows/actions-fleet-monitor.yml index df7d5df67..31db130b8 100644 --- a/.github/workflows/actions-fleet-monitor.yml +++ b/.github/workflows/actions-fleet-monitor.yml @@ -174,10 +174,31 @@ jobs: `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID})._ `; } const today = new Date().toISOString().split('T')[0]; + const titlePrefix = `${process.env.ORG} — workflow failures detected`; + + // This daily digest embeds the date in its title, so a fresh issue is + // created every run — 42 had accumulated open. Close the prior digests + // before opening today's so only the current snapshot stays open (the + // digest is a point-in-time report; history lives in closed issues). + const priors = await github.paginate(github.rest.issues.listForRepo, { + owner: context.repo.owner, repo: context.repo.repo, + state: 'open', labels: 'health-check', per_page: 100, + }); + for (const p of priors) { + if (!p.pull_request && p.title.startsWith(titlePrefix)) { + try { + await github.rest.issues.update({ + owner: context.repo.owner, repo: context.repo.repo, + issue_number: p.number, state: 'closed', state_reason: 'completed', + }); + } catch (err) { core.warning(`could not close prior digest #${p.number}: ${err.message}`); } + } + } + const issue = await github.rest.issues.create({ owner: context.repo.owner, repo: context.repo.repo, - title: `${process.env.ORG} — workflow failures detected ${today}`, + title: `${titlePrefix} ${today}`, body: report, labels: ['health-check', 'automated-report'], }); From e21f69ad3dbaf3c695005d04f97b773c49ed251d Mon Sep 17 00:00:00 2001 From: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com> Date: Tue, 14 Jul 2026 03:24:25 +0000 Subject: [PATCH 4/5] chore: dev-lead update (review-changes) [skip ci-relay] --- .github/workflows/actions-fleet-monitor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/actions-fleet-monitor.yml b/.github/workflows/actions-fleet-monitor.yml index 31db130b8..12cf448c9 100644 --- a/.github/workflows/actions-fleet-monitor.yml +++ b/.github/workflows/actions-fleet-monitor.yml @@ -401,7 +401,7 @@ jobs: const found = await github.paginate(github.rest.search.issuesAndPullRequests, { q: `org:${org} is:issue is:open label:fleet-tracker`, per_page: 100, - }); + }, response => response.data.items); let closed = 0, kept = 0, skipped = 0; for (const issue of found) { From 53e7237527ae18d973376df8a037b3c27b5d8382 Mon Sep 17 00:00:00 2001 From: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com> Date: Tue, 14 Jul 2026 04:37:53 +0000 Subject: [PATCH 5/5] fix(bot): address bot feedback [skip ci-relay] --- .github/workflows/actions-fleet-monitor.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/actions-fleet-monitor.yml b/.github/workflows/actions-fleet-monitor.yml index 12cf448c9..bf77e5b32 100644 --- a/.github/workflows/actions-fleet-monitor.yml +++ b/.github/workflows/actions-fleet-monitor.yml @@ -207,8 +207,10 @@ jobs: - name: Migrate misaligned fleet-tracker issues uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_PAT_WORKFLOWS: ${{ secrets.GH_PAT_WORKFLOWS }} with: - github-token: ${{ secrets.GH_PAT_WORKFLOWS }} + github-token: ${{ env.GH_PAT_WORKFLOWS }} script: | // Find open fleet-tracker issues in .github-private that belong to other repos const allIssues = await github.paginate(github.rest.issues.listForRepo, { @@ -266,9 +268,10 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: ORG: ${{ env.ORG }} + GH_PAT_WORKFLOWS: ${{ secrets.GH_PAT_WORKFLOWS }} with: # Use GH_PAT_WORKFLOWS for cross-repo issues:write on target repos - github-token: ${{ secrets.GH_PAT_WORKFLOWS }} + github-token: ${{ env.GH_PAT_WORKFLOWS }} script: | const fs = require('fs');