"""Shared fixtures: the example configurations, fixed revisions, and event builders.""" import copy from pathlib import Path from typing import cast import yaml from platform_ci.configuration import ProjectConfiguration, parse_project_configuration from platform_ci.plan import EventContext, Plan, Target, prepare_plan from platform_ci.runtimes import RuntimeCatalog, parse_runtime_catalog EXAMPLES_DIRECTORY = Path(__file__).resolve().parent.parent / "examples" SOURCE_REVISION = "a" * 40 SOURCE_TREE = "d" * 40 PLATFORM_REVISION = "b" * 40 # Syntactically valid placeholders for tests only; they name no real image and are never used outside tests. JAVA_IMAGE = f"registry.example/toolchain-java@sha256:{'1' * 64}" NODE_IMAGE = f"registry.example/toolchain-node@sha256:{'2' * 64}" TEST_RUNTIME_CATALOG = parse_runtime_catalog({"schema": 1, "toolchains": {"java": {"21": {"image": JAVA_IMAGE}}, "node": {"22.20.0": {"image": NODE_IMAGE}}}}) def placeholder_image(toolchain: str) -> str: """Return a syntactically valid placeholder image for a toolchain; it names no real image and is used only in tests.""" return f"registry.example/toolchain-{toolchain}@sha256:{'4' * 64}" # Every toolchain is qualified here, so tests can plan mixed-platform configurations. Host platforms are attested for the # toolchains that run natively. Runner labels are placeholders, not the operator's real labels. NATIVE_RUNTIME_CATALOG = parse_runtime_catalog( { "schema": 1, "runners": {"windows-amd64": {"standard": "test-windows-pool"}, "macos-arm64": {"standard": "test-macos-pool"}}, "toolchains": { "java": {"21": {"image": JAVA_IMAGE, "browser_image": placeholder_image("browser")}}, "node": {"22.20.0": {"image": NODE_IMAGE}}, "go": {"1": {"image": placeholder_image("go"), "hosts": ["macos-arm64", "windows-amd64"]}}, "rust": {"1": {"image": placeholder_image("rust"), "hosts": ["macos-arm64", "windows-amd64"]}}, "python": {"3.13": {"image": placeholder_image("python")}}, "android": {"2026.10.1": {"image": placeholder_image("android")}}, "dotnet": {"10.0.403": {"image": None, "hosts": ["windows-amd64"]}}, "xcode": {"27": {"image": None, "hosts": ["macos-arm64"]}}, }, } ) def example_mapping(file_name: str) -> dict[str, object]: """Return a fresh, mutable copy of an example `.ci.yaml` as parsed YAML.""" text = (EXAMPLES_DIRECTORY / file_name).read_text(encoding="utf-8") return copy.deepcopy(cast("dict[str, object]", yaml.safe_load(text))) def example_configuration(file_name: str) -> ProjectConfiguration: """Return a validated example configuration.""" return parse_project_configuration(example_mapping(file_name)) def component_mapping(configuration: dict[str, object], name: str) -> dict[str, object]: """Return one component's mutable mapping inside a parsed example.""" return cast("dict[str, object]", cast("dict[str, object]", configuration["components"])[name]) def build_mapping(configuration: dict[str, object], name: str) -> dict[str, object]: """Return one component's mutable `build` mapping inside a parsed example.""" return cast("dict[str, object]", component_mapping(configuration, name)["build"]) def first_target(file_name: str, context: EventContext | None = None) -> Target: """Return the first planned target of an example for the given event (a pull request by default).""" return plan_for(example_configuration(file_name), context or event())["targets"][0] def plan_for(configuration: ProjectConfiguration, context: EventContext, runtimes: RuntimeCatalog = TEST_RUNTIME_CATALOG) -> Plan: """Prepare a plan against the fully qualified test catalog unless a test supplies its own.""" return prepare_plan(configuration, context, runtimes) def event(name: str = "pull_request", ref: str = "refs/pull/1/merge", default_branch: str = "main") -> EventContext: """Build an event context with fixed revisions and a default branch.""" return EventContext(name=name, ref=ref, source_revision=SOURCE_REVISION, platform_revision=PLATFORM_REVISION, default_branch=default_branch)