Skip to content
Latchkey

Stale Bot workflow (gatsbyjs/gatsby)

The Stale Bot workflow from gatsbyjs/gatsby, explained and optimized by Latchkey.

B

CI health: B - good

Point runs-on at Latchkey and get job timeouts, SHA-pinned actions, self-healing for flaky steps, and up to 58% lower cost, applied automatically.

Grade your own workflow free or run it on Latchkey →
Source: gatsbyjs/gatsby.github/workflows/schedule-stale.ymlLicense MITView source

What it does

This is the Stale Bot workflow from the gatsbyjs/gatsby repository, a real project running GitHub Actions. It is shown here with attribution under its MIT license.

Below, Latchkey shows a faster, safer version produced by its optimization engine.

The workflow

workflow (.yml)
name: Stale Bot
on:
  schedule:
    - cron: "0 */12 * * *"
permissions:
  contents: read
jobs:
  stale:
    permissions:
      contents: read
      issues: write
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: actions/stale@v10
        name: stale
        id: stale
        with:
          days-before-stale: 20
          days-before-pr-stale: -1 # Don't mark PRs as stale
          days-before-close: 40
          exempt-all-assignees: true
          operations-per-run: 1000
          stale-issue-message: |
            Hiya!

            This issue has gone quiet. Spooky quiet. 👻

            We get a lot of issues, so we currently close issues after 60 days of inactivity. It’s been at least 20 days since the last update here.
            If we missed this issue or if you want to keep it open, please reply here.
            As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request. Check out [gatsby.dev/contribute](https://www.gatsbyjs.com/contributing#how-to-contribute) for more information about opening PRs, triaging issues, and contributing!

            Thanks for being a part of the Gatsby community! 💪💜
          close-issue-message: |
            Hey again!

            It’s been 60 days since anything happened on this issue, so our friendly neighborhood robot (that’s me!) is going to close it.
            Please keep in mind that I’m only a robot, so if I’ve closed this issue in error, I’m `HUMAN_EMOTION_SORRY`. Please feel free to comment on this issue or create a new one if you need anything else.
            As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request. Check out [gatsby.dev/contribute](https://www.gatsbyjs.com/contributing#how-to-contribute) for more information about opening PRs, triaging issues, and contributing!

            Thanks again for being part of the Gatsby community! 💪💜
          stale-issue-label: "stale?"
          exempt-issue-labels: "not stale,status: triage needed,status: confirmed"
      - name: Format Stale Output
        id: format-stale-output
        uses: ./.github/actions/format-stale-output
        with:
          staled-issues-prs: ${{ steps.stale.outputs.staled-issues-prs }}
          closed-issues-prs: ${{ steps.stale.outputs.closed-issues-prs }}
      - name: Slack Report Closed Issues
        uses: pullreminders/slack-action@master
        env:
          SLACK_BOT_TOKEN: ${{ secrets.SLACK_TOKEN }}
        with:
          args: '{\"channel\": \"${{ secrets.SLACK_STALE_CHANNEL_ID }}\", \"text\": \"\", \"blocks\": ${{ steps.format-stale-output.outputs.blocks }} }'

The same workflow, on Latchkey

Removes redundant runs and caps runaway jobs. Added and changed lines are highlighted.

name: Stale Bot
on:
  schedule:
    - cron: "0 */12 * * *"
permissions:
  contents: read
jobs:
  stale:
    timeout-minutes: 30
    permissions:
      contents: read
      issues: write
    runs-on: latchkey-small
    steps:
      - uses: actions/checkout@v6
      - uses: actions/stale@v10
        name: stale
        id: stale
        with:
          days-before-stale: 20
          days-before-pr-stale: -1 # Don't mark PRs as stale
          days-before-close: 40
          exempt-all-assignees: true
          operations-per-run: 1000
          stale-issue-message: |
            Hiya!
 
            This issue has gone quiet. Spooky quiet. 👻
 
            We get a lot of issues, so we currently close issues after 60 days of inactivity. It’s been at least 20 days since the last update here.
            If we missed this issue or if you want to keep it open, please reply here.
            As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request. Check out [gatsby.dev/contribute](https://www.gatsbyjs.com/contributing#how-to-contribute) for more information about opening PRs, triaging issues, and contributing!
 
            Thanks for being a part of the Gatsby community! 💪💜
          close-issue-message: |
            Hey again!
 
            It’s been 60 days since anything happened on this issue, so our friendly neighborhood robot (that’s me!) is going to close it.
            Please keep in mind that I’m only a robot, so if I’ve closed this issue in error, I’m `HUMAN_EMOTION_SORRY`. Please feel free to comment on this issue or create a new one if you need anything else.
            As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request. Check out [gatsby.dev/contribute](https://www.gatsbyjs.com/contributing#how-to-contribute) for more information about opening PRs, triaging issues, and contributing!
 
            Thanks again for being part of the Gatsby community! 💪💜
          stale-issue-label: "stale?"
          exempt-issue-labels: "not stale,status: triage needed,status: confirmed"
      - name: Format Stale Output
        id: format-stale-output
        uses: ./.github/actions/format-stale-output
        with:
          staled-issues-prs: ${{ steps.stale.outputs.staled-issues-prs }}
          closed-issues-prs: ${{ steps.stale.outputs.closed-issues-prs }}
      - name: Slack Report Closed Issues
        uses: pullreminders/slack-action@master
        env:
          SLACK_BOT_TOKEN: ${{ secrets.SLACK_TOKEN }}
        with:
          args: '{\"channel\": \"${{ secrets.SLACK_STALE_CHANNEL_ID }}\", \"text\": \"\", \"blocks\": ${{ steps.format-stale-output.outputs.blocks }} }'
 

What changed

1 third-party action is referenced by a movable tag. Pin it to the commit SHA (Latchkey resolves and applies this automatically) so a repointed tag cannot change what runs.

This workflow runs 1 job per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.

Actions used in this workflow