"""Quality gate evaluation. Gates (in order): 1. Build green – cmake --build succeeds with zero errors 2. Existing tests green – full CTest suite passes 3. New tests green – only the newly generated tests pass Warnings are always collected and stored for reporting, but they are advisory only (do NOT block) unless config.WARNINGS_ARE_BLOCKING=True. """ from __future__ import annotations from pathlib import Path from migration_pipeline.build_runner import cmake_build, parse_warnings, run_ctest from migration_pipeline.models import QualityGateResult async def evaluate_gates( build_dir: Path, test_prefix: str | None = None, ) -> QualityGateResult: """Run all quality gates and return an aggregated result. *test_prefix* is the CTest regex for newly generated tests. If None, the new-tests gate is skipped (considered passing). """ gate = QualityGateResult() # --- Gate 1: Build ------------------------------------------------------ build_ok, build_out, build_err = await cmake_build(build_dir) gate.build_ok = build_ok gate.build_errors = build_err gate.build_warnings = parse_warnings(build_out + "\n" + build_err) if not build_ok: # Short-circuit: remaining gates cannot run without a successful build. return gate # --- Gate 2: Existing tests --------------------------------------------- existing_ok, ctest_out, ctest_err = await run_ctest(build_dir) gate.existing_tests_ok = existing_ok gate.test_output = ctest_out + "\n" + ctest_err gate.test_warnings = parse_warnings(ctest_err) # --- Gate 3: New tests only --------------------------------------------- if test_prefix: new_ok, new_out, new_err = await run_ctest(build_dir, test_prefix) gate.new_tests_ok = new_ok gate.test_output += f"\n--- New tests ({test_prefix}) ---\n{new_out}{new_err}" gate.test_warnings += parse_warnings(new_err) else: gate.new_tests_ok = True # no new test → gate vacuously true return gate