ci: enhance stale issue/PR workflow (#522)
# ci: enhance stale issue/PR workflow
- Split stale workflow into marking and closing jobs
- Add dry-run mode input and environment variables
- Improve configuration for timing, messages, and operations per run
## Motivation and Context
To mark and close stale issues/PRs automatically
## How it works
The automations.yml workflow automates the lifecycle of inactive issues
and pull requests using a two-stage process. It is scheduled to run
daily at 2:00 AM UTC and supports manual execution with a dry-run
option.
### 1. Marking Phase (mark-stale job)
This job identifies inactive items and labels them as stale without
closing them.
- Criteria: Any issue or PR with no activity for 30 days.
- Action: Adds the stale label and posts a notification comment.
- Exemptions:
- Draft PRs are ignored.
- Issues labeled with awaiting-approval or work-in-progress are ignored.
- Recovery: If a contributor updates the item, the stale label is
automatically removed.
- Safety: This job is explicitly configured never to close items
(days-before-*-close: -1).
### 2. Closing Phase (close-stale job)
This job handles the final closure of items that have remained inactive
after being marked.
- Criteria: Only targets items that already have the stale label and
have seen no further activity for 15 days.
- Action: Closes the issue or PR and posts a final closure message.
- Safety: This job is explicitly configured never to mark new items
(days-before-*-stale: -1).
### Global Configuration
- Dry Run: Controlled by the DRY_RUN variable. When true, the bot logs
planned actions in the workflow output but does not actually apply
labels, post comments, or close items.
- Throttling: Processes up to 100 items per run to avoid hitting GitHub
API rate limits.
- Permissions: Requires write access to issues and pull requests to
perform its actions.
## How Has This Been Tested?
[Manually tested on
CI](https://github.com/modelcontextprotocol/kotlin-sdk/actions/runs/21984701285)
with dry run
## Breaking Changes
No
## Types of changes
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] Documentation update
- [x] Workflow update
## Checklist
<!-- Go over all the following points, and put an `x` in all the boxes
that apply. -->
- [ ] I have read the [MCP
Documentation](https://modelcontextprotocol.io)
- [ ] My code follows the repository's style guidelines
- [ ] New and existing tests pass locally
- [ ] I have added appropriate error handling
- [ ] I have added or updated documentation as needed
## Additional context
<!-- Add any other context, implementation notes, or design decisions
-->
This commit is contained in:
parent
6120b3109e
commit
52a0ec3b8f
1 changed files with 65 additions and 31 deletions
106
.github/workflows/automations.yml
vendored
106
.github/workflows/automations.yml
vendored
|
|
@ -5,6 +5,11 @@ on:
|
|||
# Runs every day at 2:00 AM UTC
|
||||
- cron: '0 2 * * *'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
DRY_RUN:
|
||||
type: boolean
|
||||
description: 'Run in dry run mode'
|
||||
default: true
|
||||
|
||||
permissions:
|
||||
actions: write
|
||||
|
|
@ -12,58 +17,87 @@ permissions:
|
|||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
env:
|
||||
DRY_RUN: true
|
||||
MOVE_TO_STALE_DAYS: 30
|
||||
CLOSE_AFTER_STALE_DAYS: 15
|
||||
|
||||
jobs:
|
||||
close-question-prs:
|
||||
name: Mark/Close stale PRs and issues
|
||||
mark-stale:
|
||||
name: Mark/unmark stale PRs and issues
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v10
|
||||
## https://github.com/marketplace/actions/close-stale-issues
|
||||
with:
|
||||
debug-only: true # 'true' for dry run
|
||||
exempt-draft-pr: true # pull requests currently in draft will not be marked as stale
|
||||
debug-only: ${{ env.DRY_RUN }}
|
||||
exempt-draft-pr: true
|
||||
exempt-issue-labels: 'awaiting-approval,work-in-progress'
|
||||
stale-issue-label: 'stale'
|
||||
stale-pr-label: 'stale'
|
||||
only-labels: 'awaiting-feedback,awaiting-answers'
|
||||
|
||||
# --- Scope: only PRs, not issues ---
|
||||
stale-issue-message: >
|
||||
👋 **This issue has been marked as Stale.**
|
||||
|
||||
This issue was awaiting feedback and has had no activity for **30 days**.
|
||||
|
||||
— 🤖 Stale PR Bot
|
||||
days-before-issue-stale: 30
|
||||
days-before-issue-close: -1
|
||||
|
||||
# --- Timing ---
|
||||
# Since we target PRs already labeled "question",
|
||||
# days-before-stale counts from last activity.
|
||||
days-before-pr-stale: 30
|
||||
days-before-pr-close: 15
|
||||
# Job 1 marks/unmarks, but never closes.
|
||||
days-before-issue-stale: ${{ env.MOVE_TO_STALE_DAYS }}
|
||||
days-before-issue-close: -1
|
||||
days-before-pr-stale: ${{ env.MOVE_TO_STALE_DAYS }}
|
||||
days-before-pr-close: -1
|
||||
|
||||
# --- Labels ---
|
||||
remove-stale-when-updated: true
|
||||
remove-pr-stale-when-updated: true
|
||||
|
||||
# --- Messages ---
|
||||
stale-issue-message: >
|
||||
👋 **This issue has been marked as Stale.**
|
||||
|
||||
This issue has had no activity for **${{ env.MOVE_TO_STALE_DAYS }} days**.
|
||||
|
||||
— 🤖 Stale Bot
|
||||
stale-pr-message: >
|
||||
👋 **This PR has been marked as Stale.**
|
||||
|
||||
This PR was awaiting feedback and has had no activity for **30 days**.
|
||||
|
||||
— 🤖 Stale PR Bot
|
||||
close-pr-message: >
|
||||
👋 **This PR has been automatically closed.**
|
||||
|
||||
This PR was labeled with `stale` and has had no activity
|
||||
for **15 days** since that.
|
||||
|
||||
If this is still relevant, please feel free to reopen it
|
||||
or create a new PR.
|
||||
|
||||
— 🤖 Stale PR Bot
|
||||
|
||||
# --- Operations ---
|
||||
This PR has had no activity for **${{ env.MOVE_TO_STALE_DAYS }} days**.
|
||||
|
||||
— 🤖 Stale Bot
|
||||
|
||||
operations-per-run: 100
|
||||
ascending: true
|
||||
|
||||
close-stale:
|
||||
name: Close stale PRs and issues
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v10
|
||||
with:
|
||||
debug-only: ${{ env.DRY_RUN }}
|
||||
only-labels: 'stale'
|
||||
stale-issue-label: 'stale'
|
||||
stale-pr-label: 'stale'
|
||||
|
||||
# --- Timing ---
|
||||
# Job 2 only closes already marked items.
|
||||
days-before-issue-stale: -1
|
||||
days-before-pr-stale: -1
|
||||
days-before-issue-close: ${{ env.CLOSE_AFTER_STALE_DAYS }}
|
||||
days-before-pr-close: ${{ env.CLOSE_AFTER_STALE_DAYS }}
|
||||
|
||||
# --- Messages ---
|
||||
close-issue-message: >
|
||||
👋 **This issue has been automatically closed.**
|
||||
|
||||
This issue was labeled with `stale` and has had no activity
|
||||
for **${{ env.CLOSE_AFTER_STALE_DAYS }} days** since that.
|
||||
|
||||
— 🤖 Stale Bot
|
||||
close-pr-message: >
|
||||
👋 **This PR has been automatically closed.**
|
||||
|
||||
This PR was labeled with `stale` and has had no activity
|
||||
for **${{ env.CLOSE_AFTER_STALE_DAYS }} days** since that.
|
||||
|
||||
If this is still relevant, please feel free to reopen it
|
||||
or create a new PR.
|
||||
|
||||
— 🤖 Stale Bot
|
||||
|
||||
operations-per-run: 100
|
||||
ascending: true
|
||||
|
|
|
|||
Loading…
Reference in a new issue