fix(runtime): release 2.7.1 with consistent ADB and failure diagnostics

This commit is contained in:
chenmingxuan committed 2026-11-05 11:40:49 +08:00
1 parent b2316ca249
commit 8bf59897bb
24 files changed
+792 -45

No files matched your search

+70 -2
View File
@@ -181,18 +181,23 @@ def test_completed_batch_reuses_existing_archive(client, isolated, monkeypatch):
exporter.assert_not_called()
def test_legacy_batch_archive_is_rebuilt_with_current_recording_layout(client, isolated):
@pytest.mark.parametrize("signature", [None, "artemis-batch-layout-3"])
def test_legacy_batch_archive_is_rebuilt_with_runtime_diagnostics(client, isolated, signature):
batch = service.create_batch(payload())
batch_id = batch["id"]
isolated.put("batch", batch_id, {**batch, "status": "completed", "report_ready": True})
path = reports.EXPORT_ROOT / "batches" / batch_id / "批次报告.zip"
path.parent.mkdir(parents=True)
path.write_bytes(b"legacy archive")
if signature:
reports.remember(path, signature)
base = f"/api/automation/batches/{batch_id}/archive"
assert client.get(base + "/status").json()["status"] == "idle"
response = client.get(base)
assert response.status_code == 200
assert zipfile.is_zipfile(BytesIO(response.content))
with zipfile.ZipFile(BytesIO(response.content)) as archive:
assert len([name for name in archive.namelist() if name.endswith("运行环境诊断.json")]) == 2
assert client.get(base + "/status").json()["status"] == "ready"
@@ -721,7 +726,7 @@ async def test_fail_fast_includes_skipped_reports(isolated, monkeypatch):
assert [j["status"] for j in isolated.jobs(batch["id"])] == ["failed", "skipped"]
archive = reports.export_batch(batch["id"])
with zipfile.ZipFile(archive) as z:
assert len(z.namelist()) == 10 # summaries + reports, diagnostics and evidence per task
assert len(z.namelist()) == 12 # summaries + reports, diagnostics and evidence per task
diagnostics = [name for name in z.namelist() if name.endswith("模型请求诊断.json")]
assert len(diagnostics) == 2
for name in diagnostics:
@@ -1304,6 +1309,69 @@ def test_batch_zip_contains_each_tasks_android_artifacts(isolated):
assert {archive.read(name).decode() for name in names} == {"任务0", "任务1"}
@pytest.mark.parametrize("pause_source", ["device", "initialization", "user", "model"])
def test_restart_retains_original_pause_reason_and_archives_recovery(isolated, pause_source):
batch = service.create_batch(payload())
reason = "原始暂停原因"
isolated.put(
"batch",
batch["id"],
{**batch, "status": "paused", "pause_source": pause_source, "reason": reason},
)
service.recover_batches()
recovered = isolated.get("batch", batch["id"])
assert recovered["status"] == "paused"
assert recovered["pause_source"] == "recovery"
assert recovered["reason"] == reason
event = recovered["recovery_events"][0]
assert event["previous_reason"] == reason
assert event["previous_pause_source"] == pause_source
assert "服务已重启" in event["message"]
assert all(job["status"] == "pending" for job in isolated.jobs(batch["id"]))
service.recover_batches()
assert isolated.get("batch", batch["id"])["reason"] == reason
def test_runtime_evidence_is_exported_from_the_task_without_resampling(isolated, monkeypatch):
batch = service.create_batch(payload())
first, second = isolated.jobs(batch["id"])
snapshot = {
"schema_version": 1,
"failure": {
"captured_at": 1,
"runtime": {"source_commit": "worker-commit"},
"memory": {"available_bytes": 163},
},
}
directory = reports.TRACES_PATH / first["session_id"]
directory.mkdir(parents=True)
(directory / "runtime_diagnostics.json").write_text(json.dumps(snapshot), encoding="utf-8")
isolated.put(
"batch",
batch["id"],
{**batch, "status": "paused", "reason": "设备离线", "pause_source": "device"},
)
service.recover_batches()
def assert_snapshots(archive_path):
with zipfile.ZipFile(archive_path) as archive:
records = [
json.loads(archive.read(name))
for name in archive.namelist()
if name.endswith("运行环境诊断.json")
]
recorded = next(record for record in records if record["runtime"])
assert recorded["runtime"] == snapshot
assert recorded["batch"]["reason"] == "设备离线"
assert recorded["batch"]["recovery_events"][0]["previous_pause_source"] == "device"
return records
assert_snapshots(reports.export_session_media(first["session_id"], "all"))
records = assert_snapshots(reports.export_batch(batch["id"]))
assert len(records) == 2
assert next(record for record in records if record["runtime"] is None)["runtime"] is None
def test_all_material_cache_reuses_reports_and_invalidates_on_review_or_new_files(
isolated, monkeypatch
):