Label and close stale issues#

Issues and pull-requests are part of projects and repositories, but can also be forgotten when they grow out of control. You could search for stale issues manually once in a while, but it is another task on someone’s calendar that has been done. Like with post Add labels to GitHub pull requests this also can be automated. This way the backlog can be kept small so the team working on doesn’t have too much outstanding and untouched work.

Both GitHub App probot/stale and GitHub Action actions/stale are solutions that can be used to scan for stale issues and pull-requests, and label them or even close them. Both solutions have their benefits and drawbacks, but let’s see how they’re configured.

Using Probot Stale#

With GitHub App probot/stale an application scans with intervals if issues or pull-requests are overdue and should be labeled as stale or can even be closed. The GitHub App itself can be installed via apps/stale after which configuration file .github/stale.yml can be added to every repository that needs maintenance via this GitHub App.

Example configuration file .github/stale.yml#
---
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 60
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 10
# Issues with these labels will never be considered stale
exemptLabels:
  - pinned
  - security
# Label to use when marking an issue as stale
staleLabel: wontfix
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
  This issue has been automatically marked as stale because it has not had
  recent activity. It will be closed if no further activity occurs. Thank you
  for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false

The configuration is somewhat limited, but for most repositories, it does work as it marks issues as stale after 60 days and closes them after another 10 days. The exception is that issues having one of these labels pinned or security are excluded from being evaluated.

Warning

While Probot Stale is trusted by a lot of people, it is a third-party service with access to a repository.

Using GitHub Action Stale#

The second solution to use GitHub Action actions/stale which only requires a workflow file for GitHub Actions as the workflow file also contains the configuration. The most minimalistic version is the example below which will label issues and pull-requests after 60 days of inactivity and then closes them after another 7 days. GitHub will run this workflow every day at around 1:30 at night.

Workflow file .github/workflows/stale.yml for GitHub Actions#
---
name: 'Close stale issues and PRs'
on:
  schedule:
    - cron: '30 1 * * *'

permissions:
  issues: write
  pull-requests: write

jobs:
  stale:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/stale@v7

Warning

GitHub Actions are consuming time and will be billed against your pipeline budget. For public repositories, this is unlimited for now, but for private repositories, you have to pay per minute executed.

As said before is the configuration part of the workflow and the example below are similar to the configuration used in Using Probot Stale. The example is mostly extended with the option exempt-all-milestones: true that will exclude all issues and pull-requests that have been assigned to a milestone. Many more options can be found in the documentation, but this is a good starting point.

Workflow file .github/workflows/stale.yml for GitHub Actions#
---
name: 'Close stale issues and PRs'
on:
  schedule:
    - cron: '30 1 * * *'

permissions:
  issues: write
  pull-requests: write

jobs:
  stale:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/stale@v7
        with:
          close-issue-message: 'This issue has automatically been closed due to no activities.'
          close-pr-message: 'This pull-request has automatically been closed due to no activities.'
          stale-issue-message: 'This issue has not been updated for a while and will be closed soon.'
          stale-pr-message: 'This pull-request has not been updated for a while and will be closed soon.'
          days-before-stale: 60
          days-before-close: 10
          exempt-all-milestones: true
          exempt-issue-labels: security
          exempt-pr-labels: security
          stale-issue-label: stale
          stale-pr-label: stale

Note

Having the configuration as part of the file for the GitHub Action allows for this workflow to be reusable by other repositories.

Considerations for stale issues#

Automating the closing of unresolved issues and pull-requests may help to keep the backlog in control, but it may also kill the backlog if things get closed too quickly. The default timelines of 60 and 7 days may seem fine for smaller projects or with a high velocity, but longer timelines may be advised. And for projects with a huge backlog, it may be advised to use the option start-date that tells the action to ignore everything before this date.