Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 33 additions & 4 deletions src/fastapi_cloud_cli/commands/deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -310,18 +312,45 @@ 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(

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()
toolkit.print_line()

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(
"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: # pragma: no cover
app = selected_app
else:
with toolkit.progress(title="Creating app...") as progress:
with handle_http_errors(progress):
app = _create_app(team.id, app_name)
Expand Down
38 changes: 37 additions & 1 deletion tests/test_cli_deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -383,6 +417,7 @@ def test_exits_successfully_when_deployment_is_done(
Keys.ENTER,
*"demo",
Keys.ENTER,
Keys.ENTER,
]

team_data = _get_random_team()
Expand Down Expand Up @@ -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()
Expand Down