ci-timing

Measure how long GitHub Actions jobs and steps took across past runs, and find the pull request that made CI slower. Use for any question about CI duration, a slow job, or when CI got slow.

SKILL.md

GitHub

CI Timing

ci-times.mjs reads run, job and step timings from the GitHub API with gh. Run it with mise's Node, and redirect its output to a file in scratchpad/: a sweep over a month makes hundreds of API calls.

Find When a Job Got Slower

Sweep the runs on main, one row per run, oldest first:

mise exec -- node .claude/skills/ci-timing/ci-times.mjs \
  --since 2026-09-01 --job 'Test \(O|E2E\+stdlib' --step stdlib \
  > scratchpad/ci-times.tsv

Jobs are named by what they hold, so a rebalance renames them. A sweep across one names both: the level jobs were Test (E2E+stdlib O2) before 2026-10-30 and Test (O2) after.

Each matched job prints as name=STEP/JOB in seconds. - means the step did not run or there was no --step. The row ends with the run's title, which names the merged pull request. Look for the row where a job's total steps up and stays up.

Only runs on main from push events give a clean timeline: each one is a single merge. The defaults are --workflow ci.yml --branch main --event push.

Find Which Step Grew

The job total can grow while the step you guessed stays flat. A step that a pull request added is invisible to --step. Print every step of the runs on either side of the jump and compare them:

mise exec -- node .claude/skills/ci-timing/ci-times.mjs --sha <before> --job 'Test \(O3\)|stdlib O3'
mise exec -- node .claude/skills/ci-timing/ci-times.mjs --sha <after>  --job 'Test \(O3\)|stdlib O3'

--run <run id> does the same for a run that is not on main, such as a pull request's run.

Read the Numbers

  • Hosted runners vary from run to run. Several runs on each side of a jump show a real change. A single run does not.
  • The slowest job sets how long CI takes. A step that grew in a job that finishes early does not slow CI down.
  • A test step grows as tests are added. Compare its growth with the growth in the count of what it runs (wado-compiler/tests/fixtures/*.wado, test blocks under wado-compiler/lib/) before calling it a regression.