Improving stale issue workflow (#45767)

Refactor stale issue formatting to use HTML lists for improved rendering
in GitHub Actions summary; update workflow dependencies to latest
versions.

Example run (see summary):
https://github.com/fleetdm/fleet/actions/runs/26101161627

<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #45700 


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
* Updated GitHub Actions and automation dependencies to latest versions
  * Improved stale issue management workflow formatting and logic

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45767?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Victor Lyuboslavsky
2026-05-20 16:19:39 -05:00
committed by GitHub
parent bc72cc105b
commit ed5f0c135f
3 changed files with 26 additions and 35 deletions
+19 -28
View File
@@ -314,23 +314,17 @@ async function run({ github, context, core }) {
}
}
const fmt = (list) =>
list.length
? list
.map(
(e) =>
`- [#${e.number}](${e.url}) by @${
e.author
} (idle ${e.idleDays.toFixed(1)}d)`
)
.join("\n")
: "_none_";
const fmtErrors = (list) =>
list.length
? list.map((e) => `- #${e.number} (${e.phase}): ${e.message}`).join("\n")
: "_none_";
// Each entry is an HTML <li> so it renders correctly inside <ul>. We use raw <a> tags rather
// than markdown links because GitHub Actions summary surrounds list content with HTML blocks
// (from addHeading / addList), which suspends markdown parsing for child content — markdown
// bullets via addRaw collapse onto one line in that context.
const fmtItem = (e) =>
`<a href="${e.url}">#${e.number}</a> by @${e.author} (idle ${e.idleDays.toFixed(1)}d)`;
const fmtErrorItem = (e) => `#${e.number} (${e.phase}): ${e.message}`;
const appendList = (s, items, fn) =>
items.length ? s.addList(items.map(fn)) : s.addRaw("_none_").addEOL();
await core.summary
let summary = core.summary
.addHeading("Fleetie stale-issue closer")
.addRaw(`Mode: **${dryRun ? "dry-run" : "live"}**`)
.addBreak()
@@ -347,18 +341,15 @@ async function run({ github, context, core }) {
`Un-staled this run (activity after label): ${unstaled.length}`,
`Errors: ${errored.length}`,
])
.addHeading("Marked stale", 3)
.addRaw(fmt(staled))
.addBreak()
.addHeading("Closed", 3)
.addRaw(fmt(closed))
.addBreak()
.addHeading("Un-staled (activity after label)", 3)
.addRaw(fmt(unstaled))
.addBreak()
.addHeading("Errors", 3)
.addRaw(fmtErrors(errored))
.write();
.addHeading("Marked stale", 3);
summary = appendList(summary, staled, fmtItem);
summary = summary.addHeading("Closed", 3);
summary = appendList(summary, closed, fmtItem);
summary = summary.addHeading("Un-staled (activity after label)", 3);
summary = appendList(summary, unstaled, fmtItem);
summary = summary.addHeading("Errors", 3);
summary = appendList(summary, errored, fmtErrorItem);
await summary.write();
// Returned for test assertions only. The production caller (the workflow) discards this and
// reads `core.summary` instead.