Phase 5.13: CI/CD deploy script with build/test/deploy/rollback
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
"""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
|
||||
Reference in New Issue
Block a user