mirror of
https://github.com/redwoodjs/local-ci.git
synced 2026-09-19 07:54:29 +08:00
fix/immutable-node-modules-snapshots
2 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
ef2ee43835 |
Catch any missing tool in runner image hint (#231)
* fix: skip orphan cleanup when running inside a Docker container
When agent-ci runs nested inside a container (e.g. smoke-bun-setup step 8),
it shares the host's Docker socket. killOrphanedContainers() checks
agent-ci.pid labels using process.kill(pid, 0), but host PIDs don't
exist in the container's PID namespace — so every container looks like
an orphan. This caused the nested agent-ci to force-remove its own
parent container (exit 137).
Both pruneOrphanedDockerResources() and killOrphanedContainers() now
bail out when /.dockerenv exists.
Fixes #228
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: ignore inherited AGENT_CI_DTU_HOST inside containers
When agent-ci runs nested inside a container (e.g. smoke-bun-setup),
the outer container's AGENT_CI_DTU_HOST=host.docker.internal is
inherited. The nested agent-ci used this to tell the inner container
where the DTU is, but the nested DTU is inside the outer container,
not on the host. The inner container got "Connection refused" trying
to reach host.docker.internal:PORT.
Now when /.dockerenv exists, AGENT_CI_DTU_HOST is ignored and the
container's own IP (via hostname -I) is used instead, so sibling
containers can reach the DTU.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: move /.dockerenv guard to call site so tests still work
The /.dockerenv check inside killOrphanedContainers() broke the
shutdown integration tests — they run inside a Docker container (the
test runner) and need the function to work. Moved the guard to the
session bootstrap in cli.ts where the nested agent-ci problem occurs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: add global concurrency limiter across all workflows
In --all mode, each workflow created its own per-wave limiter, allowing
20+ containers to run simultaneously and exhaust available memory (OOM
kills with exit 137). Now a single global limiter (CPU/2) is created in
the orchestrator and shared by all handleWorkflow calls, including
single-job workflows and cold-cache first jobs.
Closes #225
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: factor Docker VM memory into concurrency limit
CPU-based limit alone (cpuCount/2 = 7) still causes OOM kills. Now
reads MemAvailable from /proc/meminfo inside the Docker VM and caps
at floor(available / 3GB per container). Falls back to docker info
with a 4GB reserve if busybox isn't available.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: guard orphan cleanup in the function, not just the call site
The /.dockerenv guard was only in cli.ts, but killOrphanedContainers
is also called directly by the Docker integration tests (via a spawned
tsx subprocess). Inside a container, the test's subprocess would see
the parent container's PID label, misidentify it as an orphan, and
kill the container running the tests.
Put the guard back in both functions AND keep the cli.ts guard.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: increase per-container memory estimate to 4 GB
3 GB per container wasn't enough — tests.yml (vitest + Docker
integration tests) and smoke-binary.yml (full build) both got killed
at 3 concurrent containers. 4 GB gives 2 concurrent containers on a
12 GB Docker VM, with ~5.4 GB each.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: mock fs.existsSync in shutdown unit tests for /.dockerenv guard
The unit tests mock execSync but not fs. Inside a runner container,
the real fs.existsSync("/.dockerenv") returns true, causing
killOrphanedContainers to bail before reaching the mocked execSync.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: skip Docker integration tests for orphan cleanup inside containers
The integration tests spawn a real killOrphanedContainers() subprocess.
Inside a container, the function bails due to /.dockerenv (PID namespace
mismatch), so the tests can't exercise it. Skip them with insideDocker().
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add --jobs flag and document concurrency
Adds -j/--jobs <n> to override the auto-detected concurrency limit.
Adds a Concurrency section to the README explaining how the limit is
calculated and how to override it.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: catch any missing tool in runner image hint, add Nix recipe and docs
Closes #229
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Revert "feat: catch any missing tool in runner image hint, add Nix recipe and docs"
This reverts commit
|
||
|
|
66ac2a4b6b |
test: smoke repro for missing cc in runner image (#207)
* test: add smoke repro for missing cc in runner image Minimal smoke workflow that calls `command -v cc` and compiles a trivial C program. Reproduces a cargo/Rust workflow failure where `linker 'cc' not found` breaks builds under agent-ci-dev because ghcr.io/actions/actions-runner:latest does not ship build-essential. CI-only change (no packages/ code modified) — no changeset. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: pluggable runner image via .github/agent-ci.Dockerfile (#208) agent-ci now discovers a user-provided Dockerfile at .github/agent-ci.Dockerfile (or .github/agent-ci/Dockerfile for builds with a COPY context), hashes its contents, builds it locally via `docker build`, and uses the resulting agent-ci-runner:<hash> tag as the default runner image. Edits trigger automatic rebuilds; identical contents reuse the cached image. This closes the gap where the minimal ghcr.io/actions/actions-runner image lacks build-essential, python3, and other toolchains that GitHub's hosted ubuntu-latest VM ships preinstalled. Workflows green on GitHub but failing locally with `linker 'cc' not found` can now opt into a richer image by dropping a 5-line Dockerfile into .github/. Resolution order (highest wins): 1. per-job `container:` (unchanged) 2. AGENT_CI_RUNNER_IMAGE env var 3. .github/agent-ci/Dockerfile (directory form, supports COPY) 4. .github/agent-ci.Dockerfile (simple form, empty context) 5. ghcr.io/actions/actions-runner:latest (default) Also adds an error-hint heuristic: when a step fails with "command not found" for cc/gcc/make/python3/pkg-config and the user is still on the default image, the failure summary includes a paste-ready Dockerfile pointing at the fix. Docs at packages/cli/runner-image.md. Dogfoods the feature by shipping .github/agent-ci.Dockerfile for this repo, which makes smoke-cc-compiler.yml (the issue #208 reproduction) pass end-to-end. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: announce first-run runner image build Print a one-time stderr notice before `docker build` fires so users understand why the first run pauses for ~60s. The message lives in stderr so log-update can't clobber it and stays in scrollback after. Docs updated to match. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * docs: clarify that container: runs verbatim, no Dockerfile layering Spell out explicitly that a job-level container: directive bypasses .github/agent-ci.Dockerfile entirely — agent-ci does not layer the Dockerfile on top. This preserves the "same YAML runs locally and on GitHub" parity promise. Also document the two recommended ways to combine a custom base image with agent-ci's extras. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |