Written for the other machine, which asked. Everything in it was read off the running host rather than remembered. Also adds docker/ci/ -- the CI image recipe and a capped runner -- because the image existed on exactly one host and its Dockerfile was in a scratch directory under /tmp, which was swept. That is the same shape as every other thing this consolidation has turned up: something correct that exists in one place. docker/ci/Dockerfile rust 1.98.1 + the apt list copied from ci.yml docker/ci/Dockerfile.ffmpeg + ffmpeg, which sylpheed-export shells out to docker/ci/run 6 CPUs / 7 GB / NO SWAP, named cargo volumes The rule the runner exists to enforce: every heavy command goes in the capped container. CARGO_BUILD_JOBS caps codegen units, not rustc's threads, not the linker, not the test harness -- a bare host build is unbounded and has frozen this box repeatedly. The document also records the two agent defects the other machine will meet: a brief change does not reach a RESUMED session, and nothing brought an agent back to its own red PR (fixed in #24, which is itself subject to the first). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
44 lines
1.7 KiB
Bash
Executable File
44 lines
1.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Run a command against this repository inside the capped CI container.
|
|
#
|
|
# docker/ci/run cargo check --workspace --all-targets
|
|
# docker/ci/run cargo clippy --workspace --all-targets --keep-going -- -D warnings
|
|
# docker/ci/run bash -c 'cargo fmt --all; cargo fmt --all -- --check | grep -c "^Diff in"'
|
|
#
|
|
# 🔴 EVERY HEAVY COMMAND GOES THROUGH HERE. A bare `cargo build` on the host is
|
|
# unbounded: `CARGO_BUILD_JOBS` caps codegen units, not rustc's own threads, not
|
|
# the linker, not the test harness. A full-parallel build has OOM-crashed this
|
|
# box, and unbounded host runs have frozen it since. The container is the cap
|
|
# that actually holds.
|
|
#
|
|
# Half the machine, no swap. `--memory-swap` equal to `--memory` means a build
|
|
# that would swap is killed instead, which is a fast failure rather than an
|
|
# hour of thrashing that takes the desktop with it.
|
|
set -euo pipefail
|
|
|
|
REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
IMAGE="${SYLPH_CI_IMAGE:-sylph-ci:local}"
|
|
CPUS="${SYLPH_CI_CPUS:-6}"
|
|
MEM_GB="${SYLPH_CI_MEM_GB:-7}"
|
|
|
|
args=(
|
|
--rm
|
|
--cpus "$CPUS"
|
|
--memory "${MEM_GB}g"
|
|
--memory-swap "${MEM_GB}g"
|
|
--pids-limit 2048
|
|
-v "$REPO:/work"
|
|
# Named volumes, not bind mounts: the host tree keeps a 32 GB `target/` from
|
|
# earlier host-side builds, and mixing the two produces rebuilds that look
|
|
# like cache misses and are actually two toolchains fighting over one directory.
|
|
-v sylph-ci-cargo:/cargo -e CARGO_HOME=/cargo
|
|
-v sylph-ci-target:/target -e CARGO_TARGET_DIR=/target
|
|
-w /work
|
|
)
|
|
|
|
# The disc, read-only, when a disc-backed test or the exporter needs it.
|
|
DISC="${SYLPHEED_DISC:-$REPO/../sylph_extract}"
|
|
[ -d "$DISC" ] && args+=(-v "$DISC:/disc:ro" -e SYLPHEED_DISC=/disc)
|
|
|
|
exec docker run "${args[@]}" "$IMAGE" "$@"
|