A GitHub composite action that bulk-deletes workflow runs from a repository using the gh CLI. By default it targets skipped runs (the common cleanup case), but it can also delete runs with any other conclusion — or all runs regardless of conclusion. Useful for keeping a repo's Actions history tidy.
- name: Delete skipped workflow runs
uses: MandalAutomations/Removed_Skipped_Runs@main
with:
repo: my-org/my-repo
num_to_delete: '500'
github_token: ${{ secrets.GH_TOKEN }}The job must grant actions: write to the token (see the example workflow below).
| Input | Required | Default | Description |
|---|---|---|---|
repo |
Yes | — | Repository in owner/repo form (e.g. my-org/my-repo). |
num_to_delete |
No | 500 |
Maximum number of workflow runs to delete in one invocation. |
conclusion |
No | skipped |
Run conclusion to target. One of skipped, success, failure, cancelled, stale, timed_out, neutral, action_required, startup_failure, or all. |
dry_run |
No | false |
If true, list runs that would be deleted without deleting them. |
github_token |
Yes | — | Token used to authenticate the gh CLI. Needs actions: write on the target repo. The default GITHUB_TOKEN works if the calling job grants that permission. |
The action runs scripts/delete_runs.sh, which lists workflow runs from the configured repository (filtering server-side by conclusion when one is given) and deletes up to num_to_delete of them via gh api --method DELETE. Schedule it on a cron (e.g. nightly) to keep your Actions history tidy.
The script counts only successful deletions and reports failures separately, so if you scheduled it on cron and it starts emitting failure counts, you'll know.
name: Cleanup workflow runs
on:
schedule:
- cron: '0 3 * * *' # 03:00 UTC daily
workflow_dispatch:
jobs:
cleanup:
runs-on: ubuntu-latest
permissions:
actions: write
contents: read
steps:
- uses: MandalAutomations/Removed_Skipped_Runs@main
with:
repo: ${{ github.repository }}
num_to_delete: '200'
github_token: ${{ github.token }}Delete failed runs in dry-run mode (logs IDs but deletes nothing):
- uses: MandalAutomations/Removed_Skipped_Runs@main
with:
repo: ${{ github.repository }}
conclusion: failure
dry_run: 'true'
github_token: ${{ github.token }}Delete up to 1000 runs of any conclusion:
- uses: MandalAutomations/Removed_Skipped_Runs@main
with:
repo: ${{ github.repository }}
conclusion: all
num_to_delete: '1000'
github_token: ${{ github.token }}