Skip to content

ci: add swap headroom to ShellCheck job (fixes intermittent OOM) - #100

Merged
aimsise merged 1 commit into
mainfrom
ci/shellcheck-swap-headroom
Jun 28, 2026
Merged

ci: add swap headroom to ShellCheck job (fixes intermittent OOM)#100
aimsise merged 1 commit into
mainfrom
ci/shellcheck-swap-headroom

Conversation

@aimsise

@aimsise aimsise commented Jun 28, 2026

Copy link
Copy Markdown
Owner

Problem

The ShellCheck CI job fails non-deterministically with ##[error]The operation was canceled. — an OOM kill, not a lint finding. (It blocked v10.0.0, which was admin-merged past a real OOM.)

Root cause (measured): shellcheck --severity=warning on tests/test-skill-contracts.sh (~11,671 lines) peaks at ~15-24 GB by itself — all other tests/*.sh + tests/helpers/*.sh combined peak at 287 MB and hooks/*.sh hooks/lib/*.sh at 80 MB. The 16 GB ubuntu-latest runner OOM-kills the agent intermittently. The file lints clean (rc=0, 0 findings); the failure is purely a memory limit. It is check/severity-independent (--severity=error and --exclude=SC2086 both still ~14-24 GB) — shellcheck's core dataflow analysis, super-linear on the monolith.

This is pre-existing: main's version of the file uses even more memory; recent releases passed by luck.

Fix

Add a dedicated 16 GB swapfile before the shellcheck steps (16 GB RAM + ~4 GB default + 16 GB new ≈ 36 GB addressable, covering the worst measured peak). The kernel pages the cold GC copy-space instead of OOM-killing the agent.

  • Both shellcheck --severity=warning steps and their coverage are byte-identical — the lint surface is unchanged.
  • Distinct path /mnt/swapfile-ci avoids the runner image's default swap; fallocate has a dd fallback for filesystems that reject holes.
  • swapon --show + free -h logged for observability.

Verification

  • Local: confirmed the OOM (/usr/bin/time peak ~15-24 GB, rc=0, 0 findings) and that more addressable memory (ulimit -v 32000000 vs 13000000) lets it complete.
  • CI (authoritative): this PR's ShellCheck job is the real test — confirm the swap mounts (swapon --show lists /mnt/swapfile-ci at 16G) and the job goes green reliably across re-runs (the bug is intermittent).

Follow-up (durable, tracked separately)

Split tests/test-skill-contracts.sh so no single file exceeds runner RAM (worst half measured ~6 GB at the category boundary line 6989); then the swap step can be removed.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Mw2bH4wbEPeebXsvSG6rWe

The ShellCheck CI job failed non-deterministically with
`##[error]The operation was canceled.` — an OOM kill, not a lint finding.
shellcheck's core dataflow analysis on tests/test-skill-contracts.sh
(~11,671 lines) peaks at ~15-24 GB by itself (measured; all other test
files combined peak at 287 MB, hooks at 80 MB), exceeding the 16 GB
ubuntu-latest runner intermittently. The file lints clean (rc=0, 0 findings),
so the failure was purely an out-of-memory kill on the agent.

Add a dedicated 16 GB swapfile before the shellcheck steps so the kernel can
page the cold GC copy-space instead of OOM-killing the agent. Both shellcheck
steps and `--severity=warning` are byte-identical; lint coverage is unchanged.
A distinct path /mnt/swapfile-ci avoids the runner image's default swap, and
fallocate has a dd fallback for filesystems that reject holes.

This is a pre-existing fragility (main's version of the file uses even more
memory; recent releases passed CI by luck and v10.0.0 was admin-merged past a
real OOM). Durable follow-up tracked separately: split test-skill-contracts.sh
so no single file exceeds runner RAM (worst half measured ~6 GB).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mw2bH4wbEPeebXsvSG6rWe
@aimsise
aimsise merged commit 3fbd057 into main Jun 28, 2026
4 checks passed
@aimsise
aimsise deleted the ci/shellcheck-swap-headroom branch June 28, 2026 07:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant