Files
dotnet__skills/.github/workflows/close-stale-prs.agent.md

118 lines
7.3 KiB
Markdown

---
name: "Close Stale Pull Requests"
description: "Automatically warn about and close pull requests that have been open for more than 30 days with no recent activity."
on:
schedule: weekly on monday
workflow_dispatch: # Allow manual triggering
# ###############################################################
# Override the COPILOT_GITHUB_TOKEN secret usage for the workflow
# with a randomly-selected token from a pool of secrets.
#
# As soon as organization-level billing is offered for Agentic
# Workflows, this stop-gap approach will be removed.
#
# See: /.github/actions/select-copilot-pat/README.md
# ###############################################################
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
name: Checkout the select-copilot-pat action folder
with:
persist-credentials: false
sparse-checkout: .github/actions/select-copilot-pat
sparse-checkout-cone-mode: true
fetch-depth: 1
- id: select-copilot-pat
name: Select Copilot token from pool
uses: ./.github/actions/select-copilot-pat
env:
# If the secret names are changed here, they must also be changed
# in the `engine: env` case expression below
SECRET_0: ${{ secrets.COPILOT_GITHUB_TOKEN }}
SECRET_1: ${{ secrets.COPILOT_GITHUB_TOKEN_2 }}
SECRET_2: ${{ secrets.COPILOT_GITHUB_TOKEN_3 }}
SECRET_3: ${{ secrets.COPILOT_GITHUB_TOKEN_4 }}
SECRET_4: ${{ secrets.COPILOT_GITHUB_TOKEN_5 }}
SECRET_5: ${{ secrets.COPILOT_GITHUB_TOKEN_6 }}
SECRET_6: ${{ secrets.COPILOT_GITHUB_TOKEN_7 }}
SECRET_7: ${{ secrets.COPILOT_GITHUB_TOKEN_8 }}
# Don't run scheduled triggers on forked repositories — forks lack the
# secrets and context required, and scheduled runs would consume the
# fork owner's minutes.
if: ${{ !(github.event_name == 'schedule' && github.event.repository.fork) }}
# Add the pre-activation output of the randomly selected PAT
jobs:
pre-activation:
outputs:
copilot_pat_number: ${{ steps.select-copilot-pat.outputs.copilot_pat_number }}
# Override the COPILOT_GITHUB_TOKEN expression used in the activation job
# Consume the PAT number from the pre-activation step and select the corresponding secret
engine:
id: copilot
env:
# We cannot use line breaks in this expression as it leads to a syntax error in the compiled workflow
# If none of the `COPILOT_GITHUB_TOKEN_#` secrets were selected, then the default COPILOT_GITHUB_TOKEN is used
COPILOT_GITHUB_TOKEN: ${{ case(needs.pre_activation.outputs.copilot_pat_number == '0', secrets.COPILOT_GITHUB_TOKEN, needs.pre_activation.outputs.copilot_pat_number == '1', secrets.COPILOT_GITHUB_TOKEN_2, needs.pre_activation.outputs.copilot_pat_number == '2', secrets.COPILOT_GITHUB_TOKEN_3, needs.pre_activation.outputs.copilot_pat_number == '3', secrets.COPILOT_GITHUB_TOKEN_4, needs.pre_activation.outputs.copilot_pat_number == '4', secrets.COPILOT_GITHUB_TOKEN_5, needs.pre_activation.outputs.copilot_pat_number == '5', secrets.COPILOT_GITHUB_TOKEN_6, needs.pre_activation.outputs.copilot_pat_number == '6', secrets.COPILOT_GITHUB_TOKEN_7, needs.pre_activation.outputs.copilot_pat_number == '7', secrets.COPILOT_GITHUB_TOKEN_8, secrets.COPILOT_GITHUB_TOKEN) }}
safe-outputs:
close-pull-request:
max: 25
add-comment:
max: 30
noop:
report-as-issue: false
---
# Close Stale Pull Requests
You are an automated repository maintenance agent for the MSBuild repository.
## Task
Find pull requests that have been open for more than **30 days** and have had no recent activity. Depending on how long they have been inactive, either **warn** the author or **close** the pull request.
## Definitions
- **Created date**: The date the pull request was originally opened.
- **Last activity date**: The date of the most recent **non-bot** activity on the pull request. To determine this, list the PR's comments and reviews and find the most recent one **not** authored by a bot (i.e., ignore comments from users whose login ends with `[bot]`). If there are no non-bot comments or reviews, fall back to the PR's `created_at` date. Do **not** rely on `updated_at` alone, because the bot's own stale-warning comment updates `updated_at` and would reset the inactivity timer.
- **Stale (warning)**: A PR is eligible for a stale warning if it was created more than 30 days ago **and** its last non-bot activity was more than 30 days ago but no more than 37 days ago (i.e., 30 < days_since_last_non_bot_activity ≤ 37), **and** the PR does not already have a stale warning comment from this bot.
- **Stale (close)**: A PR is eligible for closure if it was created more than 30 days ago **and** its last non-bot activity was more than 37 days ago.
## Instructions
1. List all open pull requests in this repository.
2. For each open pull request:
a. Skip it if it has the label `no-stale` — these are exempt from this policy.
b. Skip it if it was authored by `dotnet-maestro[bot]` or `dotnet-maestro` — dependency update PRs are managed separately.
c. Skip it if it was created **fewer than 30 days ago**.
d. Determine the **last non-bot activity date**: fetch the PR's comments and reviews, find the most recent entry not authored by a bot (login ending in `[bot]`), and use its date. If none exist, use the PR's `created_at` date.
3. For each eligible pull request (created more than 30 days ago):
- If last non-bot activity was **more than 37 days ago**: **Close** the pull request using the `close_pull_request` tool (with `pull_request_number` set to the PR number) and the closing comment below.
- If last non-bot activity was **more than 30 days ago but 37 or fewer days ago** and the PR does not already have a stale warning comment from this bot: **Post a stale warning comment** using the `add_comment` tool (with `item_number` set to the PR number) and the warning comment below.
- Otherwise (non-bot activity within the last 30 days): Skip it — it is not stale.
## Important
- You **must** use the `close_pull_request` tool to close pull requests. Always provide the `pull_request_number` parameter with the PR number — this workflow runs on a schedule, not on a PR event, so the tool cannot auto-detect the target PR.
- You **must** use the `add_comment` tool to post stale warning comments. Always provide the `item_number` parameter with the PR number.
- When determining staleness, ignore all bot activity (comments/reviews from users with logins ending in `[bot]`). Only human activity resets the inactivity timer.
- Process all eligible pull requests, up to the tool limits.
## Stale Warning Comment Template
Use the following comment when warning about a stale pull request (using `add_comment`):
> This PR has been automatically marked as stale because it has no activity for 30 days. It will be closed if no further activity occurs within another 7 days of this comment. If it is closed, you may reopen it anytime when you're ready again.
## Closing Comment Template
Use the following comment when closing a stale pull request (as the `body` of `close_pull_request`):
> This pull request has been automatically closed because it has been open for more than 30 days with no recent activity.
>
> If you believe this work is still relevant, please feel free to reopen or create a new pull request. Thank you for your contribution!