"""Tests for the AI deploy script (scripts/ai_deploy.py).""" from __future__ import annotations import json import os import sys from unittest.mock import patch import pytest # Add scripts dir to path sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "scripts")) def test_phase_result_to_dict(): """PhaseResult.to_dict should serialize correctly.""" from ai_deploy import PhaseResult result = PhaseResult(name="build", success=True, duration_s=1.5, output="ok") d = result.to_dict() assert d["phase"] == "build" assert d["success"] is True assert d["duration_s"] == 1.5 assert d["output"] == "ok" def test_deploy_report_to_dict(): """DeployReport.to_dict should include phases and rollback info.""" from ai_deploy import DeployReport, PhaseResult report = DeployReport( started_at="2026-01-01T00:00:00Z", finished_at="2026-01-01T00:05:00Z", overall_success=True, ) report.phases.append(PhaseResult(name="build", success=True)) d = report.to_dict() assert d["overall_success"] is True assert len(d["phases"]) == 1 assert d["rollback_performed"] is False def test_phase_build_skip(): """phase_build should skip when --skip-build is set.""" from ai_deploy import phase_build result = phase_build(skip_build=True, dry_run=False) assert result.success is True assert "skipped" in result.output.lower() def test_phase_build_dry_run(): """phase_build should return dry-run message in dry-run mode.""" from ai_deploy import phase_build result = phase_build(skip_build=False, dry_run=True) assert result.success is True assert "DRY-RUN" in result.output def test_phase_tests_skip(): """phase_tests should skip when --skip-tests is set.""" from ai_deploy import phase_tests result = phase_tests(skip_tests=True, dry_run=False) assert result.success is True assert "skipped" in result.output.lower() def test_phase_tests_dry_run(): """phase_tests should return dry-run message in dry-run mode.""" from ai_deploy import phase_tests result = phase_tests(skip_tests=False, dry_run=True) assert result.success is True assert "DRY-RUN" in result.output def test_phase_deploy_missing_env(): """phase_deploy should fail when env vars are missing.""" from ai_deploy import phase_deploy # Ensure env vars are not set with patch.dict(os.environ, {}, clear=True): result = phase_deploy(dry_run=False) assert result.success is False assert "COOLIFY" in result.error def test_phase_deploy_dry_run_with_env(): """phase_deploy should succeed in dry-run mode with env vars set.""" from ai_deploy import phase_deploy with patch.dict(os.environ, {"COOLIFY_API_TOKEN": "test", "COOLIFY_APP_UUID": "uuid-123"}): result = phase_deploy(dry_run=True) assert result.success is True assert "DRY-RUN" in result.output assert "uuid-123" in result.output def test_phase_rollback_missing_env(): """phase_rollback should fail when env vars are missing.""" from ai_deploy import phase_rollback with patch.dict(os.environ, {}, clear=True): result = phase_rollback(dry_run=False) assert result.success is False assert "COOLIFY" in result.error def test_run_pipeline_dry_run_all_skip(): """Full pipeline in dry-run with all skips should succeed with env vars.""" from ai_deploy import run_pipeline with patch.dict(os.environ, {"COOLIFY_API_TOKEN": "test", "COOLIFY_APP_UUID": "uuid-123"}): report = run_pipeline(skip_build=True, skip_tests=True, dry_run=True) assert report.overall_success is True assert len(report.phases) == 3 # build, tests, deploy assert all(p.success for p in report.phases) assert report.rollback_performed is False def test_run_pipeline_deploy_fail_triggers_rollback(): """Pipeline should trigger rollback when deploy fails.""" from ai_deploy import run_pipeline with patch.dict(os.environ, {}, clear=True): report = run_pipeline(skip_build=True, skip_tests=True, dry_run=False) assert report.overall_success is False assert report.rollback_performed is True assert len(report.phases) == 4 # build, tests, deploy, rollback