#!/usr/bin/env bash # AWOOOI P3 controlled release gate. # Read-only: this script never starts, stops, restarts, deletes, or modifies services. set -uo pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" cd "$ROOT_DIR" SSH_BATCH_MODE=${SSH_BATCH_MODE:-yes} SSH_OPTS=(-o BatchMode="$SSH_BATCH_MODE" -o ConnectTimeout=6) NO_COLOR=0 SKIP_COLD_START_GATE=0 LOAD5_PER_CORE_LIMIT="${LOAD5_PER_CORE_LIMIT:-1.0}" LOAD15_PER_CORE_LIMIT="${LOAD15_PER_CORE_LIMIT:-1.0}" JOB_CONTAINER_CPU_LIMIT="${JOB_CONTAINER_CPU_LIMIT:-1.0}" TEXTFILE_MAX_AGE_SECONDS="${TEXTFILE_MAX_AGE_SECONDS:-300}" usage() { cat <<'USAGE' Usage: bash scripts/reboot-recovery/p3-controlled-release-gate.sh [options] Options: --skip-cold-start-gate Do not run the full P0/P1/P2 read-only gate first. --no-color Disable ANSI colors. -h, --help Show this help. Environment overrides: LOAD5_PER_CORE_LIMIT=1.0 LOAD15_PER_CORE_LIMIT=1.0 JOB_CONTAINER_CPU_LIMIT=1.0 TEXTFILE_MAX_AGE_SECONDS=300 USAGE } while [ "$#" -gt 0 ]; do case "$1" in --skip-cold-start-gate) SKIP_COLD_START_GATE=1 ;; --no-color) NO_COLOR=1 ;; -h|--help) usage exit 0 ;; *) echo "Unknown argument: $1" >&2 usage >&2 exit 64 ;; esac shift done if [ "$NO_COLOR" = "1" ]; then RED="" GREEN="" YELLOW="" BLUE="" NC="" else RED=$'\033[0;31m' GREEN=$'\033[0;32m' YELLOW=$'\033[1;33m' BLUE=$'\033[0;34m' NC=$'\033[0m' fi PASS=0 WARN=0 FAIL=0 section() { printf "\n%s=== %s ===%s\n" "$BLUE" "$1" "$NC" } ok() { PASS=$((PASS + 1)) printf "%sOK%s %s\n" "$GREEN" "$NC" "$*" } warn() { WARN=$((WARN + 1)) printf "%sWARN%s %s\n" "$YELLOW" "$NC" "$*" } blocked() { FAIL=$((FAIL + 1)) printf "%sBLOCKED%s %s\n" "$RED" "$NC" "$*" } ssh_cmd() { local target="$1" local cmd="$2" ssh "${SSH_OPTS[@]}" "$target" "$cmd" } float_le() { awk -v a="$1" -v b="$2" 'BEGIN { exit !(a <= b) }' } check_cold_start_gate() { section "P0/P1/P2 cold-start gate" if [ "$SKIP_COLD_START_GATE" -eq 1 ]; then warn "cold-start gate skipped by operator option" return fi SSH_BATCH_MODE=yes bash scripts/reboot-recovery/full-stack-cold-start-check.sh --monitor-read-only --no-color --watch --interval 1 --max-attempts 1 >/tmp/awoooi-p3-cold-start-gate.log 2>&1 local rc=$? local summary blocked_count warn_count summary=$(grep -E '^PASS=[0-9]+ WARN=[0-9]+ BLOCKED=[0-9]+' /tmp/awoooi-p3-cold-start-gate.log | tail -1 || true) blocked_count=$(awk -F'BLOCKED=' '/^PASS=/ {print $2}' <<<"$summary") warn_count=$(awk -F'WARN=' '/^PASS=/ {split($2,a," "); print a[1]}' <<<"$summary") if [ "$rc" -eq 0 ]; then ok "cold-start gate is GREEN" elif [ "${blocked_count:-1}" = "0" ]; then warn "cold-start gate is DEGRADED but not blocked: ${summary:-summary unavailable}" else blocked "cold-start gate has blocked items: ${summary:-summary unavailable}; see /tmp/awoooi-p3-cold-start-gate.log" fi } check_host_load() { local label="$1" local target="$2" local out load5 load15 cores load5_per_core load15_per_core section "$label load gate" if ! out=$(ssh_cmd "$target" 'read _ load5 load15 _ < /proc/loadavg; cores=$(nproc); awk -v l5="$load5" -v l15="$load15" -v c="$cores" "BEGIN {printf \"LOAD5 %.4f LOAD15 %.4f CORES %d LOAD5_PER_CORE %.6f LOAD15_PER_CORE %.6f\\n\", l5, l15, c, l5/c, l15/c}"' 2>&1); then blocked "$label load check unavailable" echo "$out" return fi echo "$out" load5_per_core=$(awk '/LOAD5_PER_CORE/ {for (i=1;i<=NF;i++) if ($i=="LOAD5_PER_CORE") print $(i+1)}' <<<"$out") load15_per_core=$(awk '/LOAD15_PER_CORE/ {for (i=1;i<=NF;i++) if ($i=="LOAD15_PER_CORE") print $(i+1)}' <<<"$out") if float_le "$load5_per_core" "$LOAD5_PER_CORE_LIMIT"; then ok "$label load5/core <= $LOAD5_PER_CORE_LIMIT" else blocked "$label load5/core too high for P3 release" fi if float_le "$load15_per_core" "$LOAD15_PER_CORE_LIMIT"; then ok "$label load15/core <= $LOAD15_PER_CORE_LIMIT" else blocked "$label load15/core too high for P3 release" fi } check_textfiles() { section "textfile freshness" local out if out=$(ssh_cmd "wooo@192.168.0.110" ' now=$(date +%s) for f in /home/wooo/node_exporter_textfiles/docker_stats.prom /home/wooo/node_exporter_textfiles/systemd_units.prom /home/wooo/node_exporter_textfiles/storage_health.prom /home/wooo/node_exporter_textfiles/backup_health.prom /home/wooo/node_exporter_textfiles/cold_start_recovery.prom; do if [ -f "$f" ]; then echo "$(basename "$f") $((now - $(stat -c %Y "$f")))" else echo "$(basename "$f") missing" fi done ' 2>&1); then while read -r file age; do [ -n "${file:-}" ] || continue max_age="$TEXTFILE_MAX_AGE_SECONDS" [ "$file" = "cold_start_recovery.prom" ] && max_age=900 [ "$file" = "backup_health.prom" ] && max_age=900 if [ "$age" = "missing" ]; then blocked "110 $file missing" elif [ "$age" -le "$max_age" ]; then ok "110 $file fresh age=${age}s" else blocked "110 $file stale age=${age}s" fi done <<<"$out" else blocked "110 textfile freshness check unavailable" echo "$out" fi if out=$(ssh_cmd "ollama@192.168.0.188" ' now=$(date +%s) for f in /home/ollama/node_exporter_textfiles/docker_stats.prom /home/ollama/node_exporter_textfiles/docker_restart_count.prom /home/ollama/node_exporter_textfiles/storage_health.prom /home/ollama/node_exporter_textfiles/backup.prom /home/ollama/node_exporter_textfiles/backup_health.prom; do if [ -f "$f" ]; then echo "$(basename "$f") $((now - $(stat -c %Y "$f")))" else echo "$(basename "$f") missing" fi done ' 2>&1); then while read -r file age; do [ -n "${file:-}" ] || continue max_age="$TEXTFILE_MAX_AGE_SECONDS" [ "$file" = "backup.prom" ] && max_age=90000 [ "$file" = "backup_health.prom" ] && max_age=900 if [ "$age" = "missing" ]; then blocked "188 $file missing" elif [ "$age" -le "$max_age" ]; then ok "188 $file fresh age=${age}s" else blocked "188 $file stale age=${age}s" fi done <<<"$out" else blocked "188 textfile freshness check unavailable" echo "$out" fi } check_backup_health() { section "backup health gate" local label target file out stale missing_cron missing_script failed_count integrity_stale for spec in \ "110|wooo@192.168.0.110|/home/wooo/node_exporter_textfiles/backup_health.prom" \ "188|ollama@192.168.0.188|/home/ollama/node_exporter_textfiles/backup_health.prom"; do label=${spec%%|*} target=${spec#*|} target=${target%%|*} file=${spec##*|} if ! out=$(ssh_cmd "$target" " if [ ! -f '$file' ]; then echo 'BACKUP_HEALTH missing' exit 0 fi awk ' /^awoooi_backup_job_fresh/ {total += 1; stale += (\$2 == 0)} /^awoooi_backup_job_configured/ {missing_cron += (\$2 == 0)} /^awoooi_backup_script_present/ {missing_script += (\$2 == 0)} /^awoooi_backup_last_run_failed_count/ {failed += \$2} /^awoooi_backup_integrity_fresh/ {integrity_total += 1; integrity_stale += (\$2 == 0)} END {printf \"BACKUP_HEALTH total=%d stale=%d missing_cron=%d missing_script=%d failed_count=%d integrity_total=%d integrity_stale=%d\\n\", total, stale, missing_cron, missing_script, failed, integrity_total, integrity_stale} ' '$file' " 2>&1); then blocked "$label backup health check unavailable" echo "$out" continue fi echo "$label $out" if grep -q "BACKUP_HEALTH missing" <<<"$out"; then blocked "$label backup_health.prom missing" continue fi stale=$(awk -F'stale=' '{split($2,a," "); print a[1]+0}' <<<"$out") missing_cron=$(awk -F'missing_cron=' '{split($2,a," "); print a[1]+0}' <<<"$out") missing_script=$(awk -F'missing_script=' '{split($2,a," "); print a[1]+0}' <<<"$out") failed_count=$(awk -F'failed_count=' '{split($2,a," "); print a[1]+0}' <<<"$out") integrity_stale=$(awk -F'integrity_stale=' '{split($2,a," "); print a[1]+0}' <<<"$out") [ "$stale" -eq 0 ] && ok "$label expected backups are fresh" || blocked "$label expected backup jobs are stale" [ "$missing_cron" -eq 0 ] && ok "$label expected backup crons are configured" || blocked "$label expected backup cron config missing" [ "$missing_script" -eq 0 ] && ok "$label expected backup scripts are present" || blocked "$label expected backup scripts missing" if [ "$label" = "110" ]; then [ "$integrity_stale" -eq 0 ] && ok "110 backup integrity and restore drill are fresh" || blocked "110 backup integrity or restore drill stale" [ "$failed_count" -eq 0 ] && ok "110 latest aggregate backup had no failed components" || warn "110 latest aggregate backup still records failed components; rerun backup-all after fixes" fi done } check_storage_health() { section "storage health gate" local label target file out root_readonly current_errors previous_errors fsck_errors for spec in \ "110|wooo@192.168.0.110|/home/wooo/node_exporter_textfiles/storage_health.prom" \ "188|ollama@192.168.0.188|/home/ollama/node_exporter_textfiles/storage_health.prom"; do label=${spec%%|*} target=${spec#*|} target=${target%%|*} file=${spec##*|} if ! out=$(ssh_cmd "$target" " if [ ! -f '$file' ]; then echo 'STORAGE_HEALTH missing' exit 0 fi awk ' /^awoooi_host_root_filesystem_readonly/ {root += \$2} /^awoooi_host_storage_error_count/ && /boot=\"current\"/ {current += \$2} /^awoooi_host_storage_error_count/ && /boot=\"previous\"/ {previous += \$2} /^awoooi_host_storage_error_count/ && /boot=\"last-fsck-log\"/ {fsck += \$2} END {printf \"STORAGE_HEALTH root_readonly=%d current=%d previous=%d fsck=%d\\n\", root, current, previous, fsck} ' '$file' " 2>&1); then blocked "$label storage health check unavailable" echo "$out" continue fi echo "$label $out" if grep -q "STORAGE_HEALTH missing" <<<"$out"; then blocked "$label storage_health.prom missing" continue fi root_readonly=$(awk -F'root_readonly=' '{split($2,a," "); print a[1]+0}' <<<"$out") current_errors=$(awk -F'current=' '{split($2,a," "); print a[1]+0}' <<<"$out") previous_errors=$(awk -F'previous=' '{split($2,a," "); print a[1]+0}' <<<"$out") fsck_errors=$(awk -F'fsck=' '{split($2,a," "); print a[1]+0}' <<<"$out") [ "$root_readonly" -eq 0 ] && ok "$label root filesystem is writable" || blocked "$label root filesystem is read-only" [ "$current_errors" -eq 0 ] && ok "$label current boot has no storage error evidence" || blocked "$label current boot has storage error evidence" [ "$previous_errors" -eq 0 ] && ok "$label previous boot has no storage error evidence" || warn "$label previous boot has storage error evidence; keep fsck/backup follow-up open" [ "$fsck_errors" -eq 0 ] && ok "$label fsck logs have no retained error evidence" || warn "$label fsck logs retain error evidence; verify offline fsck/backup status" done } check_runner_guardrails() { section "runner/CD guardrails" local out bad if ! out=$(ssh_cmd "wooo@192.168.0.110" ' bad=0 for u in awoooi-direct-runner-open.service awoooi-direct-runner.service gitea-act-runner-host.service gitea-act-runner-awoooi-controlled.service gitea-awoooi-controlled-runner.service gitea-act-runner-awoooi-open.service; do load=$(systemctl show "$u" -p LoadState --value 2>/dev/null || true) unitfile=$(systemctl show "$u" -p UnitFileState --value 2>/dev/null || true) active=$(systemctl show "$u" -p ActiveState --value 2>/dev/null || true) unit_ok=0 if [ "$load" = "masked" ] && [ "$unitfile" = "masked" ] && [ "$active" = "inactive" ]; then unit_ok=1 fi echo "RUNNER_FAILCLOSED_UNIT $u load=$load unitfile=$unitfile active=$active ok=$unit_ok" [ "$unit_ok" = "1" ] || bad=1 done cd_lane_load=$(systemctl show awoooi-cd-lane.service -p LoadState --value 2>/dev/null || true) cd_lane_unitfile=$(systemctl show awoooi-cd-lane.service -p UnitFileState --value 2>/dev/null || true) cd_lane_active=$(systemctl show awoooi-cd-lane.service -p ActiveState --value 2>/dev/null || true) cd_lane_execstart=$(systemctl show awoooi-cd-lane.service -p ExecStart --value 2>/dev/null || true) cd_lane_sentinel=missing [ -e /run/awoooi-cd-lane-enabled ] && cd_lane_sentinel=present cd_lane_capacity_ok=0 cd_lane_labels_ok=0 if grep -Eq "^[[:space:]]+capacity:[[:space:]]*1[[:space:]]*$" /home/wooo/awoooi-cd-lane/config.yaml 2>/dev/null; then cd_lane_capacity_ok=1 fi if grep -q "awoooi-ubuntu:docker://192.168.0.110:5000/awoooi/ci-runner:act-22.04" /home/wooo/awoooi-cd-lane/config.yaml 2>/dev/null \ && grep -q "awoooi-host:host" /home/wooo/awoooi-cd-lane/config.yaml 2>/dev/null \ && ! grep -Eq "^[[:space:]]+- \".*(ubuntu-latest|stockplatform|headless|playwright)" /home/wooo/awoooi-cd-lane/config.yaml 2>/dev/null; then cd_lane_labels_ok=1 fi cd_lane_binary_kind=$(file -b /home/wooo/awoooi-cd-lane/awoooi_cd_lane 2>/dev/null || echo missing) cd_lane_binary_elf=0 echo "$cd_lane_binary_kind" | grep -qi "ELF" && cd_lane_binary_elf=1 cd_lane_process_count=$(pgrep -f "^/home/wooo/awoooi-cd-lane/awoooi_cd_lane" 2>/dev/null | wc -l | tr -d " ") cd_lane_ok=0 cd_lane_mode=blocked if [ "$cd_lane_active" = "inactive" ] \ && [ "$cd_lane_sentinel" = "missing" ] \ && [ "$cd_lane_binary_elf" = "0" ] \ && [ "$cd_lane_process_count" = "0" ] \ && { { [ "$cd_lane_load" = "masked" ] && [ "$cd_lane_unitfile" = "masked" ]; } || echo "$cd_lane_execstart" | grep -q "/bin/false"; }; then cd_lane_ok=1 cd_lane_mode=failclosed elif [ "$cd_lane_sentinel" = "present" ] && [ "$cd_lane_active" = "active" ] && [ "$cd_lane_capacity_ok" = "1" ] && [ "$cd_lane_labels_ok" = "1" ] && [ "$cd_lane_binary_elf" = "1" ]; then cd_lane_ok=1 cd_lane_mode=controlled_open fi echo "CD_LANE_CONTROLLED mode=$cd_lane_mode load=$cd_lane_load unitfile=$cd_lane_unitfile active=$cd_lane_active sentinel=$cd_lane_sentinel capacity=$cd_lane_capacity_ok labels=$cd_lane_labels_ok binary_elf=$cd_lane_binary_elf process_count=$cd_lane_process_count ok=$cd_lane_ok" cd_lane_drain_load=$(systemctl show awoooi-cd-lane-drain.service -p LoadState --value 2>/dev/null || true) cd_lane_drain_unitfile=$(systemctl show awoooi-cd-lane-drain.service -p UnitFileState --value 2>/dev/null || true) cd_lane_drain_active=$(systemctl show awoooi-cd-lane-drain.service -p ActiveState --value 2>/dev/null || true) cd_lane_drain_cpu_accounting=$(systemctl show awoooi-cd-lane-drain.service -p CPUAccounting --value 2>/dev/null || true) cd_lane_drain_cpu_quota=$(systemctl show awoooi-cd-lane-drain.service -p CPUQuotaPerSecUSec --value 2>/dev/null || true) cd_lane_drain_memory_accounting=$(systemctl show awoooi-cd-lane-drain.service -p MemoryAccounting --value 2>/dev/null || true) cd_lane_drain_memory_max=$(systemctl show awoooi-cd-lane-drain.service -p MemoryMax --value 2>/dev/null || true) cd_lane_drain_tasks_accounting=$(systemctl show awoooi-cd-lane-drain.service -p TasksAccounting --value 2>/dev/null || true) cd_lane_drain_tasks_max=$(systemctl show awoooi-cd-lane-drain.service -p TasksMax --value 2>/dev/null || true) cd_lane_drain_limits_ok=0 if [ "$cd_lane_drain_cpu_accounting" = "yes" ] \ && [ -n "$cd_lane_drain_cpu_quota" ] && [ "$cd_lane_drain_cpu_quota" != "infinity" ] \ && [ "$cd_lane_drain_memory_accounting" = "yes" ] \ && [ -n "$cd_lane_drain_memory_max" ] && [ "$cd_lane_drain_memory_max" != "infinity" ] \ && [ "$cd_lane_drain_tasks_accounting" = "yes" ] \ && [ -n "$cd_lane_drain_tasks_max" ] && [ "$cd_lane_drain_tasks_max" != "infinity" ]; then cd_lane_drain_limits_ok=1 fi cd_lane_drain_capacity_ok=0 cd_lane_drain_labels_ok=0 if grep -Eq "^[[:space:]]+capacity:[[:space:]]*1[[:space:]]*$" /home/wooo/awoooi-cd-lane-drain/config.yaml 2>/dev/null; then cd_lane_drain_capacity_ok=1 fi if grep -q "awoooi-ubuntu:docker://192.168.0.110:5000/awoooi/ci-runner:act-22.04" /home/wooo/awoooi-cd-lane-drain/config.yaml 2>/dev/null \ && grep -q "awoooi-host:host" /home/wooo/awoooi-cd-lane-drain/config.yaml 2>/dev/null \ && ! grep -Eq "^[[:space:]]+- \".*(ubuntu-latest|stockplatform|headless|playwright)" /home/wooo/awoooi-cd-lane-drain/config.yaml 2>/dev/null; then cd_lane_drain_labels_ok=1 fi cd_lane_drain_binary_kind=$(file -b /home/wooo/awoooi-cd-lane-drain/awoooi_cd_lane_controlled 2>/dev/null || echo missing) cd_lane_drain_binary_elf=0 echo "$cd_lane_drain_binary_kind" | grep -qi "ELF" && cd_lane_drain_binary_elf=1 cd_lane_drain_process_count=$(pgrep -f "^/home/wooo/awoooi-cd-lane-drain/awoooi_cd_lane_controlled" 2>/dev/null | wc -l | tr -d " ") cd_lane_drain_ok=0 cd_lane_drain_mode=blocked if [ "$cd_lane_drain_active" != "active" ] \ && [ "$cd_lane_drain_binary_elf" = "0" ] \ && [ "$cd_lane_drain_process_count" = "0" ] \ && { [ "$cd_lane_drain_load" = "not-found" ] || { [ "$cd_lane_drain_load" = "masked" ] && [ "$cd_lane_drain_unitfile" = "masked" ]; }; }; then cd_lane_drain_ok=1 cd_lane_drain_mode=failclosed elif [ "$cd_lane_drain_active" = "active" ] \ && [ "$cd_lane_drain_capacity_ok" = "1" ] \ && [ "$cd_lane_drain_labels_ok" = "1" ] \ && [ "$cd_lane_drain_binary_elf" = "1" ] \ && [ "$cd_lane_drain_limits_ok" = "1" ]; then cd_lane_drain_ok=1 cd_lane_drain_mode=controlled_open fi echo "CD_LANE_DRAIN_CONTROLLED mode=$cd_lane_drain_mode load=$cd_lane_drain_load unitfile=$cd_lane_drain_unitfile active=$cd_lane_drain_active capacity=$cd_lane_drain_capacity_ok labels=$cd_lane_drain_labels_ok binary_elf=$cd_lane_drain_binary_elf limits=$cd_lane_drain_limits_ok process_count=$cd_lane_drain_process_count ok=$cd_lane_drain_ok" cd_lane_root_restore_left=unknown if sudo -n true >/dev/null 2>&1; then cd_lane_root_restore_left=$(sudo -n find /root -maxdepth 1 -type d \( -name "awoooi-cd-lane-disabled-*" -o -name "awoooi-cd-lane-drain-disabled-*" \) -print 2>/dev/null | wc -l | tr -d " ") fi echo "CD_LANE_ROOT_RESTORE_SOURCES left=$cd_lane_root_restore_left" cd_lane_guard_ok=0 if { [ "$cd_lane_ok" = "1" ] || [ "$cd_lane_drain_ok" = "1" ]; } && [ "$cd_lane_root_restore_left" = "0" ]; then cd_lane_guard_ok=1 fi echo "CD_LANE_GUARDRAILS_OK $cd_lane_guard_ok" [ "$cd_lane_guard_ok" = "1" ] || bad=1 direct_runner_count=$(pgrep -f "^/home/wooo/act-runner/act_runner|^/home/wooo/act-runner-controlled/act_runner|^/home/wooo/awoooi-controlled-runner/awoooi_controlled_runner" 2>/dev/null | wc -l | tr -d " ") echo "RUNNER_DIRECT_PROCESS_COUNT $direct_runner_count" [ "$direct_runner_count" = "0" ] || bad=1 for p in /home/wooo/act-runner/act_runner /home/wooo/act-runner/act_runner.real-20260628-runner-pressure-guard /home/wooo/act-runner-controlled/act_runner /home/wooo/awoooi-controlled-runner/awoooi_controlled_runner; do kind=$(file -b "$p" 2>/dev/null || echo missing) echo "RUNNER_FAILCLOSED_BINARY $p kind=$kind" echo "$kind" | grep -qi "ELF" && bad=1 done for u in $(systemctl list-units "actions.runner.*" --all --no-legend --plain 2>/dev/null | awk "{print \$1}"); do load=$(systemctl show "$u" -p LoadState --value) unitfile=$(systemctl show "$u" -p UnitFileState --value) mainpid=$(systemctl show "$u" -p MainPID --value) watchdog=$(systemctl show "$u" -p WatchdogUSec --value) quota=$(systemctl show "$u" -p CPUQuotaPerSecUSec --value) memory=$(systemctl show "$u" -p MemoryMax --value) state=$(systemctl show "$u" -p ActiveState --value) action_ok=0 action_mode=blocked if [ "$state" != "active" ] \ && { [ "$load" = "masked" ] || [ "$load" = "not-found" ] || [ "$unitfile" = "masked" ] || [ "$unitfile" = "disabled" ]; } \ && [ "${mainpid:-0}" = "0" ]; then action_ok=1 action_mode=github_disabled fi echo "$u mode=$action_mode load=$load unitfile=$unitfile state=$state mainpid=$mainpid watchdog=$watchdog quota=$quota memory=$memory ok=$action_ok" [ "$action_ok" = "1" ] || bad=1 done echo "BAD_RUNNER_GUARDRAILS $bad" ' 2>&1); then blocked "runner guardrail check unavailable" echo "$out" return fi echo "$out" grep -q "BAD_RUNNER_GUARDRAILS 0" <<<"$out" && ok "legacy runner fail-closed and controlled cd-lane guardrails complete" || blocked "legacy runner / controlled cd-lane guardrails incomplete" } check_job_containers() { section "active job container CPU" local out if ! out=$(ssh_cmd "wooo@192.168.0.110" ' names=$(docker ps --format "{{.Names}}" | grep -E "^(GITEA-ACTIONS-|awoooi-cd-)" || true) if [ -z "$names" ]; then echo "NO_ACTIVE_JOB_CONTAINERS" exit 0 fi for name in $names; do cpu=$(docker stats "$name" --no-stream --format "{{.CPUPerc}}" | tr -d "%" | awk "{printf \"%.6f\", \$1 / 100}") echo "JOB_CONTAINER $name cpu_cores=$cpu" done ' 2>&1); then blocked "job container CPU check unavailable" echo "$out" return fi echo "$out" if grep -q "NO_ACTIVE_JOB_CONTAINERS" <<<"$out"; then ok "no active Gitea/CD job containers" return fi local bad_count bad_count=$(awk -v limit="$JOB_CONTAINER_CPU_LIMIT" -F'cpu_cores=' '/^JOB_CONTAINER / {if (($2 + 0) > limit) bad++} END {print bad+0}' <<<"$out") if [ "$bad_count" -eq 0 ]; then ok "active job containers are below ${JOB_CONTAINER_CPU_LIMIT} CPU cores" else blocked "$bad_count active job container(s) exceed ${JOB_CONTAINER_CPU_LIMIT} CPU cores" fi } check_high_load_services() { section "high-load service health" local out if out=$(ssh_cmd "ollama@192.168.0.188" ' echo "ollama-systemd $(systemctl is-active ollama 2>/dev/null || true)" echo "ollama-api $(curl -s -o /dev/null -w "%{http_code}" --max-time 5 http://127.0.0.1:11434/api/tags || true)" docker inspect -f "momo-scheduler {{.State.Status}} {{if .State.Health}}{{.State.Health.Status}}{{end}}" momo-scheduler 2>/dev/null || true docker inspect -f "litellm {{.State.Status}} {{if .State.Health}}{{.State.Health.Status}}{{end}}" litellm 2>/dev/null || true if ! docker inspect litellm >/dev/null 2>&1 && [ ! -d /opt/litellm ]; then echo "litellm not-provisioned" fi docker inspect -f "signoz-clickhouse {{.State.Status}} {{if .State.Health}}{{.State.Health.Status}}{{end}}" signoz-clickhouse 2>/dev/null || true ' 2>&1); then echo "$out" grep -q "ollama-systemd active" <<<"$out" && ok "188 Ollama systemd active" || blocked "188 Ollama systemd inactive" grep -q "ollama-api 200" <<<"$out" && ok "188 Ollama API reachable" || blocked "188 Ollama API not reachable" grep -q "momo-scheduler running healthy" <<<"$out" && ok "188 momo-scheduler healthy" || blocked "188 momo-scheduler not healthy" if grep -Eq "litellm running( |$)" <<<"$out"; then ok "188 litellm running" elif grep -q "litellm not-provisioned" <<<"$out"; then warn "188 litellm not provisioned; provider route/cost switch requires separate approval" else blocked "188 litellm not running" fi grep -q "signoz-clickhouse running healthy" <<<"$out" && ok "188 SignOz ClickHouse healthy" || warn "188 SignOz ClickHouse health not confirmed" else blocked "188 high-load service check unavailable" echo "$out" fi if out=$(ssh_cmd "wooo@192.168.0.110" ' docker inspect -f "sentry-clickhouse {{.State.Status}} {{if .State.Health}}{{.State.Health.Status}}{{end}}" sentry-self-hosted-clickhouse-1 2>/dev/null || true docker inspect -f "sentry-kafka {{.State.Status}} {{if .State.Health}}{{.State.Health.Status}}{{end}}" sentry-self-hosted-kafka-1 2>/dev/null || true docker ps --format "{{.Names}} {{.Status}}" | grep -E "sentry-self-hosted-(snuba|events|transactions|generic|metrics|subscription).*consumer" | head -20 || true ' 2>&1); then echo "$out" grep -q "sentry-clickhouse running healthy" <<<"$out" && ok "110 Sentry ClickHouse healthy" || blocked "110 Sentry ClickHouse not healthy" grep -q "sentry-kafka running healthy" <<<"$out" && ok "110 Sentry Kafka healthy" || blocked "110 Sentry Kafka not healthy" grep -q "Restarting" <<<"$out" && blocked "110 Sentry consumers include restarting containers" || ok "110 sampled Sentry consumers are not restarting" else blocked "110 high-load service check unavailable" echo "$out" fi } summary() { section "summary" echo "PASS=$PASS WARN=$WARN BLOCKED=$FAIL" if [ "$FAIL" -gt 0 ]; then echo "Result: HOLD_P3_RELEASE. Do not release runner/CD/crawlers/consumers further." return 1 fi if [ "$WARN" -gt 0 ]; then echo "Result: P3_RELEASE_WITH_CAUTION. Proceed only with operator review." return 0 fi echo "Result: P3_RELEASE_READY. Controlled high-load work release is allowed." } echo "AWOOOI P3 controlled release gate" date '+%Y-%m-%d %H:%M:%S %Z' echo "Limits: load5/core<=$LOAD5_PER_CORE_LIMIT load15/core<=$LOAD15_PER_CORE_LIMIT job_container_cpu<=$JOB_CONTAINER_CPU_LIMIT" check_cold_start_gate check_host_load "110" "wooo@192.168.0.110" check_host_load "188" "ollama@192.168.0.188" check_textfiles check_storage_health check_backup_health check_runner_guardrails check_job_containers check_high_load_services summary