Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
4.2 KiB
STATUS — phase nixenv (Builder)
Phase plan: /srv/cc-ci/cc-ci-plan/plan-phase-nixenv-shared-runtime-env.md
Phase
Single-source the harness/recipe-test runtime env so the Drone runner, the nightly/weekly sweep
timer, and host systemPackages share ONE declaration (no duplicate pyEnv, no divergent
runtimeInputs, DEFECT-3 host-PATH patch removed/subsumed).
Gate: M1 — CLAIMED, awaiting Adversary
WHAT (M1 DoD). The harness/recipe-test runtime env is declared ONCE and referenced by all
consumers; nixos-rebuild build succeeds for both hosts; the shared set is superset-or-equal of
every prior list (nothing dropped); the sweep and the Drone runner resolve the same tooling; a
future dep added to the shared set reaches all consumers.
WHERE (inputs). All changes at the tip of main (commit pushed with this claim).
- Single source:
nix/modules/packages.nix— overlay definesccciPyEnv(let),ccciRuntimeTools(overlay attr),cc-ci-run(overlay attr,runtimeInputs = [ccciPyEnv] ++ ccciRuntimeTools). - Consumers:
nix/modules/harness.nix(systemPackages = [ pkgs.cc-ci-run ]),nix/modules/nightly-sweep.nix(wrapper execscc-ci-run),nix/hosts/cc-ci/configuration.nix+nix/hosts/cc-ci-hetzner/configuration.nix(systemPackages = pkgs.ccciRuntimeTools ++ [ pkgs.openssh ]). nix/modules/drone-runner.nixunchanged (stillPATH=/run/current-system/sw/bin:/run/wrappers/bin; it consumes the host PATH, which now references the shared set).
HOW + EXPECTED (cold-verifiable; secrets/ is a git submodule → use ?submodules=1 for a dirty
tree, or build from a git clone --recursive).
-
Builds succeed (both hosts):
nixos-rebuild build --flake '.?submodules=1#cc-ci-hetzner'→ buildsnixos-system-nixos-24.11.…(locally:/nix/store/dhmpm232r6m0sq3s7y5r5jpyv5kxgzwi-nixos-system-nixos-24.11.20250630.50ab793; store hash may differ on a fresh clone if paths differ, but it MUST build with no collision error).nixos-rebuild build --flake '.?submodules=1#cc-ci'→ builds OK (no collision error).
-
Single source (grep proofs):
grep -rn withPackages nix/→ EXACTLY 1 hit:nix/modules/packages.nix(ccciPyEnv).grep -rn "pytest playwright" nix/→ EXACTLY 1 hit: same line. (No duplicate pyEnv.)grep -rn ccciRuntimeTools nix/→ defined once (packages.nix), referenced by both host configs.nightly-sweep.nixcontains NOwithPackages, NOpython3, NO/run/current-system/sw/binPATH prepend, and itsruntimeInputs = [ pkgs.cc-ci-run ]only; itexec cc-ci-run ….
-
Superset-or-equal —
cc-ci-runcarries every tool (inspect the built wrapper's PATH):CCRUN=$(nix eval --raw '.?submodules=1#nixosConfigurations.cc-ci-hetzner.pkgs.cc-ci-run'); grep '^export PATH' "$CCRUN/bin/cc-ci-run"- EXPECTED store dirs on PATH (15): python3-3.12.8-env, abra-0.13.0-beta, docker-27.5.1, git-2.47.2, git-lfs-3.6.1, bash-5.2p37, coreutils-9.5, util-linux-2.39.4, curl-8.12.1, jq-1.7.1, gnused-4.9, gnugrep-3.11, gnutar-1.35, openssl-3.3.3, procps-4.0.4.
- git-lfs + openssl are the additions vs prior lists; nothing from any prior list is dropped.
-
Sweep ≡ Drone entrypoint (parity by construction):
- The built
cc-ci-nightly-sweepwrapperexec cc-ci-run …resolves the BYTE-IDENTICAL cc-ci-run store path that the.drone.ymlcc-ci-run runner/run_recipe_ci.pystep runs (locally/nix/store/zxlx9jnylh7la5m48bsqb1wfm5l9r0bd-cc-ci-run). Same store path ⇒ same pyEnv, same tooling, same PLAYWRIGHT_BROWSERS_PATH.
- The built
-
Host divergence removed:
- Both host
configuration.nixsystemPackageslines are textually identical (pkgs.ccciRuntimeTools ++ [ pkgs.openssh ]). Thecc-cihost now GAINSgit-lfs+opensslon its system PATH (ls $(nix eval --raw '.?submodules=1#nixosConfigurations.cc-ci.config.system.build.toplevel')/sw/bin/ | grep -E '^(git-lfs|openssl)$'→ both present; pre-refactor cc-ci lacked git-lfs).
- Both host
-
Future-dep propagation: adding a pkg to
ccciRuntimeToolsin packages.nix lands in cc-ci-run's runtimeInputs (Drone + sweep) AND both hosts' systemPackages from the single edit.
Build backlog
See BACKLOG-nixenv.md. M2 (deploy + live parity witness) is gated behind the M1 PASS.