from __future__ import annotations from pathlib import Path from typing import Any from skillsbench_agentbeats.deploy_bundle import DEPLOY_BUNDLE_SCHEMA_VERSION, DeployBundleError, build_deploy_bundle from skillsbench_agentbeats.task_sets import load_task_set_manifest def _repo_root() -> Path: return Path(__file__).resolve().parents[2] def _branch_image_artifact() -> dict[str, Any]: return { "source_revision": "a" * 40, "image_tag": "skillsbench-v1.1-" + "a" * 40, "images": { "worker": "ghcr.io/benchflow-ai/skillsbench-agentbeats-worker@sha256:" + "b" * 64, "green": "ghcr.io/benchflow-ai/skillsbench-agentbeats-green@sha256:" + "c" * 64, "purple": "ghcr.io/benchflow-ai/skillsbench-agentbeats-purple@sha256:" + "d" * 64, }, } def _prebuilt_task_env_images(task_ids: list[str]) -> dict[str, str]: return dict.fromkeys(task_ids, "ghcr.io/benchflow-ai/skillsbench-task-env@sha256:" + "e" * 64) def test_build_deploy_bundle_normalizes_branch_and_task_image_artifacts() -> None: root = _repo_root() manifest = load_task_set_manifest("skillsbench-v1.1", repo_root=root) assert manifest is not None task_ids = [task["task_id"] for task in manifest["tasks"]] bundle = build_deploy_bundle( repo_root=root, branch_images=_branch_image_artifact(), task_environment_images=_prebuilt_task_env_images(task_ids), ) assert bundle["schema_version"] == DEPLOY_BUNDLE_SCHEMA_VERSION assert bundle["source_revision"] == "a" * 40 assert bundle["image_tag"] == "skillsbench-v1.1-" + "a" * 40 assert bundle["task_set"] == { "task_set": "skillsbench-v1.1", "task_count": manifest["task_count"], "task_set_digest": manifest["task_set_digest"], } assert bundle["components"]["green"] == { "image": "ghcr.io/benchflow-ai/skillsbench-agentbeats-green@sha256:" + "c" * 64, "image_digest": "sha256:" + "c" * 64, "image_platform": "linux/amd64", "manifest_path": "integrations/agentbeats/green_agent/amber-manifest.json5", } assert bundle["public_readiness_images"] == { "green_image": "ghcr.io/benchflow-ai/skillsbench-agentbeats-green@sha256:" + "c" * 64, "green_image_digest": "sha256:" + "c" * 64, "green_image_platform": "linux/amd64", "worker_image": "ghcr.io/benchflow-ai/skillsbench-agentbeats-worker@sha256:" + "b" * 64, "worker_image_digest": "sha256:" + "b" * 64, "worker_image_platform": "linux/amd64", "purple_image": "ghcr.io/benchflow-ai/skillsbench-agentbeats-purple@sha256:" + "d" * 64, "purple_image_digest": "sha256:" + "d" * 64, "purple_image_platform": "linux/amd64", } assert bundle["worker_prebuilt_images"] == _prebuilt_task_env_images(task_ids) assert len(bundle["public_readiness_task_environment_images"]["images"]) == manifest["task_count"] assert bundle["public_readiness_task_environment_images"]["images"][0] == { "task_id": task_ids[0], "image": "ghcr.io/benchflow-ai/skillsbench-task-env@sha256:" + "e" * 64, "image_digest": "sha256:" + "e" * 64, "image_platform": "linux/amd64", } def test_build_deploy_bundle_rejects_missing_prebuilt_task_images() -> None: root = _repo_root() manifest = load_task_set_manifest("skillsbench-v1.1", repo_root=root) assert manifest is not None task_ids = [task["task_id"] for task in manifest["tasks"]] task_environment_images = _prebuilt_task_env_images(task_ids) missing_task_id = task_ids[-1] del task_environment_images[missing_task_id] try: build_deploy_bundle( repo_root=root, branch_images=_branch_image_artifact(), task_environment_images=task_environment_images, ) except DeployBundleError as exc: assert any( issue.path == "$.task_environment_images" and "missing 1 skillsbench-v1.1 task environment image" in issue.message and missing_task_id in issue.message for issue in exc.issues ) else: raise AssertionError("expected DeployBundleError")