# Phase 2w / WC6 — nightly full-cold sweep. A systemd TIMER fires nightly and runs # `runner/nightly_sweep.py`: roll warm/infra (keycloak+traefik) to latest health-gated (WC1.1) THEN # a SERIAL full-cold run across enrolled (WARM_CANONICAL) recipes on latest — each green run # promotes/refreshes that recipe's canonical (WC5), serving as the daily authoritative regression. # Serial = MAX_TESTS honored (one at a time); skips itself if a test is already in flight. Declarative # + reproducible (runner/ packaged in the nix store, D8-clean). { pkgs, ... }: let runnerSrc = ../../runner; # The sweep drives run_recipe_ci.py (pytest/playwright) — needs the full harness env like cc-ci-run. pyEnv = pkgs.python3.withPackages (ps: with ps; [ pytest playwright ]); sweep = pkgs.writeShellApplication { name = "cc-ci-nightly-sweep"; # util-linux provides `script` (abra's PTY wrapper for backup/restore TTY ops) — same as cc-ci-run. runtimeInputs = with pkgs; [ abra docker git curl jq gnused gnugrep gnutar coreutils util-linux procps ]; text = '' export HOME=/root export PLAYWRIGHT_BROWSERS_PATH=${pkgs.playwright-driver.browsers} export PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 exec ${pyEnv}/bin/python3 ${runnerSrc}/nightly_sweep.py ''; }; in { systemd.services.nightly-sweep = { description = "Phase-2w nightly: roll warm/infra (health-gated) + full-cold sweep over canonicals"; after = [ "deploy-proxy.service" "warm-keycloak.service" "docker.service" ]; environment.HOME = "/root"; serviceConfig = { Type = "oneshot"; # A full sweep across several recipes (each a cold deploy/test/teardown) is long; bound it. TimeoutStartSec = "21600"; # 6h ceiling ExecStart = "${sweep}/bin/cc-ci-nightly-sweep"; }; }; systemd.timers.nightly-sweep = { description = "Nightly trigger for the Phase-2w full-cold canonical sweep (WC6)"; wantedBy = [ "timers.target" ]; timerConfig = { OnCalendar = "*-*-* 03:00:00"; Persistent = true; # catch up a missed nightly after downtime RandomizedDelaySec = "600"; }; }; }