Close Stale Issues Bot
Weekly scans issues with label 'waiting-for-response' and no activity >90 days; posts a courtesy comment and calls Update An Issue to close each so the backlog reflects reality, not abandonment.
Provided as-is, without warranty of any kind. Review and test each pattern in a non-production environment before deploying it to live automations. See our Terms.
Overview
FlowLibs - Close Stale Issues Bot runs on a weekly recurrence and prunes the backlog in a single GitHub repository. Every Monday morning it pulls all open issues carrying a configurable "waiting-for-response" label, then for each issue whose updated_at is older than a configurable day threshold it posts a courtesy comment via the GitHub REST API and closes the issue with state_reason = not_planned. The result: your triage queue stops drifting, issues awaiting info get a gentle nudge-and-close instead of lingering forever, and the label drives everything — no code changes to tune behavior.
## When To Use Use this flow when you have a single GitHub repository where issues frequently stall waiting for additional information from the reporter. The label-driven model means you (or your team) simply tag an issue waiting-for-response, and from that moment on the flow controls its lifecycle. Drop the label, and the flow will ignore it. Pair this with an issue-template rule ("requires reproduction steps") and the stale-issue workflow becomes fully self-service.
Use Case
Use this flow when you have a single GitHub repository where issues frequently stall waiting for additional information from the reporter. The label-driven model means you (or your team) simply tag an issue waiting-for-response, and from that moment on the flow controls its lifecycle. Drop the label, and the flow will ignore it. Pair this with an issue-template rule ("requires reproduction steps") and the stale-issue workflow becomes fully self-service.
Flow Architecture
Weekly Stale Issue Sweep
RecurrenceFires every Monday at 09:00 Eastern to begin the weekly scan.
Init varGitHubOwner / varGitHubRepository / varGitHubPAT / varStaleIssueLabel / varStaleIssueDaysThreshold / varStaleIssueClosingComment
Initialize variableSix env-var reads that isolate all tenant-specific values (repo owner, repo name, PAT, label, day threshold, closing comment body) from the flow logic.
Init varStaleCutoffUtc
Initialize variableComputed UTC cutoff using addDays(utcNow(), -threshold). String-to-int conversion is handled inline so the threshold env var can stay a string.
Get Open Stale Labeled Issues
GitHub — ListIssuesAssignedToAuthenticatedUser (scoped to repo)Returns up to 100 open issues with the stale label, sorted oldest-updated first.
For Each Open Issue
Apply to eachFor each open issue returned: checks staleness, and if stale, posts a courtesy comment then closes it. Concurrency is set to 1 to respect GitHub rate limits.
If Issue Is Stale
If conditionEvaluates less(item()?['updated_at'], varStaleCutoffUtc) to decide whether the issue has crossed the inactivity threshold.
- Post Courtesy Comment Via GitHub API — Built-in HTTP action with PAT auth — used because the GitHub connector exposes no `create issue comment` op.
- Close Stale Issue — GitHub — UpdateIssueNum with state: closed, state_reason: not_planned.
Environment Variables
| Schema name | Type | Default | Description |
|---|---|---|---|
| flowlibs_GitHubOwner | String | <configure> | Repository owner (user or org login) the bot scans. |
| flowlibs_GitHubRepository | String | <configure> | Repository name (without owner) the bot scans. |
| flowlibs_GitHubPAT | Secret String | <configure> | Personal Access Token used by the built-in HTTP action to post issue comments (fine-grained PAT scheme uses `token` auth, not Bearer). |
| flowlibs_StaleIssueLabel | String | waiting-for-response | Label that marks issues as stale-track candidates. Drop the label to opt an issue out. |
| flowlibs_StaleIssueDaysThreshold | String | 90 | Days of inactivity (updated_at older than this many days) before the bot auto-closes. Stored as string; converted to int inline. |
| flowlibs_StaleIssueClosingComment | String | <configure> | Comment body posted on the issue immediately before closing. Customize to match your team's tone. |
Connectors & Connections
| Connector | API name | Actions used |
|---|---|---|
| GitHub | shared_github | ListIssuesAssignedToAuthenticatedUser (scoped to repo — lists open labeled issues) UpdateIssueNum (closes issue with state_reason: not_planned) |
| HTTP (built-in) | http | HTTP POST (POST issue comment — GitHub connector has no native create-comment op; uses Bearer PAT from flowlibs_GitHubPAT) |
Note — All connections are referenced as solution connection references; the flow is portable between environments as long as a connection is mapped at import time.
Customization Guide
Almost every realistic variant of this flow can be implemented by changing environment variable values. A few cases require small edits inside the flow definition — those are called out explicitly below.
- Tune inactivity window via env var
- Update flowlibs_StaleIssueDaysThreshold to change how long an issue can sit before being closed — no flow edit required.
- Track a different label taxonomy
- Update flowlibs_StaleIssueLabel to point at a different label (e.g. needs-info, pending-author). The flow logic stays put.
- Rewrite the closing comment
- Edit flowlibs_StaleIssueClosingComment to match your team's tone. The exact string is posted verbatim on each closed issue.
- Target a second repository
- Clone the solution, change flowlibs_GitHubRepository, and deploy side-by-side. Each instance can have its own label/threshold.
- Change cadence
- Edit the Recurrence trigger's frequency/interval to scan daily, twice a week, monthly, etc.
- Widen scan beyond 100 issues per run
- Replace the single Get Open Stale Labeled Issues call with a paginated loop — add an Until around the GitHub list action keyed off page number until the response body length is < 100.
- Drop the HTTP fallback when GitHub adds native comment op
- If the GitHub connector ever ships a native create issue comment operation, the built-in HTTP action is the only piece that needs refactoring — the rest stays put.
Key Expressions
The flow is intentionally light on Power Fx / WDL gymnastics — the heaviest expressions are the branch-name concatenation and the approval outcome check. They are listed below in the order they appear in the flow.
EXPR.01Cutoff computation
Produces an ISO-8601 UTC string the same shape GitHub returns, so string-less-than comparison against `updated_at` is valid.
EXPR.02Staleness check
Inside the For Each loop — true when the issue's updated_at is older than the cutoff.
EXPR.03PAT auth header
GitHub's fine-grained PAT scheme uses `token`, not `Bearer` — sent on the built-in HTTP POST that creates the comment.
EXPR.04Close reason payload
GitHub's Update Issue supports state_reason: not_planned | completed | reopened. This flow uses `not_planned` so the close mirrors 'abandoned, not resolved'.
Comments
Sign in to join the conversation.
Sign inNo comments yet. Be the first to share your experience with this flow.