Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions scripts/ci/docker/linux-runner/persist/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ n'a pas ete remplacee. Un `git pull` ne deploie pas `persist/`.
| `coursia-runner-start.sh` | **po-2024** | `/usr/local/bin/coursia-runner-start.sh` | reference |
| `launch-runner.sh` | po-2024 | lancement manuel d'un slot | reference |
| `hold-runner.ps1` | po-2024 (hote Windows) | tache planifiee | reference |
| `coursia-lean.service` | **po-2024** | `/etc/systemd/system/coursia-lean.service` | reference |
| `coursia-lean-start.sh` | **po-2024** | `/usr/local/bin/coursia-lean-start.sh` | reference |
| `coursia-waiters.service` | **ai-01** | `/etc/systemd/system/coursia-waiters.service` | reference |
| `coursia-waiters-start.sh` | **ai-01** | `/usr/local/bin/coursia-waiters-start.sh` | reference |
| `coursia-ci.slice` | **ai-01** | `/etc/systemd/system/coursia-ci.slice` | **a deployer** (une version ad-hoc de 283 octets, sans documentation, occupe la place) |
Expand Down
78 changes: 78 additions & 0 deletions scripts/ci/docker/linux-runner/persist/coursia-lean-start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#!/usr/bin/env bash
# Lanceur PERSISTANT du pool LEAN specialise (label coursia-lean).
#
# POURQUOI CE FICHIER EXISTE (incident 2026-09-09)
# -------------------------------------------
# La jambe `lean` n'avait de persistance sur AUCUNE machine : elle etait
# lancee a la main dans une session, et mourait avec elle. Consequence
# mesuree le 2026-09-09 : apres le reboot de po-2024 (restauration
# coursia-runner + coursia-waiters), le pool lean est reste a ZERO toute
# la journee -- aucun runner ne portait le label `coursia-lean`, le run
# main de lean-knot y est mort "runner lost communication" (check-run
# 102437210604), et deux jobs lean de PR sont restes en queue de 12:39Z a
# 15:00Z+ pendant que les runners generaux servaient tout le reste.
# po-2027 a nomme le defaut ; ce fichier le ferme cote po-2024, sur le
# meme pattern que coursia-waiters-start.sh (#14612, #14846).
#
# STATE_DIR DEDIE, ET C'EST LE POINT DELICAT. L'appel manuel d'avant
# l'incident tournait SANS COURSIA_RUNNER_STATE_DIR : supervise.sh
# retombait sur /var/lib/coursia-runner, PARTAGE avec la jambe
# d'execution. Deux consequences mesurees : la sentinelle d'arret etait
# commune (un `systemctl stop coursia-runner` aurait arrete le pool lean
# au passage), et les pid files des deux familles vivaient entremelles.
# D'ou /var/lib/coursia-lean -- la sentinelle et le verrou pid redeviennent
# par-jambe, comme pour les waiters.
#
# LE SECRET NE SE DUPLIQUE PAS : GH_RUNNERS_ADMIN_TOKEN est relu dans
# master.env a chaque demarrage (jamais recopie dans un EnvironmentFile,
# jamais en argv).
set -uo pipefail

MASTER_ENV="${COURSIA_MASTER_ENV:-/mnt/c/dev/CoursIA/.secrets/master.env}"
REPO_DIR="${COURSIA_REPO_DIR:-/mnt/c/dev/CoursIA}"
ARG="${1:-2}"

[ -r "$MASTER_ENV" ] || { echo "master.env illisible : $MASTER_ENV" >&2; exit 1; }

GH_TOKEN="$(sed -n 's/^GH_RUNNERS_ADMIN_TOKEN=//p' "$MASTER_ENV" | head -1 | tr -d '"'"'"'\r')"
[ -n "$GH_TOKEN" ] || { echo "GH_RUNNERS_ADMIN_TOKEN absent de master.env -- abandon" >&2; exit 1; }
export GH_TOKEN

# Daemon EPINGLE (meme raison que coursia-runner-start.sh) : sans cela
# l'integration WSL de Docker Desktop rattacherait les conteneurs a la session.
export DOCKER_HOST="${DOCKER_HOST:-unix:///var/run/docker-ce.sock}"

export COURSIA_LEAN_RUNNER_NAME_PREFIX="${COURSIA_LEAN_RUNNER_NAME_PREFIX:-myia-po-2024-lean-docker}"
export COURSIA_RUNNER_STATE_DIR="${COURSIA_RUNNER_STATE_DIR:-/var/lib/coursia-lean}"
mkdir -p "$COURSIA_RUNNER_STATE_DIR"

cd "$REPO_DIR" || exit 1

if [ "$ARG" = "stop" ]; then
exec ./scripts/ci/docker/linux-runner/supervise.sh stop
fi
# --- PURGE SENTINELLE PERIMEE (#15163) -----------------------------
# Meme bloc que coursia-waiters-start.sh, avec le predicat PAR-JAMBE que
# son commentaire annoncait (« un futur supervise.sh lean prendra son
# propre predicat ») : `supervise\.sh lean`. Un predicat global ferait
# que chaque jambe refuserait de purger SA sentinelle tant qu'une AUTRE
# tourne -- un verrou par jambe garde par un test global ne garde rien.
if [ -e "$COURSIA_RUNNER_STATE_DIR/stop" ]; then
if pgrep -f 'supervise\.sh lean' >/dev/null 2>&1; then
echo "sentinelle presente ET superviseur vivant -- arret en cours, on n'interfere pas" >&2
exit 1
fi
echo "sentinelle perimee (aucun superviseur vivant) -- purge avant demarrage" >&2
rm -f "$COURSIA_RUNNER_STATE_DIR/stop"
fi
# ---------------------------------------------------------------------------
# Les pid files perimes (reboot) ne bloquent pas cmd_lean -- son garde
# teste le pid au kill -0 -- mais un fichier de pids d'un etat anterieur
# n'a aucune valeur : purge defensive coherente avec le rm -f de cmd_lean.
if [ -f "$COURSIA_RUNNER_STATE_DIR/lean-pids" ]; then
head_pid="$(head -1 "$COURSIA_RUNNER_STATE_DIR/lean-pids" 2>/dev/null || true)"
if [ -z "$head_pid" ] || ! kill -0 "$head_pid" 2>/dev/null; then
rm -f "$COURSIA_RUNNER_STATE_DIR/lean-pids"
fi
fi
exec ./scripts/ci/docker/linux-runner/supervise.sh lean "$ARG"
53 changes: 53 additions & 0 deletions scripts/ci/docker/linux-runner/persist/coursia-lean.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Unite systemd de persistance du POOL LEAN specialise (label coursia-lean).
# Troisieme jambe du superviseur, apres coursia-runner.service (execution,
# label coursia-linux) et coursia-waiters.service (attente PR-gate, label
# coursia-waiter). Les trois jambes sont independantes : state dirs distincts
# (/var/lib/coursia-runner, /var/lib/coursia-waiters, /var/lib/coursia-lean),
# sentinelles d'arret distinctes, prefixes de nom distincts.
#
# Deploiement po-2024 (2026-09-09, incident pool lean wedged post-reboot) :
# copie de reference -- l'original vit dans la distro Ubuntu de l'hote, sous
# /etc/systemd/system/coursia-lean.service (systemctl enable --now).
#
# INCIDENT FONDATEUR : le pool lean tournait en appel manuel hors systemd.
# Au reboot du 2026-09-09, les jambes runner+waiters restaurees, la jambe
# lean est restee a ZERO : aucun runner ne portait le label coursia-lean,
# le run main de lean-knot y est mort "runner lost communication"
# (check-run 102437210604), et deux jobs lean de PR sont restes en queue
# toute l'apres-midi (diagnostic po-2027, 14:23Z).
#
# N slots porte par l'argument ExecStart (po-2024 -> 2, l'effectif
# d'avant la chute : volumes _work chauds coursia-runner-work-lean-{1,2}).
[Unit]
Description=CoursIA Lean runners pool (coursia-lean slots)
# Wants= et non Requires= (meme raison que coursia-runner.service, #14347) :
# un docker.service en echec au boot doit retarder le service et le laisser
# retenter, pas le sortir de la liste des unites.
Wants=docker.service
After=docker.service

# #15091 : plafond de redemarrage, calque des deux autres unites.
StartLimitIntervalSec=600
StartLimitBurst=5

[Service]
Type=simple
ExecStart=/usr/local/bin/coursia-lean-start.sh 2
ExecStop=/usr/local/bin/coursia-lean-start.sh stop
Restart=always
RestartSec=30
Nice=10
# Un slot lean porte des lake builds : 900 s comme la jambe d'execution,
# pas 120 s comme les waiters. ExecStop est gracieux (sentinel) : un job
# lake en vol va a son terme.
TimeoutStopSec=900

# Nice=10 gouverne le CPU ; l'I/O du pool cede sous contention comme les
# autres (IOWeight=50), cf #15091. Les caps durs par conteneur (cpus=6,
# memory=8g, memory-swap=24g) sont portes par supervise.sh lui-meme via
# LEAN_CPUS/LEAN_MEMORY/LEAN_MEMORY_SWAP -- l'unite ne les re-encode pas.
IOAccounting=yes
IOWeight=50

[Install]
WantedBy=multi-user.target
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,11 @@ run_case() { # $1 = script de purge ; $2 = STATE_DIR ; $3 = table de processus
return $?
}

for LEG in runner waiters; do
for LEG in runner waiters lean; do
case "$LEG" in
runner) SRC="$HERE/ai-01/coursia-runner-start.sh"; OTHER=waiters ;;
waiters) SRC="$HERE/coursia-waiters-start.sh"; OTHER=start ;;
lean) SRC="$HERE/coursia-lean-start.sh"; OTHER=start ;;
esac
[ -r "$SRC" ] || { bad "$LEG: wrapper illisible ($SRC)"; continue; }

Expand Down Expand Up @@ -138,6 +139,7 @@ for LEG in runner waiters; do
case "$LEG" in
runner) MINE='bash ./supervise.sh start 4' ;;
waiters) MINE='bash ./supervise.sh waiters 4' ;;
lean) MINE='bash ./supervise.sh lean 2' ;;
esac
out="$(run_case "$PURGE" "$SD" "$MINE")"; rc=$?
if [ "$rc" -eq 1 ] && [ -e "$SD/stop" ] && ! printf '%s' "$out" | grep -q 'DEMARRAGE'; then
Expand Down
Loading