The One-Liner
Cancel older running pipelines/workflows on the same branch (keep latest)
Hey engineer, happy Friday! đ
Today weâre taking a look at a one-liner power move for CI/CD that automatically cancels older duplicate runs for a branch and keeps the latest which lowers CI costs and gives you faster feedback.
Iâll give you GitHub Actions, GitLab, and a gh (GitHub CLI) variant. Each has a dry-run option and safe caveats.
1. GitHub Actions (curl + jq) â cancel older runs for branch-name
# env: GITHUB_TOKEN, OWNER, REPO, BRANCH
curl -s -H âAuthorization: Bearer $GITHUB_TOKENâ \
âhttps://api.github.com/repos/$OWNER/$REPO/actions/runs?per_page=100â \
| jq -r --arg BR â$BRANCHâ â.workflow_runs
| map(select(.head_branch==$BR and (.status==âin_progressâ or .status==âqueuedâ)))
| sort_by(.created_at)
| .[0:-1][] | .idâ \
| xargs -r -n1 -I{} curl -s -X POST -H âAuthorization: Bearer $GITHUB_TOKENâ \
âhttps://api.github.com/repos/$OWNER/$REPO/actions/runs/{}/cancelâ
Dry-run: replace the final curl -X POST ... with echo âcancel {}â inside the pipeline (or remove the | xargs ...and print IDs/URLs).
What it does: lists running/queued workflow runs for the branch, sorts by creation time, and cancels all but the newest.
2. GitHub CLI (cleaner) â same behaviour with gh
# env: GH_TOKEN set & gh authenticated, OWNER/REPO set or run within repo
gh api repos/$OWNER/$REPO/actions/runs --paginate --jq \
--jq â.workflow_runs | map(select(.head_branch==env.BRANCH and (.status==âin_progressâ or .status==âqueuedâ))) | sort_by(.created_at) | .[0:-1][] | .idâ \
| xargs -r -n1 -I{} gh api -X POST repos/$OWNER/$REPO/actions/runs/{}/cancel
Note: gh simplifies auth and pagination; use --jq/--paginate carefully.
3. GitLab â cancel older pipelines for a branch, keep the most recent
# env: GITLAB_TOKEN, PROJECT_ID, BRANCH
curl -s --header âPRIVATE-TOKEN: $GITLAB_TOKENâ \
âhttps://gitlab.com/api/v4/projects/$PROJECT_ID/pipelines?ref=$BRANCH&per_page=100â \
| jq -r âsort_by(.id) | .[0:-1][] | .idâ \
| xargs -r -n1 -I{} curl -s -X POST --header âPRIVATE-TOKEN: $GITLAB_TOKENâ \
âhttps://gitlab.com/api/v4/projects/â$PROJECT_IDâ/pipelines/{}/cancelâ
Dry-run: print pipeline IDs/URLs instead of calling cancel.
Quick breakdown & tips
sort_by(.created_at)(GitHub) orsort_by(.id)(GitLab) orders runs; removing the last (.[0:-1]) cancels all but the most recent.xargs -ravoids errors when no IDs are returned.Use
per_page/ pagination (or--paginatewithgh) if you have many runs.Run this in a pre-commit hook, a scheduled job, or as a short-lived GitHub Action/GitLab job triggered on push. Good to run as a small maintenance job for busy repos.
Dry-run first. Always list IDs/URLs before canceling to make sure you wonât cancel a deployment or other critical run.
Caveats & best practices
Auth & scopes: Token must have permissions (GitHub:
actionswrite; GitLab:api/maintaineras required). Donât hardcode tokens. Use repo secrets or a secrets manager.Deploy safety: Some pipelines include deploy steps; prefer canceling only test/build pipelines or ensure your pipeline is safe to be canceled mid-run (e.g., deploy steps gated or flagged).
Rate limits & pagination: If you query a very busy repo, use pagination and throttle requests to avoid API limits.
Run selection: Consider narrowing by
workflow_id,workflow_name, oractorto avoid canceling unrelated runs.Idempotency: Cancelling a run thatâs about to finish wastes a tiny amount of time; acceptable tradeoff vs. queue buildup. If unsure, add minimal age filter (
created_at < now - 30s) to avoid racing the latest run.
Variations youâll love
Only cancel queued runs (leave in_progress): change status filter to only
queued.Cancel older runs across all branches except main: donât filter by branch, but exclude
mainor protected branches.Auto-trigger after cancel (re-run latest): after canceling older runs you can explicitly re-run the latest to ensure a clean queue.
Until next time,
Stay sharp.
For those that want speed, reliability and best practices without starting from scratch, I released CI/CD Pipeline Templatesâââa collection of fully functional pipelines for GitHub Actions, GitLab CI, Jenkins, and CircleCI.
Donât waste another weekend writing Bash scripts from scratch.
The DevOps Automation Pack gives you 60+ plug-and-play production-ready Bash scripts for backups, monitoring, security, cleanup, and more.
Every script is cron-ready, supports dry-run mode, and works right out of the box.

