docs(agents): how the containers and agents are actually set up
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>
This commit is contained in:
33
docker/ci/Dockerfile
Normal file
33
docker/ci/Dockerfile
Normal file
@@ -0,0 +1,33 @@
|
||||
# The CI image, reproduced locally.
|
||||
#
|
||||
# 🔴 WHY THIS FILE EXISTS. This image was built once, by hand, from a Dockerfile
|
||||
# in a scratch directory under /tmp — and /tmp was swept. The image survived on
|
||||
# one host and its recipe did not, which is the same shape as every other thing
|
||||
# this consolidation found: something correct that exists in exactly one place.
|
||||
#
|
||||
# The apt list below is COPIED from `.github/workflows/ci.yml`'s "Install Linux
|
||||
# system dependencies" step. If that list changes, this must change with it, or
|
||||
# a local run stops predicting the runner.
|
||||
#
|
||||
# docker build -t sylph-ci:local docker/ci
|
||||
#
|
||||
# ⚠️ The Rust version is PINNED and the runner's is NOT — `dtolnay/rust-toolchain@stable`
|
||||
# floats. That difference is issue #15: `collapsible_else_if` is `warn` on 1.92
|
||||
# and `allow` on 1.98.1, so a local clippy pass and a runner clippy pass can
|
||||
# legitimately disagree. When they do, the runner is the authority.
|
||||
FROM rust:1.98.1-bookworm
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
libasound2-dev \
|
||||
libudev-dev \
|
||||
libwayland-dev \
|
||||
libxkbcommon-dev \
|
||||
libx11-dev \
|
||||
libxi-dev \
|
||||
pkg-config \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN rustup component add clippy rustfmt \
|
||||
&& rustup target add wasm32-unknown-unknown
|
||||
|
||||
WORKDIR /work
|
||||
11
docker/ci/Dockerfile.ffmpeg
Normal file
11
docker/ci/Dockerfile.ffmpeg
Normal file
@@ -0,0 +1,11 @@
|
||||
# `sylph-ci:ffmpeg` — the CI image plus ffmpeg, for `sylpheed-export`.
|
||||
#
|
||||
# The exporter shells out to `ffprobe`/`ffmpeg` to transcode the two movies, so
|
||||
# `cargo run -p sylpheed-export -- export` fails in the plain CI image with
|
||||
# "run ffprobe -- is it on PATH?". CI itself never runs the exporter, which is
|
||||
# why its own image does not carry this.
|
||||
#
|
||||
# docker build -t sylph-ci:ffmpeg -f docker/ci/Dockerfile.ffmpeg docker/ci
|
||||
FROM sylph-ci:local
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends ffmpeg \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
43
docker/ci/run
Executable file
43
docker/ci/run
Executable file
@@ -0,0 +1,43 @@
|
||||
#!/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" "$@"
|
||||
Reference in New Issue
Block a user