GitHub Actions guides

Make your CI faster, cheaper, and more reliable. Each guide is the exact fix for a specific waste pattern, the same ones GitSpider detects automatically, backed by real scans of popular repos.

Why your GitHub Actions CI is slow (and how to speed it up)
The usual reasons GitHub Actions CI is slow: duplicate runs, no caching, no concurrency control, oversized matrices. Each with the exact YAML fix, based on real scans of 35 popular repos.
The GitHub Actions workflow that's been failing for weeks (and how to find it)
Scheduled GitHub Actions workflows quietly fail for months and nobody notices: the failure emails get filtered, the red X gets tuned out. How to find your always-failing workflows and what to do, with real examples from popular repos.
How to cache dependencies in GitHub Actions (and cut build time)
Caching is the cheapest GitHub Actions speedup: one line on your setup step stops every run reinstalling dependencies. Built-in caching, actions/cache, cache keys, and why caches miss.
GitHub Actions concurrency: cancel superseded runs with one block
Without a concurrency group, pushing twice runs both commits to the end. cancel-in-progress kills the superseded run. The exact YAML, the group key explained, and when NOT to cancel (deploys). The most common gap in the repos we scan.
The GitHub Actions timeout nobody sets (and the 6-hour job it hides)
Leaving timeout-minutes off a job does not mean no limit, it means GitHub's 6-hour default. A hung test or a stalled network call burns minutes to that ceiling before it is cancelled. The one-line fix, job vs step timeouts, and why scheduled jobs are the worst case.
How to cache pip dependencies in GitHub Actions (one line)
setup-python caches pip with cache: 'pip'. One line stops every run re-downloading your requirements. What it caches, cache-dependency-path, poetry and uv, and a popular repo that still skips it.
Python version matrix in GitHub Actions: test 3.10-3.14 without waste
How to test every supported Python version with a strategy matrix: the quoting trap (3.10 becomes 3.1), per-version pip caches, include: for spot-checking other OSes, and when to turn off fail-fast.
Caching cargo builds in GitHub Actions: use rust-cache, not actions/cache
Rust pays the most for a missing CI cache: full dependency recompiles every run. Swatinem/rust-cache is the one-line standard: what it caches, why hand-rolled actions/cache backfires on target/, and when skipping the cache is actually fine.
Go module caching in GitHub Actions: setup-go already does it
Since v4, actions/setup-go caches Go modules and build output by default, keyed on go.sum. When you're already covered, the monorepo cache-dependency-path case, and where Go CI actually leaks minutes instead.
Caching Gradle and Maven dependencies in GitHub Actions
setup-java caches Gradle or Maven with one cache: option. Hundreds of artifacts stop re-downloading every run. When to step up to gradle/actions/setup-gradle for the build cache, and the Maven habits that keep the cache stable.
bundler-cache: true, the one-option Ruby cache in GitHub Actions
ruby/setup-ruby installs and caches your gems with a single option, replacing the manual bundle install step. Why Gemfile.lock is required, the double-install mistake, and native-extension caching across a version matrix.
Your GitHub Actions bill is mostly macOS minutes (here's how to tell)
macOS runners bill ~10x a Linux minute and xlarge tiers more; one 10-minute macOS job per PR is 100 Linux-equivalent minutes. What genuinely needs macOS, what's inertia, and the one-line moves that cut the premium.
Scheduled workflows: the GitHub Actions cost nobody is watching
Cron-triggered workflows run with nobody waiting, so hangs, over-firing schedules, and always-red runs drain minutes silently. A nightly build with no timeout, a 15-minute cron that could be hourly, and the one-line discipline that fixes both.
upload-artifact keeps files 90 days by default (set retention-days)
Every actions/upload-artifact without retention-days keeps its files up to 90 days: build zips and test logs billed as storage for a quarter year. How to size retention to an artifact's real lifetime, with real repo examples.
Matrix math: when one push quietly fans out into 25 jobs
GitHub Actions matrices multiply: OS x version x arch turns one push into dozens of billable jobs. How to compute your expansion, when a big matrix is correct (sharp's 25 legs are), the slim-PR/full-main split, and fail-fast tradeoffs.
Caching JS dependencies in Actions: npm vs pnpm vs Yarn vs bun
One line each, but a different line per package manager. The pnpm ordering trap (pnpm/action-setup before setup-node), Yarn Classic vs Berry, why setup-bun caches nothing, and the node_modules mistake all four share.
Gate your CI on config waste (a ratchet for GitHub Actions hygiene)
Config waste creeps back unless something fails. A ~15-line scheduled workflow gates on your public scorecard's JSON: fail when findings grow, ratchet the threshold down as you fix. Coverage-threshold thinking, applied to CI config.
Your workflow runs twice on every PR (push + pull_request duplicate runs)
on: [push, pull_request] with no branch scoping runs your whole workflow twice on the same commit for any branch with an open PR. The branches-filter fix, the fork exception, and a real repo that deliberately runs both.
Flaky tests in GitHub Actions: how to detect them and stop paying for them
Flaky tests hide as rerun-until-green clicks and slowly climbing failure rates. How to detect them (rerun counts, 30-day failure rate), why retries are a diagnostic not a cure, and the fix patterns for the tests underneath.