Abort fast when the build box's disk can't hold the run - #178
Merged
Conversation
The root NVMe carries the swapfile, the docker image and its overlay writes, TMP merge/tippecanoe scratch and the run logs. Only declared job tmp is bounded by the disk_mb budget, so a wide plan on a small-root box fills the disk out from under the runner itself: the agent dies on "No space left on device: /actions-runner/_diag" and the step never reports a conclusion, after an hour of doomed IO. Scale the swapfile to an eighth of the root disk instead of a flat 64 G so it tracks the box, and refuse to start when free root space is under what the plan's width needs, naming ccx63 as the fix.
The main invocation reruns incomplete outputs, but the dry run refused to plan at all while one existed (IncompleteFilesException on vector-shallow.pmtiles, run 32030051338) — so a crash-recovery dispatch died in the gate that exists to protect it. Mirror --rerun-incomplete into the dry run.
There was a problem hiding this comment.
Pull request overview
This PR hardens the build.yml workflow to fail fast when the selected runner’s root disk is too small for the planned run, and to make crash-recovery dispatches plan successfully instead of failing during the scope gate.
Changes:
- Scale swapfile size to the runner’s root disk (1/8th, capped at 64G) instead of a fixed 64G.
- Mirror
--rerun-incompleteinto the scope-gate dry-run so incomplete marks from prior crashes don’t prevent planning. - Add a root-disk free-space floor (80G narrow / 300G wide) to abort quickly with actionable remediation guidance.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
The gate's dry run executes inside the container and can leave overlay writes behind, so a floor and disk budget measured before it describe space that may no longer exist.
The status close is pure bookkeeping, and its one-shot curl let a single GitHub 503 paint an entirely successful 721-job planet build as a failed run (run 32030835194).
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.
Two dispatches died this weekend to box-sizing failures the workflow could have caught in seconds:
server_type: ccx33(240 GB root disk) with ~8,800 planet jobs remaining. Swap, the docker image, merge scratch, and logs are all sized against the ccx63's 960 GB; the root disk filled in 52 minutes and the runner itself died mid-write (No space left on device: /actions-runner/_diag/...), so the build step never even reported a conclusion.vector-shallow.pmtilesmarked incomplete, the main invocation reruns incomplete outputs, but the dry run carried no--rerun-incompleteand refused to plan at all (IncompleteFilesException).Four changes: one per observed failure mode, plus the shared sizing root, plus a bookkeeping fix from the successful rerun (run 32030835194) whose one-shot status curl let a GitHub 503 paint a fully successful 721-job build as a failed run.
Swapfile scaled to the box
An eighth of the root disk, capped at 64 G. The ccx63 keeps its proven 64 G; a ccx33 gets 30 G instead of spending a quarter of its disk on spill its 32 GB of RAM will rarely reach.
Root-disk floor
The
disk_mbbudget admits only declared job tmp; swap, image layers, run logs, and under-declared scratch sit outside it on the same disk. After the scope gate and before the main invocation, the step now requires 300 G free for wide plans (>2000 planned jobs, or an unstated scope, which is what a planet dispatch looks like) and 80 G for narrow ones. Bbox runs are narrow by construction and keep the loose floor, so ccx33's documented uses (bbox smokes, stated-scope incremental builds) stay open. The abort message names both remedies:server_type=ccx63, or stating a narrow scope withmax_jobs.On the incident's numbers: ccx33 had ~190 G usable after swap and image, and the wide run consumed all of it, so the 300 G floor rejects that dispatch in seconds. The ccx63 clears it roughly 3x over.
Scope gate plans across incomplete marks
--rerun-incompletemirrored into the dry run, so a crash-recovery dispatch is planned (with the incomplete outputs as jobs) instead of dying in the gate that exists to protect it.Status POST retries
The "Publish build status" close is pure bookkeeping; its curl now retries transient API errors (
--retry 5 --retry-all-errors) instead of failing the job over a blip.Validated with actionlint (shellcheck-backed) and the two new shell blocks simulated standalone across ccx63/ccx33 with wide, gated-narrow, and bbox plans.