feat(ship): enforce test manifest handoff
This commit is contained in:
@@ -19,6 +19,7 @@ from ship_lib import (
|
||||
check_ship_id,
|
||||
load_yaml,
|
||||
)
|
||||
from validate_test_manifest import validate_manifest
|
||||
|
||||
|
||||
def _issue(issues: list[str], msg: str) -> None:
|
||||
@@ -144,6 +145,7 @@ def validate_ship_dir(ship_dir: Path) -> list[str]:
|
||||
_issue(issues, f"缺少 {tasks_rel}")
|
||||
else:
|
||||
issues.extend(_validate_tasks(tasks_path, ship_id, kind))
|
||||
issues.extend(_validate_manifest_pointers(tasks_path, ship_dir, ship_id))
|
||||
|
||||
delivery = data.get("delivery")
|
||||
if delivery is not None:
|
||||
@@ -247,6 +249,43 @@ def _validate_tasks(path: Path, ship_id: Any, kind: Any) -> list[str]:
|
||||
return issues
|
||||
|
||||
|
||||
def _validate_manifest_pointers(path: Path, ship_dir: Path, ship_id: str) -> list[str]:
|
||||
issues: list[str] = []
|
||||
try:
|
||||
data = load_yaml(path)
|
||||
except Exception:
|
||||
return issues
|
||||
tasks = data.get("tasks") if isinstance(data, dict) else None
|
||||
if not isinstance(tasks, list):
|
||||
return issues
|
||||
for index, item in enumerate(tasks):
|
||||
if not isinstance(item, dict):
|
||||
continue
|
||||
plan = item.get("testPlan")
|
||||
if not isinstance(plan, dict):
|
||||
continue
|
||||
manifest = plan.get("manifest")
|
||||
if not isinstance(manifest, str) or not manifest.strip():
|
||||
continue
|
||||
target = (ship_dir / manifest).resolve()
|
||||
try:
|
||||
target.relative_to(ship_dir.resolve())
|
||||
except ValueError:
|
||||
_issue(issues, f"tasks[{index}].testPlan.manifest 必须位于 ship 目录内: {manifest}")
|
||||
continue
|
||||
if not target.is_file():
|
||||
_issue(issues, f"tasks[{index}].testPlan.manifest 不存在: {manifest}")
|
||||
continue
|
||||
manifest_issues, _ = validate_manifest(
|
||||
target,
|
||||
expected_ship_id=ship_id,
|
||||
policy=str(plan.get("policy") or "required"),
|
||||
mode="schema",
|
||||
)
|
||||
issues.extend(f"tasks[{index}].{issue}" for issue in manifest_issues)
|
||||
return issues
|
||||
|
||||
|
||||
def _validate_evidence(evidence: dict[str, Any], project_root: Path) -> list[str]:
|
||||
issues: list[str] = []
|
||||
for key in ("testRuns", "artifacts", "deploys", "prs", "commits"):
|
||||
|
||||
Reference in New Issue
Block a user