diff --git a/src/fastapi_cloud_cli/commands/logs.py b/src/fastapi_cloud_cli/commands/logs.py index 2bcbd4b..645d215 100644 --- a/src/fastapi_cloud_cli/commands/logs.py +++ b/src/fastapi_cloud_cli/commands/logs.py @@ -40,6 +40,8 @@ } SINCE_PATTERN = re.compile(r"^\d+[smhd]$") +MIN_LOG_TAIL = 1 +MAX_LOG_TAIL = 1000 class AppLogsOutput(BaseModel): @@ -57,6 +59,15 @@ def _validate_since(value: str) -> str: return value +def _validate_tail(value: int) -> int: + if not MIN_LOG_TAIL <= value <= MAX_LOG_TAIL: + raise typer.BadParameter( + f"Invalid value. Use a number between {MIN_LOG_TAIL} and {MAX_LOG_TAIL}." + ) + + return value + + def _get_log_bullet(log: AppLogEntry) -> str: """Colored indicator rendered in the emoji bullet column. @@ -214,8 +225,9 @@ def logs( 100, "--tail", "-t", - help="Number of log lines to show before streaming.", + help=f"Number of log lines to show before streaming (max {MAX_LOG_TAIL}).", show_default=True, + callback=_validate_tail, ), since: str = typer.Option( "5m", diff --git a/tests/test_logs.py b/tests/test_logs.py index e7725a4..0a3dfde 100644 --- a/tests/test_logs.py +++ b/tests/test_logs.py @@ -540,6 +540,19 @@ def test_rejects_invalid_since_format( assert "Invalid format" in result.output +@pytest.mark.parametrize("invalid_tail", [0, 1001]) +def test_rejects_invalid_tail( + logged_in_cli: None, + configured_app: ConfiguredApp, + invalid_tail: int, +) -> None: + with changing_dir(configured_app.path): + result = runner.invoke(app, ["logs", "--tail", str(invalid_tail)]) + + assert result.exit_code == 2 + assert "between 1 and 1000" in result.output + + @pytest.mark.respx @pytest.mark.parametrize( "valid_since",