feat: add step-by-step connectivity diagnostics to health_check
All checks were successful
Deploy / deploy (push) Successful in 13s

Break connectivity check into three stages — DNS resolution, TCP connect,
and API auth — each reported separately so failures pinpoint the exact layer.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-16 22:42:35 +01:00
parent d85c0d4780
commit 56b141e301

View File

@@ -16,11 +16,13 @@ import os
import sys import sys
import re import re
import json import json
import socket
import subprocess import subprocess
import time import time
import logging import logging
import argparse import argparse
from pathlib import Path from pathlib import Path
from urllib.parse import urlparse
from typing import Dict, List, Optional, Tuple from typing import Dict, List, Optional, Tuple
import requests import requests
@@ -177,13 +179,38 @@ class OutlineSync:
return None return None
def health_check(self) -> bool: def health_check(self) -> bool:
print("Checking API connectivity...", end=" ", flush=True) parsed = urlparse(self.base_url)
host = parsed.hostname or "outline"
port = parsed.port or (443 if parsed.scheme == "https" else 80)
print(f"Checking API connectivity to {self.base_url} ...")
# 1. DNS resolution
print(f" DNS resolve {host!r} ... ", end="", flush=True)
try:
ip = socket.gethostbyname(host)
print(f"✓ ({ip})")
except socket.gaierror as exc:
print(f"✗ DNS failed: {exc}")
return False
# 2. TCP reachability
print(f" TCP connect {ip}:{port} ... ", end="", flush=True)
try:
with socket.create_connection((host, port), timeout=5):
print("")
except (socket.timeout, ConnectionRefusedError, OSError) as exc:
print(f"{exc}")
return False
# 3. API authentication
print(f" API auth ... ", end="", flush=True)
result = self._api("/api/auth.info") result = self._api("/api/auth.info")
if result and "data" in result: if result and "data" in result:
user = result["data"].get("user", {}) user = result["data"].get("user", {})
print(f"✓ ({user.get('name', 'unknown')})") print(f"✓ (user: {user.get('name', 'unknown')})")
return True return True
print("") print(" bad response")
return False return False
def get_collections(self) -> List[Dict]: def get_collections(self) -> List[Dict]: