From 4ddb15d41ce2ecafd4d07e45aba94bc37f5c0354 Mon Sep 17 00:00:00 2001 From: Alejandra Date: Mon, 5 Jan 2026 11:48:24 +0100 Subject: [PATCH 1/6] =?UTF-8?q?=E2=9C=A8=20Add=20confirmation=20option=20w?= =?UTF-8?q?hen=20deploying=20the=20first=20time?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/fastapi_cloud_cli/commands/deploy.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/fastapi_cloud_cli/commands/deploy.py b/src/fastapi_cloud_cli/commands/deploy.py index 18146784..2c5272c5 100644 --- a/src/fastapi_cloud_cli/commands/deploy.py +++ b/src/fastapi_cloud_cli/commands/deploy.py @@ -322,6 +322,25 @@ def _configure_app(toolkit: RichToolkit, path_to_deploy: Path) -> AppConfig: toolkit.print_line() + toolkit.print("Deployment Configuration", tag="summary") + toolkit.print(f" Team: [bold]{team.name}[/bold]") + toolkit.print(f" App: [bold]{app_name}[/bold]") + toolkit.print_line() + + choice = toolkit.ask( + "Does everything look right?", + tag="confirm", + options=[ + Option({"name": "Yes, start the deployment!", "value": "deploy"}), + Option({"name": "No, let me start over", "value": "cancel"}), + ], + ) + toolkit.print_line() + + if choice == "cancel": + toolkit.print("Deployment cancelled.") + raise typer.Exit(0) + with toolkit.progress(title="Creating app...") as progress: with handle_http_errors(progress): app = _create_app(team.id, app_name) From e887c3be9034017aa2f23581bb768e456648cfa5 Mon Sep 17 00:00:00 2001 From: Alejandra Date: Mon, 5 Jan 2026 11:55:53 +0100 Subject: [PATCH 2/6] =?UTF-8?q?=E2=9C=85=20Update=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/test_cli_deploy.py | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/tests/test_cli_deploy.py b/tests/test_cli_deploy.py index 33976ed2..2b094b6d 100644 --- a/tests/test_cli_deploy.py +++ b/tests/test_cli_deploy.py @@ -316,7 +316,7 @@ def test_asks_for_app_name_after_team( def test_creates_app_on_backend( logged_in_cli: None, tmp_path: Path, respx_mock: respx.MockRouter ) -> None: - steps = [Keys.ENTER, Keys.ENTER, *"demo", Keys.ENTER] + steps = [Keys.ENTER, Keys.ENTER, *"demo", Keys.ENTER, Keys.ENTER] team = _get_random_team() @@ -344,6 +344,40 @@ def test_creates_app_on_backend( assert "App created successfully" in result.output +@pytest.mark.respx(base_url=settings.base_api_url) +def test_cancels_deployment_when_user_selects_no( + logged_in_cli: None, tmp_path: Path, respx_mock: respx.MockRouter +) -> None: + steps = [ + Keys.ENTER, + Keys.ENTER, + *"demo", + Keys.ENTER, + Keys.DOWN_ARROW, + Keys.ENTER, + ] + + team = _get_random_team() + + respx_mock.get("/teams/").mock( + return_value=Response( + 200, + json={"data": [team]}, + ) + ) + + with ( + changing_dir(tmp_path), + patch("rich_toolkit.container.getchar") as mock_getchar, + ): + mock_getchar.side_effect = steps + + result = runner.invoke(app, ["deploy"]) + + assert result.exit_code == 0 + assert "Deployment cancelled." in result.output + + @pytest.mark.respx(base_url=settings.base_api_url) def test_uses_existing_app( logged_in_cli: None, tmp_path: Path, respx_mock: respx.MockRouter @@ -383,6 +417,7 @@ def test_exits_successfully_when_deployment_is_done( Keys.ENTER, *"demo", Keys.ENTER, + Keys.ENTER, ] team_data = _get_random_team() @@ -633,6 +668,7 @@ def _deploy_without_waiting(respx_mock: respx.MockRouter, tmp_path: Path) -> Res Keys.ENTER, *"demo", Keys.ENTER, + Keys.ENTER, ] team_data = _get_random_team() From 6e9f1969107ced580cc0f2e5e4e01972e3811c66 Mon Sep 17 00:00:00 2001 From: Alejandra Date: Mon, 5 Jan 2026 12:21:30 +0100 Subject: [PATCH 3/6] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Update?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/fastapi_cloud_cli/commands/deploy.py | 51 +++++++++++++----------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/src/fastapi_cloud_cli/commands/deploy.py b/src/fastapi_cloud_cli/commands/deploy.py index 2c5272c5..bee4cd5d 100644 --- a/src/fastapi_cloud_cli/commands/deploy.py +++ b/src/fastapi_cloud_cli/commands/deploy.py @@ -294,6 +294,8 @@ def _configure_app(toolkit: RichToolkit, path_to_deploy: Path) -> AppConfig: toolkit.print_line() + selected_app: AppResponse | None = None + if not create_new_app: with toolkit.progress("Fetching apps...") as progress: with handle_http_errors( @@ -310,37 +312,40 @@ def _configure_app(toolkit: RichToolkit, path_to_deploy: Path) -> AppConfig: raise typer.Exit(1) - app = toolkit.ask( + selected_app = toolkit.ask( "Select the app you want to deploy to:", options=[Option({"name": app.slug, "value": app}) for app in apps], ) - else: - app_name = toolkit.input( - title="What's your app name?", - default=_get_app_name(path_to_deploy), - ) - toolkit.print_line() + app_name = selected_app.slug if selected_app else toolkit.input( + title="What's your app name?", + default=_get_app_name(path_to_deploy), + ) - toolkit.print("Deployment Configuration", tag="summary") - toolkit.print(f" Team: [bold]{team.name}[/bold]") - toolkit.print(f" App: [bold]{app_name}[/bold]") - toolkit.print_line() + toolkit.print_line() - choice = toolkit.ask( - "Does everything look right?", - tag="confirm", - options=[ - Option({"name": "Yes, start the deployment!", "value": "deploy"}), - Option({"name": "No, let me start over", "value": "cancel"}), - ], - ) - toolkit.print_line() + toolkit.print("Deployment Configuration", tag="summary") + toolkit.print(f" Team: [bold]{team.name}[/bold]") + toolkit.print(f" App: [bold]{app_name}[/bold]") + toolkit.print_line() - if choice == "cancel": - toolkit.print("Deployment cancelled.") - raise typer.Exit(0) + choice = toolkit.ask( + "Does everything look right?", + tag="confirm", + options=[ + Option({"name": "Yes, start the deployment!", "value": "deploy"}), + Option({"name": "No, let me start over", "value": "cancel"}), + ], + ) + toolkit.print_line() + + if choice == "cancel": + toolkit.print("Deployment cancelled.") + raise typer.Exit(0) + if selected_app: + app = selected_app + else: with toolkit.progress(title="Creating app...") as progress: with handle_http_errors(progress): app = _create_app(team.id, app_name) From bdbcfc8e37885adc5c439060b6d5d7a1c495aa4b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 5 Jan 2026 11:21:50 +0000 Subject: [PATCH 4/6] =?UTF-8?q?=F0=9F=8E=A8=20Auto=20format?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/fastapi_cloud_cli/commands/deploy.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/fastapi_cloud_cli/commands/deploy.py b/src/fastapi_cloud_cli/commands/deploy.py index bee4cd5d..161a043d 100644 --- a/src/fastapi_cloud_cli/commands/deploy.py +++ b/src/fastapi_cloud_cli/commands/deploy.py @@ -317,9 +317,13 @@ def _configure_app(toolkit: RichToolkit, path_to_deploy: Path) -> AppConfig: options=[Option({"name": app.slug, "value": app}) for app in apps], ) - app_name = selected_app.slug if selected_app else toolkit.input( - title="What's your app name?", - default=_get_app_name(path_to_deploy), + app_name = ( + selected_app.slug + if selected_app + else toolkit.input( + title="What's your app name?", + default=_get_app_name(path_to_deploy), + ) ) toolkit.print_line() From f40c40494917163f144d31fa96fd932edd0ef146 Mon Sep 17 00:00:00 2001 From: Alejandra Date: Mon, 5 Jan 2026 12:44:21 +0100 Subject: [PATCH 5/6] =?UTF-8?q?=E2=9C=85=20Fix=20coverage=20exclusion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/fastapi_cloud_cli/commands/deploy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fastapi_cloud_cli/commands/deploy.py b/src/fastapi_cloud_cli/commands/deploy.py index 161a043d..70d26567 100644 --- a/src/fastapi_cloud_cli/commands/deploy.py +++ b/src/fastapi_cloud_cli/commands/deploy.py @@ -347,7 +347,7 @@ def _configure_app(toolkit: RichToolkit, path_to_deploy: Path) -> AppConfig: toolkit.print("Deployment cancelled.") raise typer.Exit(0) - if selected_app: + if selected_app: # pragma: no cover app = selected_app else: with toolkit.progress(title="Creating app...") as progress: From 109565f3fd3c4bc2d50a0b58f0d5182a5e245ee5 Mon Sep 17 00:00:00 2001 From: Patrick Arminio Date: Fri, 9 Jan 2026 15:17:55 +0000 Subject: [PATCH 6/6] Update layout --- src/fastapi_cloud_cli/commands/deploy.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/fastapi_cloud_cli/commands/deploy.py b/src/fastapi_cloud_cli/commands/deploy.py index 70d26567..5b6536f5 100644 --- a/src/fastapi_cloud_cli/commands/deploy.py +++ b/src/fastapi_cloud_cli/commands/deploy.py @@ -328,9 +328,10 @@ def _configure_app(toolkit: RichToolkit, path_to_deploy: Path) -> AppConfig: toolkit.print_line() - toolkit.print("Deployment Configuration", tag="summary") - toolkit.print(f" Team: [bold]{team.name}[/bold]") - toolkit.print(f" App: [bold]{app_name}[/bold]") + toolkit.print("Deployment configuration:", tag="summary") + toolkit.print_line() + toolkit.print(f"Team: [bold]{team.name}[/bold]") + toolkit.print(f"App name: [bold]{app_name}[/bold]") toolkit.print_line() choice = toolkit.ask(