ci(runners): move every job to the 1-vCPU ubuntu-slim runner - #1190
Merged
Conversation
Nothing this repository runs in CI is heavy. The slowest job on the 4-vCPU image is `prek` at 131s; the rest land between 3s and 99s. Paying for four cores to run a YAML linter and a 20-second pytest suite is waste on infrastructure the foundation shares. `ubuntu-slim` is GitHub-hosted (1 vCPU, 5 GB), not an ASF self-hosted label, so it needs no Infra ticket — and 114 workflow files across the `apache` org already use it. Jobs run in a container rather than a dedicated VM and are killed at 15 minutes. Measured against that budget the slowest job here uses 15% of it, so the headroom is real even after the single-core slowdown. Two consequences worth recording. `codeql.yml` gives up its `ubuntu-24.04` pin along with the four cores; its Python analysis is the one job here that is genuinely CPU- and memory-bound, so it is the first place to look if a run starts timing out. And no workflow sets `timeout-minutes`, which makes slim's 15-minute kill the effective timeout everywhere — stricter than the 6-hour default it replaces, and appropriate for a repo where every job finishes inside two minutes. Generated-by: Claude Code (Opus 5)
`zizmorcore/zizmor-action` is a composite action whose `action.sh` runs the tool with `docker pull` + `docker run`, and it aborts outright — "Cannot run this action without Docker" — when the daemon is absent. `ubuntu-slim` jobs are themselves containers and have no daemon, so the job died before zizmor was ever invoked. Declaring `zizmor` in the root `[dependency-groups] dev` and calling `uv run zizmor` removes the dependency on Docker entirely, and brings three things the action could not: - the version is resolved into the root `uv.lock` (1.30.0) and governed by the `[tool.uv] exclude-newer` cooldown, like every other pinned tool here, instead of being a floating tag inside a container image; - `uv run zizmor --config .zizmor.yml .` reproduces CI locally, which the Docker path only did for contributors with a working daemon; - one fewer third-party action in a workflow whose entire purpose is auditing third-party actions. Behaviour is unchanged where it matters. `--persona regular` is the action's default, and `advanced-security: false` already meant no SARIF upload, so the console-plus-exit-code contract is the same. The action defaults its `token` input to `github.token`, so online audits were already enabled; `GH_TOKEN` in the run step keeps them enabled rather than silently dropping to offline mode. `uv sync` uses `--no-install-workspace`: zizmor imports nothing from this repo, so building ~34 member packages to run it would be pure cost on a 1-vCPU runner. Verified locally against the whole tree — no findings, 15 suppressed. Generated-by: Claude Code (Opus 5)
potiuk
force-pushed
the
worktree-curious-hugging-hinton
branch
from
September 9, 2026 23:07
a17f7dc to
1b41144
Compare
The `typos` hook was the one job that would not survive the move to
`ubuntu-slim`. It failed as a bare `- exit code: 1` with no output,
which reads like a hook that lost its error message; it is really an
OOM kill, and prek has no exit code to report for a signal-killed
process.
typos' peak RSS scales with the number of paths handed to a single
invocation — about 1.2 MB each — and prek splits the file list across
roughly `cpu_count` invocations. Measured on this repo's ~4.9k tracked
files, in a 1-vCPU `ubuntu:24.04` container (what `ubuntu-slim` is):
610 paths 422 MB
1219 paths 925 MB <- the 4-vCPU chunk; fits, hence green on
ubuntu-latest
2438 paths 2514 MB
4876 paths 5754 MB <- the 1-vCPU chunk; over the runner's memory,
SIGKILL, no stdout, no stderr
walk mode 21 MB
`pass_filenames: false` plus a trailing `.` makes the hook walk the
repo itself — the shape the `lychee` hook below already uses — for a
flat ~21 MB whatever the core count. Coverage is unchanged: typos
honours .gitignore while walking, and this checkout has no untracked
non-ignored files. `.venv/` joins .gitignore for the same reason;
uv already writes a `*` .gitignore inside it, so git behaved either
way, but the walk should not depend on that.
Note that this busts the prek hook-env cache key. The `prek-Linux-`
restore-key prefix still restores the previous archive, so no hook env
is rebuilt from scratch.
Generated-by: Claude Code (Opus 5)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Nothing this repository runs in CI is heavy. Measured on the current
4-vCPU image:
prekanalyze (python)/(actions)sandbox-lintratpytest (dev)/(vetted-ops)validate skills and tool contractslist-workspace-memberstests-okPaying for four cores to run a YAML linter and a 20-second pytest suite
is waste on infrastructure the foundation shares.
ubuntu-slimis GitHub-hosted (1 vCPU, 5 GB) rather than an ASFself-hosted label, so it needs no Infra ticket — and 114 workflow files
across the
apacheorg already use it. Jobs run in a container instead ofa dedicated VM and are killed at 15 minutes; the slowest job here uses 15%
of that budget, so the headroom survives the single-core slowdown.
Two jobs needed a fix to survive the move
zizmorran through a Docker action.zizmorcore/zizmor-action'saction.shruns the tool withdocker pull+docker runand abortswith "Cannot run this action without Docker";
ubuntu-slimjobs arethemselves containers with no Docker daemon, so the job failed before
zizmor was ever invoked. The CLI now comes from the root uv workspace's
devgroup, which also puts its version under the lockfile and the[tool.uv] exclude-newercooldown, same as prek. This supersedes #1167'spin bump of that action, which the rebase dropped.
typoswas OOM-killed. It reported a bare- exit code: 1with nooutput, which reads like a hook that lost its error message — but prek has
no exit code to report for a signal-killed process. typos' peak RSS scales
with the number of paths handed to a single invocation (~1.2 MB each), and
prek splits the file list across roughly
cpu_countinvocations. Measuredon this repo's ~4.9k tracked files, in a 1-vCPU
ubuntu:24.04container(which is what
ubuntu-slimis):So the hook fit comfortably on four cores and went past the runner's
memory on one.
pass_filenames: falseplus a trailing.makes typoswalk the repo itself — the shape the
lycheehook already uses — for aflat ~21 MB whatever the core count. Coverage is unchanged: typos honours
.gitignore while walking, and this checkout has no untracked non-ignored
files.
.venv/joins .gitignore for the same reason.Three consequences worth flagging for review:
codeql.ymlgives up itsubuntu-24.04pin along with the fourcores. Its Python analysis is the one genuinely CPU- and memory-bound
job here, so it's the first place to look if a run starts timing out.
Happy to leave that workflow pinned and on the fat runner if reviewers
prefer.
timeout-minutes, so slim's 15-minute kill becomesthe effective timeout everywhere — stricter than the 6-hour default it
replaces, and appropriate for a repo where every job finishes inside two
minutes.
uv tool install prekis unpinned, sopre-commit.ymltrackswhatever prek is latest at run time. Not introduced here, but the typos
diagnosis leaned on knowing the version, so it's worth a follow-up.
🤖 Generated with Claude Code
https://claude.ai/code/session_01R3wLTXcKFLKiZE992K5UHr