diff --git a/src/api_contract_guardian/cli.py b/src/api_contract_guardian/cli.py index ac65cca..47055d6 100644 --- a/src/api_contract_guardian/cli.py +++ b/src/api_contract_guardian/cli.py @@ -124,8 +124,8 @@ def check( fail_on_dangerous: bool = typer.Option( False, "--fail-on-dangerous/--allow-dangerous", help="Fail on dangerous changes", ), - max_breaking: int = typer.Option(0, "--max-breaking", help="Max allowed breaking changes (default 0)"), - max_dangerous: int = typer.Option(-1, "--max-dangerous", help="Max allowed dangerous changes (-1=unlimited)"), + max_breaking: int = typer.Option(-1, "--max-breaking", help="Max allowed breaking changes (-1=defer to flag, 0=none)"), + max_dangerous: int = typer.Option(-1, "--max-dangerous", help="Max allowed dangerous changes (-1=defer to flag, 0=none)"), output: str | None = typer.Option(None, "--output", "-o", help="Output file path"), ) -> None: """Gate CI pipeline on breaking changes. Returns exit code 1 if gate fails.""" diff --git a/src/api_contract_guardian/gate.py b/src/api_contract_guardian/gate.py index 3a066bd..0727418 100644 --- a/src/api_contract_guardian/gate.py +++ b/src/api_contract_guardian/gate.py @@ -33,7 +33,7 @@ def check_gate( *, fail_on_breaking: bool = True, fail_on_dangerous: bool = False, - max_breaking: int = 0, + max_breaking: int = -1, max_dangerous: int = -1, ) -> GateResult: """Check if a diff result passes the CI gate. @@ -52,21 +52,17 @@ def check_gate( dangerous_count = len(result.dangerous_changes) # Determine effective thresholds + # max_breaking >= 0 is an explicit ceiling — always honour it. + # When absent (-1, the default), fall back to fail_on_breaking flag. if max_breaking >= 0: - if fail_on_breaking or max_breaking > 0: # noqa: SIM108 - effective_max_breaking = max_breaking - else: - effective_max_breaking = -1 # unlimited + effective_max_breaking = max_breaking elif fail_on_breaking: effective_max_breaking = 0 # default: zero tolerance else: effective_max_breaking = -1 # unlimited if max_dangerous >= 0: - if fail_on_dangerous or max_dangerous > 0: # noqa: SIM108 - effective_max_dangerous = max_dangerous - else: - effective_max_dangerous = -1 # unlimited + effective_max_dangerous = max_dangerous elif fail_on_dangerous: effective_max_dangerous = 0 # default: zero tolerance else: diff --git a/tests/test_gate.py b/tests/test_gate.py index e1a5da0..31a591c 100644 --- a/tests/test_gate.py +++ b/tests/test_gate.py @@ -125,3 +125,15 @@ def test_fail_on_breaking_false_max_breaking_exceeded(self): result = _make_result(breaking=3) gate = check_gate(result, fail_on_breaking=False, max_breaking=1) assert not gate.passed + + def test_fail_on_breaking_false_max_breaking_zero_enforced(self): + """max_breaking=0 should still fail even when fail_on_breaking=False.""" + result = _make_result(breaking=1) + gate = check_gate(result, fail_on_breaking=False, max_breaking=0) + assert not gate.passed + + def test_fail_on_dangerous_false_max_dangerous_zero_enforced(self): + """max_dangerous=0 should still fail even when fail_on_dangerous=False.""" + result = _make_result(dangerous=1) + gate = check_gate(result, fail_on_breaking=False, max_dangerous=0) + assert not gate.passed