"""Validate generated guard programs with Bash's actual parser, without effects.""" from __future__ import annotations import hashlib import importlib.util import os import shutil import subprocess import sys from pathlib import Path import pytest CONTROLLER = Path(__file__).resolve().parents[2] / "ops/gitea-deploy-broker" RUNNER = '''#!/usr/bin/env bash set -euo pipefail readonly DEPLOY_RUNNER="deployment-runner" stack_recovery=0 if [ "$stack_recovery" -eq 0 ]; then stack_recovery=1 fi unexpected=0 for name in validation-runner; do [ "$name" = "$DEPLOY_RUNNER" ] && continue unexpected=1 done ''' HOST = '''#!/usr/bin/env bash set -euo pipefail # ITWORX_RUNNER_CAPACITY_V2_BEGIN capacity_active=true # ITWORX_RUNNER_CAPACITY_V2_END runner_healthy=1 if [ "$runner_healthy" -eq 1 ]; then if [ "$sandbox_healthy" -eq 1 ] && \\ timeout 20 docker start "$RUNNER" "$SECONDARY_RUNNER" >/dev/null 2>&1; then : fi fi ''' @pytest.fixture def fleet(monkeypatch): monkeypatch.syspath_prepend(str(CONTROLLER)) spec = importlib.util.spec_from_file_location( "runner_guard_shell_contract", CONTROLLER / "runner_fleet_specialize.py", ) assert spec and spec.loader module = importlib.util.module_from_spec(spec) sys.modules[spec.name] = module spec.loader.exec_module(module) return module @pytest.mark.skipif(os.name != "posix", reason="Real Bash guard validation requires POSIX") @pytest.mark.parametrize("kind", ["runner", "host", "host_legacy"]) def test_complete_generated_guard_passes_real_bash_parser(fleet, kind, monkeypatch): bash = shutil.which("bash") assert bash is not None, "The deployment qualification requires Bash" state_command = "timeout 15 /fixed/controller --state" if kind == "runner": original = RUNNER generated = fleet._patch_runner_guard( original, state_command, 'timeout 10 /fixed/controller --guard-allows-container "$name"', ) else: original = HOST if kind == "host_legacy": original = original.replace( "# ITWORX_RUNNER_CAPACITY_V2_BEGIN\ncapacity_active=true\n" "# ITWORX_RUNNER_CAPACITY_V2_END\n", "", ) # This isolated fixture represents a single approved legacy source. # Live acceptance separately binds the actual unchanged guard hash. monkeypatch.setattr( fleet, "HOST_GUARD_SOURCE_SHA256", hashlib.sha256(original.encode("utf-8")).hexdigest(), ) generated = fleet._patch_host_guard(original, state_command) for program in (original, generated): # Parse stdin only. No shell program, controller, Docker or guard runs. result = subprocess.run( [bash, "-n"], input=program.encode("utf-8"), capture_output=True, timeout=5, check=False, ) assert result.returncode == 0, "Generated guard failed real Bash syntax validation"