GitHub Actions workflows
A workflow is code that runs on every change, and it degrades the same way code does: slow, flaky, and full of steps nobody understands. Keeping it fast and comprehensible is what keeps people running it rather than routing around it.
Method
- Trigger on what you actually need. Push to the default branch and pull requests covers most cases; triggering on everything burns minutes and produces duplicate runs on the same commit.
- Filter by path where the repository is mixed. Documentation changes should not run the full test suite, and path filters are the cheapest speed improvement available.
- Cache dependencies deliberately. A correct cache key including the lockfile hash saves most of the run time, and a wrong one serves stale dependencies silently.
- Use a matrix for genuine variation. Operating systems and language versions you support, not every combination that exists, since the matrix multiplies cost.
- Fail fast on cheap checks. Lint and type checks before the long test suite, so an obvious error returns in a minute rather than twenty (see ci-cd).
- Pin actions to a commit, not a tag. A tag can be moved, which makes it an unpinned dependency in a privileged context (see actions-security).
- Keep workflows readable. Named steps, extracted scripts, and reusable workflows for shared logic, because a wall of inline shell is unmaintainable.
Boundaries
Workflows automate checks; they do not replace review judgement. Runner minutes and concurrency are billed and limited, so cost is a real constraint at scale. Complex build logic belongs in scripts the repository can run locally rather than embedded in the workflow.