更新: 421 个文件 - 2026-03-17 18:30:02
这个提交包含在:
@@ -1,10 +1,13 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import time
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict
|
||||
|
||||
import requests
|
||||
|
||||
from lab.compose import compose_payload, generate_compose
|
||||
from lab.utils import command_available, run
|
||||
from lab.utils import command_available, run, write_json
|
||||
|
||||
|
||||
def prepare(profile: Dict[str, Any], run_dir: Path, dry_run: bool = False) -> Dict[str, Any]:
|
||||
@@ -34,10 +37,58 @@ def prepare(profile: Dict[str, Any], run_dir: Path, dry_run: bool = False) -> Di
|
||||
result["blocked_reason"] = config.stderr.strip() or "docker compose config failed"
|
||||
return result
|
||||
|
||||
up = run(["docker", "compose", "-f", str(compose_path), "up", "-d"], cwd=run_dir)
|
||||
up = run(["docker", "compose", "-f", str(compose_path), "up", "-d", "--wait"], cwd=run_dir)
|
||||
result["compose_up_rc"] = up.returncode
|
||||
if up.returncode != 0:
|
||||
result["status"] = "blocked-artifact"
|
||||
result["blocked_reason"] = up.stderr.strip() or "docker compose up failed"
|
||||
result["blocked_reason"] = up.stderr.strip() or up.stdout.strip() or "docker compose up failed"
|
||||
return result
|
||||
return result
|
||||
|
||||
|
||||
def wait_ready(profile: Dict[str, Any], run_dir: Path, compose_path: Path) -> Dict[str, Any]:
|
||||
timeout_seconds = int(profile.get("ready_timeout_seconds") or 45)
|
||||
baseline_urls = profile.get("baseline_urls", []) or []
|
||||
started = time.monotonic()
|
||||
observations = []
|
||||
status = "completed"
|
||||
detail = f"baseline urls ready ({len(baseline_urls)})"
|
||||
|
||||
while True:
|
||||
observations = []
|
||||
ready = True
|
||||
for url in baseline_urls:
|
||||
try:
|
||||
response = requests.get(url, timeout=4)
|
||||
observations.append({"url": url, "status_code": response.status_code})
|
||||
if response.status_code >= 500:
|
||||
ready = False
|
||||
except Exception as exc:
|
||||
observations.append({"url": url, "error": str(exc)})
|
||||
ready = False
|
||||
if ready:
|
||||
break
|
||||
if time.monotonic() - started >= timeout_seconds:
|
||||
status = "failed"
|
||||
detail = f"services not ready within {timeout_seconds}s"
|
||||
break
|
||||
time.sleep(1)
|
||||
|
||||
payload = {
|
||||
"status": status,
|
||||
"detail": detail,
|
||||
"elapsed_seconds": round(time.monotonic() - started, 1),
|
||||
"observations": observations,
|
||||
"compose_path": str(compose_path),
|
||||
}
|
||||
write_json(run_dir / "logs" / "ready.json", payload)
|
||||
return payload
|
||||
|
||||
|
||||
def teardown(run_dir: Path, compose_path: Path) -> Dict[str, Any]:
|
||||
if not command_available("docker") or not compose_path.exists():
|
||||
return {"status": "skipped", "detail": "docker unavailable or compose file missing"}
|
||||
down = run(["docker", "compose", "-f", str(compose_path), "down", "-v", "--remove-orphans"], cwd=run_dir)
|
||||
if down.returncode != 0:
|
||||
return {"status": "failed", "detail": down.stderr.strip() or down.stdout.strip() or "docker compose down failed"}
|
||||
return {"status": "completed", "detail": "docker compose down completed"}
|
||||
|
||||
在新工单中引用
屏蔽一个用户