---
title: "GitHub Actions CI best practices: make CI faster, with YAML"
description: "Make GitHub Actions CI faster and cheaper: best practices for caching, sharding, path filters, concurrency, queue time, and security, with copyable YAML."
url: https://starsling.dev/best-practices/github-actions
canonicalUrl: https://starsling.dev/best-practices/github-actions
---

# GitHub Actions CI best practices

Practical, copyable ways to make your GitHub Actions CI faster, leaner, and cheaper: caching, sharding, scoped build and test, path filters, concurrency, and queue time, plus the security practices (SHA pinning, per-job OIDC) that keep a fast pipeline safe. One reference page each, with good and bad YAML and how to verify it on your own repo.

## Hand your whole CI to an agent

Paste this into your coding agent to audit your repo against every practice below and open a reviewable PR for each gap:

Audit this repository's GitHub Actions CI against StarSling's best-practices catalog and fix what's missing. Start by reading the machine-readable index at https://starsling.dev/best-practices/github-actions.md, then read each per-practice page it links (at https://starsling.dev/best-practices/github-actions/<slug>.md) so you have the full guidance for every practice. Go through this repo's .github/workflows and check them against each practice: dependency caching, shallow checkout, test sharding, building and testing only what changed, path filters, cancelling superseded runs with concurrency groups, keeping advisory checks off the critical path, queue time, pinning actions to commit SHAs, and scoping id-token write to the publishing job. For every gap, apply the fix following that practice's page and respect its guardrails (for example, keep a full-run fallback when scoping to changed files, and never de-scope a check that runs real tests). Show me the diff and open a PR for each change rather than applying anything blindly, and skip any practice that genuinely does not apply to this repo, noting why.

## Caching & Setup

- [Cache dependencies in GitHub Actions](https://starsling.dev/best-practices/github-actions/cache-dependencies): Cache your package manager's downloads so CI restores dependencies from a keyed cache instead of reinstalling them from scratch on every run.
- [Use a shallow checkout in GitHub Actions](https://starsling.dev/best-practices/github-actions/shallow-checkout): Let `actions/checkout` fetch only the commit under test (its default `fetch-depth: 1`) instead of the whole git history, and reach for `fetch-depth: 0` only when a job genuinely needs history.

## Parallelization

- [Shard tests across parallel jobs in GitHub Actions](https://starsling.dev/best-practices/github-actions/shard-tests): Split one long test job into parallel shards with a matrix so the suite finishes in a fraction of the wall-clock time.
- [Build and test only what changed in GitHub Actions](https://starsling.dev/best-practices/github-actions/build-only-affected): Scope your slowest build/test job to only the packages a PR actually changed, using your monorepo tool's affected mode, with a mandatory full-run fallback so a resolution error never silently skips work.

## Trigger Scope

- [Filter workflows by path in GitHub Actions](https://starsling.dev/best-practices/github-actions/path-filter-workflows): Add `paths` or `paths-ignore` to expensive workflows so a docs-only or unrelated change doesn't trigger the full test suite.
- [Cancel superseded runs with concurrency groups](https://starsling.dev/best-practices/github-actions/cancel-superseded-runs): Add a GitHub Actions `concurrency` group scoped to the ref with `cancel-in-progress: true`, so a new push cancels the now-obsolete run instead of leaving both to occupy runners.

## Required-check Hygiene

- [Keep advisory checks off the critical path](https://starsling.dev/best-practices/github-actions/keep-advisory-checks-non-blocking): When a slow GitHub Actions check sits on the PR critical path but isn't required to merge and only produces advisory output (a size comment, a preview), narrow its trigger or make it async, but never de-scope a check that actually runs tests.

## Runner & Queue

- [Cut CI queue time in GitHub Actions](https://starsling.dev/best-practices/github-actions/cut-queue-time): GitHub-hosted runners cap how many jobs your account can run at once (20 on Free, more on paid plans), so past that ceiling jobs queue for a free slot no matter how your workflows are written. Measure the wait from a run being triggered to its job starting, then cut it by fixing over-restrictive concurrency groups or moving to runners with more available concurrency.

## Security

- [Pin GitHub Actions to commit SHAs](https://starsling.dev/best-practices/github-actions/pin-action-shas): Reference every third-party action by its full 40-character commit SHA (with the version as a trailing comment), not a mutable `@v4` tag or `@main` branch that its maintainer, or an attacker, can re-point.
- [Scope id-token: write to the publishing job](https://starsling.dev/best-practices/github-actions/scope-id-token-per-job): In GitHub Actions, declare `id-token: write` in the specific publishing job's `permissions:` block, never at the workflow's top level, so an OIDC publish token isn't minted for jobs that run untrusted code.

## FAQ

### What are the most important GitHub Actions CI best practices?

The highest-impact ones are caching dependencies so installs don't repeat every run, sharding long test suites across parallel jobs, scoping expensive workflows with path filters, cancelling superseded runs with a concurrency group, and hardening security by pinning actions to commit SHAs. Each has its own page here with copyable YAML.

### How is this catalog organized?

Practices are grouped into the six categories the StarSling CI Score uses: Caching & Setup, Parallelization, Trigger Scope, Required-check Hygiene, Runner & Queue, and Security. Every page shows what good looks like, a good/bad YAML pair, and how to verify the practice on your own repo.

### Do I have to use StarSling to apply these?

No. Every practice is a change you can make to your own GitHub Actions workflows by hand, and each page includes the verify steps to check it. StarSling's agents automate the same fixes by opening reviewable PRs, but the practices stand on their own.

Last updated: 2026-07-06
