LangGraph-based release automation agent with: - PR discovery (webhook + polling) - AI code review via Claude Code CLI (subscription-based) - Auto-create Jira tickets for PRs without ticket ID - Jira ticket lifecycle management (code review -> staging -> done) - CI/CD pipeline trigger, polling, and approval gates - Slack interactive messages with approval buttons - Per-repo semantic versioning - PostgreSQL persistence (threads, staging, releases) - FastAPI API (webhooks, approvals, status, manual triggers) - Docker Compose deployment 1069 tests, 95%+ coverage.
54 lines
2.0 KiB
Python
54 lines
2.0 KiB
Python
"""Tests for graph/full_cycle.py.
|
|
|
|
Tests that the full cycle graph composes pr_completed and release subgraphs
|
|
correctly, and that the routing conditional edge works as expected.
|
|
"""
|
|
|
|
from release_agent.graph.full_cycle import build_full_cycle_graph
|
|
from release_agent.graph.routing import should_continue_to_release
|
|
|
|
|
|
class TestBuildFullCycleGraph:
|
|
def test_returns_compiled_graph(self) -> None:
|
|
graph = build_full_cycle_graph()
|
|
assert graph is not None
|
|
|
|
def test_graph_can_be_built_multiple_times(self) -> None:
|
|
graph1 = build_full_cycle_graph()
|
|
graph2 = build_full_cycle_graph()
|
|
assert graph1 is not None
|
|
assert graph2 is not None
|
|
|
|
def test_graph_has_get_graph_method(self) -> None:
|
|
graph = build_full_cycle_graph()
|
|
assert hasattr(graph, "get_graph") or hasattr(graph, "nodes")
|
|
|
|
|
|
class TestFullCycleRouting:
|
|
"""Test that the routing function used by full_cycle correctly
|
|
determines whether to continue to the release subgraph."""
|
|
|
|
def test_continue_when_flag_true_and_no_errors(self) -> None:
|
|
state = {"continue_to_release": True, "errors": []}
|
|
assert should_continue_to_release(state) == "yes"
|
|
|
|
def test_stop_when_flag_false(self) -> None:
|
|
state = {"continue_to_release": False}
|
|
assert should_continue_to_release(state) == "no"
|
|
|
|
def test_stop_when_flag_missing(self) -> None:
|
|
state = {}
|
|
assert should_continue_to_release(state) == "no"
|
|
|
|
def test_stop_when_errors_present(self) -> None:
|
|
state = {"continue_to_release": True, "errors": ["some error"]}
|
|
assert should_continue_to_release(state) == "no"
|
|
|
|
def test_stop_when_flag_true_but_errors_present(self) -> None:
|
|
state = {"continue_to_release": True, "errors": ["critical failure"]}
|
|
assert should_continue_to_release(state) == "no"
|
|
|
|
def test_continue_when_errors_empty_list(self) -> None:
|
|
state = {"continue_to_release": True, "errors": []}
|
|
assert should_continue_to_release(state) == "yes"
|