Where the forty minutes actually goes
Before optimising a pipeline, measure it — not the total, but each stage, across at least thirty runs. The average lies; the distribution tells you whether you have a slow pipeline or a flaky one.
The four usual suspects
- Dependency resolution without a warm cache. Caching that is configured but never hits is the most common finding. Check the hit rate, not the config.
- Serial stages that have no dependency on each other. Lint, unit tests and image builds frequently run in sequence for no reason beyond the order they were added.
- Image builds that invalidate on the first layer. A
COPY . .before the dependency install means every commit rebuilds the world. - Waiting for a runner. If queue time is a third of your total, no amount of stage optimisation helps. Fix concurrency first.
What to do with the numbers
Rank changes by minutes saved per hour of work. It is normal for the top two changes to account for most of the gain, and it is normal for one of them to be a configuration line rather than an architectural change.
This note reflects work in progress. If your pipeline has a shape not covered here, I am interested in hearing about it.