fix(tester): use remote artifact path for installs

This commit is contained in:
2026-10-16 15:33:12 +08:00
parent 841a2e0ae6
commit b94aa597ca
2 changed files with 42 additions and 4 deletions
+30 -4
View File
@@ -219,6 +219,28 @@ def validate_preflight_matrix(root: Path, config_path: Path, bindings: dict[str,
raise EnvironmentFailure(f"{platform} 绑定到 {expected_node},必须使用 contract runner;禁止在协调节点执行") raise EnvironmentFailure(f"{platform} 绑定到 {expected_node},必须使用 contract runner;禁止在协调节点执行")
def preflight_remote_artifacts(config_path: Path, requested: list[str]) -> dict[str, str]:
"""Return caller-declared artifact paths readable by remote tester nodes."""
try:
import yaml
raw = yaml.safe_load(config_path.read_text(encoding="utf-8")) or {}
except (OSError, ValueError, ImportError) as exc:
raise EnvironmentFailure(f"无法读取 preflight matrix: {config_path}: {exc}") from exc
rows = raw.get("matrix") if isinstance(raw, dict) else None
if not isinstance(rows, list):
raise EnvironmentFailure("preflight matrix 缺少 matrix;不能解析远程产物路径")
by_platform = {str(row.get("platform", "")).lower(): row for row in rows if isinstance(row, dict)}
paths: dict[str, str] = {}
for platform in requested:
row = by_platform.get(platform) or {}
artifact = row.get("artifact") if isinstance(row, dict) else None
remote_path = artifact.get("remote_path") if isinstance(artifact, dict) else None
if isinstance(remote_path, str) and remote_path.strip():
paths[platform] = remote_path.strip()
return paths
def local_path(locator: str) -> Path | None: def local_path(locator: str) -> Path | None:
parsed = urllib.parse.urlsplit(locator) parsed = urllib.parse.urlsplit(locator)
if parsed.scheme in ("http", "https"): if parsed.scheme in ("http", "https"):
@@ -551,6 +573,7 @@ def execute(args: argparse.Namespace) -> int:
"product_test": {"status": "not-run", "failure_class": "automatic-repair-failed", "note": "准备完成后由 tester catalog 驱动真实移动 session;本工具不以 API 替代移动测试"}, "product_test": {"status": "not-run", "failure_class": "automatic-repair-failed", "note": "准备完成后由 tester catalog 驱动真实移动 session;本工具不以 API 替代移动测试"},
"platforms": {}, "platforms": {},
} }
remote_artifacts: dict[str, str] = {}
try: try:
locators = parse_artifacts(args.artifacts) locators = parse_artifacts(args.artifacts)
missing = [platform for platform in requested if platform not in locators] missing = [platform for platform in requested if platform not in locators]
@@ -596,6 +619,7 @@ def execute(args: argparse.Namespace) -> int:
} }
else: else:
validate_preflight_matrix(context.root, preflight_config, bindings, requested) validate_preflight_matrix(context.root, preflight_config, bindings, requested)
remote_artifacts = preflight_remote_artifacts(preflight_config, requested)
preflight_result = run_test_preflight( preflight_result = run_test_preflight(
preflight_config, preflight_config,
mode=args.preflight_mode, mode=args.preflight_mode,
@@ -676,15 +700,17 @@ def execute(args: argparse.Namespace) -> int:
}) })
if network.get("status") != "ready": if network.get("status") != "ready":
raise EnvironmentFailure(str(network.get("observed") or network)) raise EnvironmentFailure(str(network.get("observed") or network))
artifact_path = Path(result["artifact"]["path"]) artifact_path = result["artifact"]["path"]
if platform == "ios" and node_name != "local": if node_name != "local":
raise EnvironmentFailure("远程 iOS 安装必须在 matrix.artifact.remote_path 声明 Mac 可读产物;不能把协调机路径当成 Mac 路径") artifact_path = remote_artifacts.get(platform, "")
if not artifact_path:
raise EnvironmentFailure(f"远程 {platform} 安装必须在 matrix.artifact.remote_path 声明节点可读产物")
installed = agent_runner(context.root, { installed = agent_runner(context.root, {
"operation": "install", "operation": "install",
"platform": platform, "platform": platform,
"node": node_name, "node": node_name,
"binding": binding_id, "binding": binding_id,
"artifact": str(artifact_path), "artifact": artifact_path,
"identity": identity, "identity": identity,
}) })
if installed.get("status") != "ready": if installed.get("status") != "ready":
+12
View File
@@ -116,6 +116,18 @@ matrix:
["android", "ios"], ["android", "ios"],
) )
def test_remote_artifact_path_comes_from_preflight_matrix(self):
with tempfile.TemporaryDirectory() as temp:
config = Path(temp) / "matrix.yaml"
config.write_text(
"matrix:\n - platform: ios\n artifact:\n remote_path: /Users/tester/app.ipa\n",
encoding="utf-8",
)
self.assertEqual(
bundle.preflight_remote_artifacts(config, ["ios"]),
{"ios": "/Users/tester/app.ipa"},
)
def test_new_worktree_each_run(self): def test_new_worktree_each_run(self):
with tempfile.TemporaryDirectory() as temp: with tempfile.TemporaryDirectory() as temp:
repo, worktrees = Path(temp) / "repo", Path(temp) / "worktrees" repo, worktrees = Path(temp) / "repo", Path(temp) / "worktrees"