Files
devx/tests/unit/test_ci_check_workflow_tofu_init.py
T
emil 9f1bdc4cf1
Post-merge / detect-and-configure (push) Successful in 12s
Post-merge / release-and-maintain (push) Successful in 1m19s
DEVX-145: feat: extract reusable components from infra and grm into devx
2026-07-22 20:56:27 +00:00

357 lines
11 KiB
Python

"""Unit tests for devx.ci.check_workflow_tofu_init."""
from __future__ import annotations
import textwrap
from pathlib import Path
from click.testing import CliRunner
import devx.ci.check_workflow_tofu_init as mod
from devx.ci.check_workflow_tofu_init import _check_workflow, main
def _write_workflow(tmp_path: Path, content: str) -> Path:
filepath = tmp_path / "test.yml"
filepath.write_text(textwrap.dedent(content), encoding="utf-8")
return filepath
class TestCheckWorkflow:
def test_passes_when_tofu_init_present(self, tmp_path: Path) -> None:
filepath = _write_workflow(
tmp_path,
"""
name: Test
on: push
jobs:
deploy:
runs-on: docker
steps:
- run: python3 scripts/create_production_deployment.py --phase tofu-init
- run: python3 scripts/preflight_deploy.py --env production
""",
)
assert _check_workflow(filepath, mod.DEFAULT_TOFU_STATE_SCRIPTS) == []
def test_fails_when_tofu_init_missing(self, tmp_path: Path) -> None:
filepath = _write_workflow(
tmp_path,
"""
name: Test
on: push
jobs:
preflight:
runs-on: docker
steps:
- run: python3 scripts/preflight_deploy.py --env production
""",
)
errors = _check_workflow(filepath, mod.DEFAULT_TOFU_STATE_SCRIPTS)
assert len(errors) == 1
assert "preflight" in errors[0]
assert "tofu-init" in errors[0]
def test_passes_when_direct_tofu_init(self, tmp_path: Path) -> None:
filepath = _write_workflow(
tmp_path,
"""
name: Test
on: push
jobs:
deploy:
runs-on: docker
steps:
- run: tofu init
- run: tofu output -json
""",
)
assert _check_workflow(filepath, mod.DEFAULT_TOFU_STATE_SCRIPTS) == []
def test_fails_when_direct_tofu_output_without_init(self, tmp_path: Path) -> None:
filepath = _write_workflow(
tmp_path,
"""
name: Test
on: push
jobs:
check:
runs-on: docker
steps:
- run: tofu output -json
""",
)
errors = _check_workflow(filepath, mod.DEFAULT_TOFU_STATE_SCRIPTS)
assert len(errors) == 1
assert "check" in errors[0]
def test_passes_when_no_tofu_usage(self, tmp_path: Path) -> None:
filepath = _write_workflow(
tmp_path,
"""
name: Test
on: push
jobs:
lint:
runs-on: docker
steps:
- run: make lint
""",
)
assert _check_workflow(filepath, mod.DEFAULT_TOFU_STATE_SCRIPTS) == []
def test_passes_with_staging_deployment_tofu_init(self, tmp_path: Path) -> None:
filepath = _write_workflow(
tmp_path,
"""
name: Test
on: push
jobs:
deploy:
runs-on: docker
steps:
- run: python3 scripts/create_staging_deployment.py --phase tofu-init
- run: python3 scripts/create_staging_deployment.py --phase deploy
""",
)
assert _check_workflow(filepath, mod.DEFAULT_TOFU_STATE_SCRIPTS) == []
def test_fails_with_tofu_plan_without_init(self, tmp_path: Path) -> None:
filepath = _write_workflow(
tmp_path,
"""
name: Test
on: push
jobs:
plan:
runs-on: docker
steps:
- run: tofu plan
""",
)
errors = _check_workflow(filepath, mod.DEFAULT_TOFU_STATE_SCRIPTS)
assert len(errors) == 1
assert "plan" in errors[0]
def test_fails_with_tofu_apply_without_init(self, tmp_path: Path) -> None:
filepath = _write_workflow(
tmp_path,
"""
name: Test
on: push
jobs:
apply:
runs-on: docker
steps:
- run: tofu apply -auto-approve
""",
)
errors = _check_workflow(filepath, mod.DEFAULT_TOFU_STATE_SCRIPTS)
assert len(errors) == 1
assert "apply" in errors[0]
def test_multiple_jobs_one_missing(self, tmp_path: Path) -> None:
filepath = _write_workflow(
tmp_path,
"""
name: Test
on: push
jobs:
good:
runs-on: docker
steps:
- run: python3 scripts/create_production_deployment.py --phase tofu-init
- run: python3 scripts/preflight_deploy.py --env production
bad:
runs-on: docker
steps:
- run: python3 scripts/preflight_deploy.py --env production
""",
)
errors = _check_workflow(filepath, mod.DEFAULT_TOFU_STATE_SCRIPTS)
assert len(errors) == 1
assert "bad" in errors[0]
def test_no_steps_passes(self, tmp_path: Path) -> None:
filepath = _write_workflow(
tmp_path,
"""
name: Test
on: push
jobs:
empty:
runs-on: docker
""",
)
assert _check_workflow(filepath, mod.DEFAULT_TOFU_STATE_SCRIPTS) == []
def test_destroy_orphans_does_not_require_init(self, tmp_path: Path) -> None:
filepath = _write_workflow(
tmp_path,
"""
name: Test
on: push
jobs:
cleanup:
runs-on: docker
steps:
- run: python3 scripts/destroy_orphans.py
""",
)
assert _check_workflow(filepath, mod.DEFAULT_TOFU_STATE_SCRIPTS) == []
def test_invalid_yaml_returns_error(self, tmp_path: Path) -> None:
filepath = tmp_path / "bad.yml"
filepath.write_text("jobs: [invalid yaml: {", encoding="utf-8")
errors = _check_workflow(filepath, mod.DEFAULT_TOFU_STATE_SCRIPTS)
assert len(errors) == 1
assert "cannot parse YAML" in errors[0]
def test_tofu_show_requires_init(self, tmp_path: Path) -> None:
filepath = _write_workflow(
tmp_path,
"""
name: Test
on: push
jobs:
show:
runs-on: docker
steps:
- run: tofu show -json
""",
)
errors = _check_workflow(filepath, mod.DEFAULT_TOFU_STATE_SCRIPTS)
assert len(errors) == 1
assert "show" in errors[0]
def test_custom_state_scripts(self, tmp_path: Path) -> None:
filepath = _write_workflow(
tmp_path,
"""
name: Test
on: push
jobs:
custom:
runs-on: docker
steps:
- run: python3 scripts/my_custom_script.py
""",
)
errors = _check_workflow(filepath, {"my_custom_script.py"})
assert len(errors) == 1
assert "custom" in errors[0]
def test_step_with_no_run_skipped(self, tmp_path: Path) -> None:
"""A step with no 'run' key should be skipped (line 80 continue)."""
filepath = _write_workflow(
tmp_path,
"""
name: Test
on: push
jobs:
deploy:
runs-on: docker
steps:
- name: Checkout
uses: actions/checkout@v4
- run: tofu init
- run: tofu output
""",
)
assert _check_workflow(filepath, mod.DEFAULT_TOFU_STATE_SCRIPTS) == []
class TestCli:
def test_passes_with_specific_workflow(self, tmp_path: Path) -> None:
filepath = _write_workflow(
tmp_path,
"""
name: Test
on: push
jobs:
deploy:
runs-on: docker
steps:
- run: tofu init
- run: tofu output
""",
)
runner = CliRunner()
result = runner.invoke(main, ["--workflow", str(filepath)])
assert result.exit_code == 0
assert "OK" in result.output
def test_fails_with_missing_tofu_init(self, tmp_path: Path) -> None:
filepath = _write_workflow(
tmp_path,
"""
name: Test
on: push
jobs:
preflight:
runs-on: docker
steps:
- run: python3 scripts/preflight_deploy.py --env production
""",
)
runner = CliRunner()
result = runner.invoke(main, ["--workflow", str(filepath)])
assert result.exit_code == 1
assert "FAIL" in result.output
assert "preflight" in result.output
def test_checks_all_workflows_by_default(self, tmp_path: Path) -> None:
workflows_dir = tmp_path / "workflows"
workflows_dir.mkdir()
(workflows_dir / "good.yml").write_text(
textwrap.dedent("""
name: Good
on: push
jobs:
deploy:
runs-on: docker
steps:
- run: tofu init
- run: tofu output
"""),
encoding="utf-8",
)
(workflows_dir / "bad.yml").write_text(
textwrap.dedent("""
name: Bad
on: push
jobs:
check:
runs-on: docker
steps:
- run: tofu output
"""),
encoding="utf-8",
)
runner = CliRunner()
result = runner.invoke(main, ["--workflows-dir", str(workflows_dir)])
assert result.exit_code == 1
assert "bad.yml" in result.output
assert "check" in result.output
def test_all_workflows_pass(self, tmp_path: Path) -> None:
workflows_dir = tmp_path / "workflows"
workflows_dir.mkdir()
(workflows_dir / "ok.yml").write_text(
textwrap.dedent("""
name: OK
on: push
jobs:
deploy:
runs-on: docker
steps:
- run: tofu init
- run: tofu plan
"""),
encoding="utf-8",
)
runner = CliRunner()
result = runner.invoke(main, ["--workflows-dir", str(workflows_dir)])
assert result.exit_code == 0
assert "OK" in result.output