Files
plex-playlist/scripts/gitea-actions/collect_runner_diagnostics.xsh
Cliff Hill d02039a22e
Some checks failed
CICD Start / Sanity and Base Decision (push) Successful in 18s
Runner Canary / Canary Heavy (ubuntu-act-8gb) (push) Has been skipped
Runner Canary / Canary Heavy (ubuntu-act-4gb) (push) Has been skipped
Runner Canary / Canary Burst (ubuntu-act (push) Failing after 11m10s
Runner Canary / Canary (ubuntu-latest) (push) Failing after 12m39s
Runner Canary / Canary (ubuntu-act) (push) Failing after 12m42s
Backend runtime upgraded to Python 3.14 with exact dependency pinning (#57)
Signed-off-by: Cliff Hill <xlorep@darkhelm.org>

## Summary

Upgrades backend runtime baseline and dependency management for issue #10.

### Changes

1. **Python Baseline**: Updated from 3.13 to 3.14
   - Updated `backend/pyproject.toml` requires-python constraint
   - Updated `backend/pyrightconfig.json` pythonVersion
   - Updated all Dockerfile and CI references

2. **Dependency Pinning**: Switched to exact version pins in `backend/pyproject.toml`
   - All dev and runtime dependencies now use `==` instead of `>=`
   - `fastapi==0.120.2`, `uvicorn==0.38.0`
   - ruff, pyright, pytest suite pinned to current resolved versions
   - Regenerated `backend/uv.lock` under Python 3.14

3. **Startup Compatibility Guard** (TDD via RED→GREEN)
   - New `compatibility_status()` function evaluates runtime and pinned deps
   - Startup raises `RuntimeError` if policy fails
   - Implemented via FastAPI lifespan (non-deprecated) handler

4. **Compatibility Status Endpoint**
   - New `GET /compatibility` returns policy status, runtime version, and package checks
   - Shares single source of truth with startup validation

5. **Integration Tests**
   - Added failing-then-passing tests for startup guard and endpoint behavior
   - 100% coverage maintained

6. **Direnv Configuration**
   - Added `UV_PYTHON="3.14"` pin to repo `.envrc`
   - Ensures direnv creates/recreates venv with correct Python version

### Validation

-  ruff format/check
-  pyright strict (0 errors)
-  pytest: 8 passed, 100% coverage (>=95 gate)
-  pydoclint: pass
-  xdoctest: pass

### Notes

- SQLAlchemy/SQLModel introduction deferred to next pass per scope
- Compatibility logic currently validates fastapi/uvicorn pins (runtime deps)
- Ready for container build validation and Renovate bot testing

Co-authored-by: copilotcoder <copilotcoder@darkhelm.org>
Reviewed-on: #57
Co-authored-by: Cliff Hill <xlorep@darkhelm.org>
Co-committed-by: Cliff Hill <xlorep@darkhelm.org>
2026-06-18 11:19:24 -04:00

69 lines
2.3 KiB
Plaintext

# Collect actionable runner diagnostics from all known runner hosts.
# Usage examples:
# source scripts/gitea-actions/collect_runner_diagnostics.xsh
# source scripts/gitea-actions/collect_runner_diagnostics.xsh "2 hours ago"
# source scripts/gitea-actions/collect_runner_diagnostics.xsh "90 minutes ago" "cicd-checks-1234"
from datetime import datetime
hosts = [
"kankali.darkhelm.lan",
"zhokq.darkhelm.lan",
"urtzul.darkhelm.lan",
"pi-desktop.darkhelm.lan",
]
since = $ARGS[0] if len($ARGS) > 0 else "2 hours ago"
trace = $ARGS[1] if len($ARGS) > 1 else ""
print(f"runner-diagnostics-start={datetime.utcnow().isoformat()}Z")
print(f"since={since}")
print(f"trace_filter={trace or 'none'}")
remote_script = f'''
set -eu
SINCE="{since}"
TRACE="{trace}"
echo "host=$(hostname -f 2>/dev/null || hostname)"
echo "timestamp_utc=$(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo "kernel=$(uname -r 2>/dev/null || echo unknown)"
echo "=== system pressure ==="
free -h || true
df -h || true
uptime || true
echo "=== docker runner containers ==="
docker ps -a --format '{{{{.Names}}}}|{{{{.Image}}}}|{{{{.Status}}}}' | grep -E 'gitea|runner|act' || echo "no_runner_container_match"
echo "=== runner container inspect ==="
for c in $(docker ps -a --format '{{{{.Names}}}}' | grep -E 'gitea|runner|act' || true); do
echo "--- container=$c ---"
docker inspect --format 'name={{{{.Name}}}} restart={{{{.RestartCount}}}} state={{{{.State.Status}}}} started={{{{.State.StartedAt}}}} finished={{{{.State.FinishedAt}}}}' "$c" || true
docker logs --since "$SINCE" --tail 200 "$c" 2>&1 || true
done
echo "=== docker daemon recent log ==="
if command -v journalctl >/dev/null 2>&1; then
journalctl -u docker --since "$SINCE" --no-pager -n 400 2>/dev/null || true
else
echo "journalctl_unavailable=true"
fi
echo "=== oom and kill signals ==="
dmesg 2>/dev/null | grep -Ei 'killed process|out of memory|oom' | tail -n 80 || true
if [ -n "$TRACE" ]; then
echo "=== trace-filtered logs ==="
for c in $(docker ps -a --format '{{{{.Names}}}}' | grep -E 'gitea|runner|act' || true); do
echo "--- trace search in container=$c ---"
docker logs --since "$SINCE" "$c" 2>&1 | grep -F "$TRACE" | tail -n 80 || true
done
fi
'''
for host in hosts:
print(f"\n=== {host} ===")
ssh @(host) @(remote_script)