Skip to content

Add stale label tagging and 30-day auto-close to stale-issues workflow#474

Merged
strawgate merged 16 commits intomainfrom
copilot/allow-tagging-stale-issues
Feb 28, 2026
Merged

Add stale label tagging and 30-day auto-close to stale-issues workflow#474
strawgate merged 16 commits intomainfrom
copilot/allow-tagging-stale-issues

Conversation

Copy link
Contributor

Copilot AI commented Feb 28, 2026

This PR splits stale-issue automation into a detector/fixer pair: stale-issues is now stale-issues-investigator, and a new stale-issues-remediator workflow handles objections and 30-day auto-close.

What changed

  • Split the previous single flow into two workflows

    • Investigator (gh-aw-stale-issues-investigator) finds likely-resolved open issues, applies the configurable stale label, and files a report.
    • Remediator (gh-aw-stale-issues-remediator) processes already stale-labeled issues: removes the label when valid objections are posted, and closes issues after 30+ days with no objection.
  • Added stale-label input

    • Both investigator and remediator accept stale-label (default stale) and reference it throughout safe outputs and prompts.
  • Added remediator prep/data collection

    • Remediator preloads stale-labeled issues, recent comments, and label add/remove events into local JSON files:
      • /tmp/stale-labeled-issues.json
      • /tmp/stale-recent-comments.json
      • /tmp/stale-label-events.json
  • Safe outputs updated by role

    • Investigator: add-labels + create-issue
    • Remediator: remove-labels + close-issue (with required stale label)
  • Workflow migration and compatibility

    • Added new lock/source/trigger files for investigator and remediator.
    • Kept .github/workflows/gh-aw-stale-issues.lock.yml as a backward-compatibility copy with a deprecation header pointing to gh-aw-stale-issues-investigator.lock.yml.
  • Maintenance cadence update

    • .github/workflows/agentics-maintenance.yml now runs every 6 hours (from daily) to align with the 2-day expiration window used by stale-issues reporting.
  • Docs/setup updates

    • Updated stale workflow docs and examples under gh-agent-workflows/.
    • Added the consolidated stale-issues docs page in docs/workflows/gh-agent-workflows/stale-issues.md.
    • Updated workflow catalog and upgrade guidance to document the rename/split and migration path.
    • Updated quick setup and compatibility tooling to include the new workflow names.

Generated by Update PR Body for issue #474

Copilot AI and others added 2 commits February 28, 2026 06:53
Update the stale-issues workflow to operate in two phases:
1. Close phase: auto-close issues labeled 'stale' for 30+ days
2. Tag phase: label newly identified stale candidates with 'stale'

Add add-labels and close-issue safe outputs. Update permissions
to issues: write. Update README and docs.

Co-authored-by: strawgate <6384545+strawgate@users.noreply.github.com>
Co-authored-by: strawgate <6384545+strawgate@users.noreply.github.com>
Copilot AI changed the title [WIP] Add tagging feature for stale issues with auto-close Add stale label tagging and 30-day auto-close to stale-issues workflow Feb 28, 2026
@strawgate strawgate marked this pull request as ready for review February 28, 2026 06:55
@strawgate
Copy link
Collaborator

@copilot if someone has commented not stale then we should remove the stale label on our next check

Phase 1 now checks for objection comments (e.g. "not stale",
"still relevant") posted after the stale label was added. If found,
the stale label is removed via gh CLI and the issue is skipped
from automatic closure.

Co-authored-by: strawgate <6384545+strawgate@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 28, 2026

@copilot if someone has commented not stale then we should remove the stale label on our next check

Done in 2c83619. Phase 1 now checks for objection comments ("not stale", "still relevant", "still needed", "still an issue", "still a problem") posted after the stale label was added. If found, the label is removed via gh issue edit --remove-label stale and the issue is skipped from automatic closure.

@coderabbitai
Copy link

coderabbitai bot commented Feb 28, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e71b7cf and 485c98c.

📒 Files selected for processing (4)
  • .github/workflows/gh-aw-stale-issues-remediator.lock.yml
  • .github/workflows/gh-aw-stale-issues-remediator.md
  • docs/workflows/gh-agent-workflows/stale-issues.md
  • github/workflows/gh-aw-stale-issues-remediator.md

📝 Walkthrough

Walkthrough

This pull request splits the single "stale-issues" GitHub Actions workflow into two specialized workflows: stale-issues-investigator (labels likely-resolved issues as stale and files a report) and stale-issues-remediator (processes stale-labeled issues, removes labels for objections, and closes issues after a 30-day grace period). It adds an add_labels safe-outputs tool and a configurable stale-label input, updates triggers, lockfiles, docs, example workflows, and quick-setup/backwards-compat scripts to reflect the new investigator/remediator split and preserve compatibility.

Possibly related PRs

  • PR 312 — Large workflow renames/additions touching the same stale-issues investigator and remediator workflow files and corresponding trigger/lockfile updates.
  • PR 481 — Modifies the stale-issues workflow data-gathering and prescan steps that overlap the investigator’s labeling logic.
  • PR 341 — Updates the backwards-compatibility script and mappings used to maintain copies for renamed workflow files (stale-issues → stale-issues-investigator).
🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Linked Issues check ✅ Passed PR implements all primary objectives from #472: enables tagging issues as stale, automatically closes after 30-day grace period, includes objection handling via label removal, and uses safe outputs for label operations.
Out of Scope Changes check ✅ Passed All changes are scoped to implementing the stale-issues workflow enhancement. Documentation updates and workflow definition align with stated objectives; no unrelated changes detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch copilot/allow-tagging-stale-issues

Comment @coderabbitai help to get the list of available commands and usage tips.

github-actions[bot]

This comment was marked as resolved.

@strawgate
Copy link
Collaborator

/ai we won't be using gh command line to do edits we'll need to use a real gh-aw safe output to modify labels

Copilot bot added 2 commits February 28, 2026 07:17
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@cla-checker-service
Copy link

cla-checker-service bot commented Feb 28, 2026

❌ Author of the following commits did not sign a Contributor Agreement:
, , , , 9ec894b, 863815e, , ,

Please, read and sign the above mentioned agreement if you want to contribute to this project

coderabbitai[bot]

This comment was marked as resolved.

@strawgate
Copy link
Collaborator

/ai can you check if we could use a workflow input for the name of the stale label?

Does the order of events here cause any concerns? Is there any of this that we should script to help? Like for issues with the stale label, write all issue numbers and names to disk, for issues with the stale label and a comment more recent than the stale label put those in a separate file, etc.

We can probably also modify our duplicate issues agent to also have a script run which dumps like the first thousand open issue numbers and titles to disk? Kinda line we do for the previous findings agent

@github-actions
Copy link
Contributor

Yes—adding a workflow input for the stale label is reasonable, and you already use this pattern elsewhere (.github/workflows/gh-aw-scheduled-fix.md:34-38, query usage at :123-127).

Main concerns I see in this PR version:

  • The close-phase logic relies on issue_read get_comments to determine when the label was added/removed (.github/workflows/gh-aw-stale-issues.md:110-123), but comments don’t provide label event history, so the 30-day cutoff is not reliably observable.
  • There’s still a guardrail mismatch in the source workflow: direct gh issue edit --remove-label stale is instructed at :112-115, while safe-outputs in that same file currently defines add-labels and close-issue only (:71-87).

On event/order: running close first, then tag is the right order and avoids same-run reprocessing of newly-tagged issues.

On scripting: I agree it would help. I’d add a prep step (same idea as previous-findings, .github/workflows/gh-aw-fragments/previous-findings.md:3-15) to write machine-readable snapshots, e.g.:

  1. stale-labeled-issues.json (issue number/title/updated_at)
  2. stale-objections.json (subset with newer objection comments)
  3. (for duplicate issues detector) open-issues-top-1000.json with number/title/updated_at/labels

That gives deterministic inputs to the agent prompt and makes debugging/replays much easier.


What is this? | From workflow: Mention in PR

Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.

@strawgate
Copy link
Collaborator

Yes—adding a workflow input for the stale label is reasonable, and you already use this pattern elsewhere (.github/workflows/gh-aw-scheduled-fix.md:34-38, query usage at :123-127).

Main concerns I see in this PR version:

  • The close-phase logic relies on issue_read get_comments to determine when the label was added/removed (.github/workflows/gh-aw-stale-issues.md:110-123), but comments don’t provide label event history, so the 30-day cutoff is not reliably observable.
  • There’s still a guardrail mismatch in the source workflow: direct gh issue edit --remove-label stale is instructed at :112-115, while safe-outputs in that same file currently defines add-labels and close-issue only (:71-87).

On event/order: running close first, then tag is the right order and avoids same-run reprocessing of newly-tagged issues.

On scripting: I agree it would help. I’d add a prep step (same idea as previous-findings, .github/workflows/gh-aw-fragments/previous-findings.md:3-15) to write machine-readable snapshots, e.g.:

  1. stale-labeled-issues.json (issue number/title/updated_at)
  2. stale-objections.json (subset with newer objection comments)
  3. (for duplicate issues detector) open-issues-top-1000.json with number/title/updated_at/labels

That gives deterministic inputs to the agent prompt and makes debugging/replays much easier.

What is this? | From workflow: Mention in PR

Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.

@copilot I agree let's do it, for removing labels we should use remove-labels safe output.

Copilot AI and others added 2 commits February 28, 2026 18:13
…ep step

- Replace gh CLI label removal with remove-labels safe output
- Add configurable stale-label workflow input (default: "stale")
- Add prep step that dumps stale-labeled issues and recent comments to
  /tmp/stale-labeled-issues.json and /tmp/stale-recent-comments.json
- Use ${{ inputs.stale-label }} throughout prompt and safe-outputs config
- Remove erroneous github/workflows/ duplicate file
- Update README with new input and prep step docs

Co-authored-by: strawgate <6384545+strawgate@users.noreply.github.com>
…o 500 chars

Co-authored-by: strawgate <6384545+strawgate@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 28, 2026

/ai we won't be using gh command line to do edits we'll need to use a real gh-aw safe output to modify labels

Fixed in e15a6a4 — replaced gh issue edit --remove-label with the remove-labels safe output, configured with allowed: ["${{ inputs.stale-label }}"] and max: 10.

Yes—adding a workflow input for the stale label is reasonable, and you already use this pattern elsewhere (.github/workflows/gh-aw-scheduled-fix.md:34-38, query usage at :123-127).

Main...

Implemented in e15a6a4:

  • remove-labels safe output — configured with allowed: ["${{ inputs.stale-label }}"], used in Phase 1 for objection handling
  • stale-label input — new workflow input (default: "stale"), referenced throughout safe-outputs config and prompt via ${{ inputs.stale-label }}
  • Scripted prep step — dumps stale-labeled issues to /tmp/stale-labeled-issues.json (number, title, updatedAt, labels, createdAt) and last 5 comments per issue to /tmp/stale-recent-comments.json, following the previous-findings pattern
  • Also removed the erroneous github/workflows/ duplicate file that was created in a previous commit

/ai can you check if we could use a workflow input for the name of the stale label?

Does the order of events here cause any concerns? Is there any of this that we should script to help? Like for is...

Added in e15a6a4:

  1. stale-label input — configurable label name, defaults to "stale". Used throughout safe-outputs config and prompt.
  2. Scripted prep step — runs before the agent, dumps /tmp/stale-labeled-issues.json (all open stale-labeled issues) and /tmp/stale-recent-comments.json (last 5 comments per issue). The agent reads these for an overview before doing precise label-date checks.

The duplicate-issues agent suggestion (dumping first 1000 open issues) makes sense but would be a separate PR since it touches a different workflow.

@strawgate strawgate closed this Feb 28, 2026
@strawgate strawgate reopened this Feb 28, 2026
github-actions[bot]

This comment was marked as resolved.

@strawgate
Copy link
Collaborator

@copilot can you check out the tool name and make sure we got it right

The workflow runs on schedule/dispatch (no triggering issue), so
add-labels, remove-labels, and close-issue all need target: "*" to
operate on arbitrary issues (default "triggering" requires an issue
event). Also fix required_labels → required-labels to match gh-aw
reference docs kebab-case convention.

Co-authored-by: strawgate <6384545+strawgate@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 28, 2026

@copilot can you check out the tool name and make sure we got it right

Verified against the gh-aw reference docs: remove-labels is a valid safe output type and remove_labels is the correct tool function name (matching the add_labels convention).

Found two additional issues while checking — fixed in 6a5cbfb:

  • Added target: "*" to all three safe outputs (add-labels, remove-labels, close-issue). The default "triggering" requires an issue event, but this workflow runs on schedule/dispatch with no triggering issue.
  • Fixed required_labelsrequired-labels to match the gh-aw kebab-case convention.

coderabbitai[bot]

This comment was marked as resolved.

- Add prep step to fetch label timeline events to /tmp/stale-label-events.json
  for reliable 30-day expiry calculation
- Fix close-issue → close_issue to match snake_case tool convention
- Update prompt to reference label events file for 30-day check
- Revert issues: write → read (safe outputs handle permissions)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
coderabbitai[bot]

This comment was marked as resolved.

github-actions[bot]

This comment was marked as resolved.

Prevents incomplete label event history on issues with >30 events,
which could cause premature 30-day closure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
github-actions[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

Fixes review feedback: multi-word labels need quoting in GitHub search
queries, and code fences should specify a language marker.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
github-actions[bot]

This comment was marked as resolved.

Keeps both the stale-labeled issues collection step (from this PR)
and the prescan open issues step (from merged PR #481). Recompiled
lock file.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Separates the combined stale-issues workflow into two with a hard
permission boundary:

- **stale-issues-investigator**: finds resolved issues, labels them
  as stale, files a report (add-labels, create-issue, noop)
- **stale-issues-remediator**: processes stale-labeled issues —
  handles objections and closes after 30-day grace (remove-labels,
  close-issue, noop)

Renames stale-issues → stale-issues-investigator with a
backwards-compat copy at the old lock.yml path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@github/workflows/gh-aw-stale-issues-remediator.md`:
- Around line 111-115: The gh api invocation is incorrectly passing jq's --arg
to gh (causing silent failure); change the pipeline so gh api outputs raw JSON
(use gh api --paginate "repos/$GITHUB_REPOSITORY/issues/$num/events" without
--jq/--arg) and then pipe that output into a standalone jq process that uses
--arg lbl "$STALE_LABEL" and the existing filter expression, e.g.: gh api ... |
jq --arg lbl "$STALE_LABEL" '[.[] | select((.event=="labeled" or
.event=="unlabeled") and .label.name==$lbl) | {number: '"$num"', event: .event,
created_at: .created_at}]' 2>/dev/null || echo "[]", ensuring the overall
pipeline still writes /tmp/stale-label-events.json or falls back to "[]".

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 06116d7 and e71b7cf.

📒 Files selected for processing (18)
  • .github/workflows/agentics-maintenance.yml
  • .github/workflows/gh-aw-stale-issues-investigator.lock.yml
  • .github/workflows/gh-aw-stale-issues-investigator.md
  • .github/workflows/gh-aw-stale-issues-remediator.lock.yml
  • .github/workflows/gh-aw-stale-issues-remediator.md
  • .github/workflows/gh-aw-stale-issues.lock.yml
  • .github/workflows/trigger-stale-issues-investigator.yml
  • .github/workflows/trigger-stale-issues-remediator.yml
  • docs/upgrading.md
  • docs/workflows/gh-agent-workflows.md
  • gh-agent-workflows/stale-issues-investigator/README.md
  • gh-agent-workflows/stale-issues-investigator/example.yml
  • gh-agent-workflows/stale-issues-remediator/README.md
  • gh-agent-workflows/stale-issues-remediator/example.yml
  • github/workflows/gh-aw-stale-issues-investigator.md
  • github/workflows/gh-aw-stale-issues-remediator.md
  • scripts/backwards-compat.sh
  • scripts/quick-setup.sh
✅ Files skipped from review due to trivial changes (1)
  • gh-agent-workflows/stale-issues-remediator/README.md

- Create docs/workflows/gh-agent-workflows/stale-issues.md overview
  page covering both investigator and remediator (fixes nav/catalog
  consistency check)
- Fix remediator prep step: gh api does not support --arg, pipe to
  standalone jq instead

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@strawgate strawgate merged commit 50bcf4b into main Feb 28, 2026
16 of 17 checks passed
@strawgate strawgate deleted the copilot/allow-tagging-stale-issues branch February 28, 2026 21:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants