Skip to content

Commit

Permalink
Merge pull request fastapi#36 from fastapilabs/09-17-_allow_to_use_an…
Browse files Browse the repository at this point in the history
…_existing_app

✨ Allow to use an existing app
  • Loading branch information
patrick91 authored Sep 17, 2024
2 parents 020a92f + 62e562d commit d4ec2cd
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 15 deletions.
57 changes: 47 additions & 10 deletions src/fastapi_cli/commands/deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,16 @@ def _get_app(app_slug: str) -> Optional[AppResponse]:
return AppResponse.model_validate(data)


def _get_apps(team_slug: str) -> List[AppResponse]:
with APIClient() as client:
response = client.get("/apps/", params={"team_slug": team_slug})
response.raise_for_status()

data = response.json()["data"]

return [AppResponse.model_validate(app) for app in data]


class DeploymentResponse(BaseModel):
id: str
app_id: str
Expand Down Expand Up @@ -216,25 +226,52 @@ def _configure_app(

toolkit.print_line()

app_name = toolkit.input(
title="What's your app name?",
tag="app",
default=_get_app_name(path_to_deploy),
create_new_app = toolkit.confirm(
"Do you want to create a new app?", tag="app", default=True
)

toolkit.print_line()

with toolkit.progress(title="Creating app...") as progress:
with handle_http_errors(progress):
app_data = _create_app(team.id, app_name)
if not create_new_app:
with toolkit.progress("Fetching apps...") as progress:
with handle_http_errors(
progress, message="Error fetching apps. Please try again later."
):
apps = _get_apps(team.slug)

toolkit.print_line()

if not apps:
toolkit.print(
"No apps found in this team. You can create a new app instead.",
)

raise typer.Exit(1)

app = toolkit.ask(
"Select the app you want to deploy to:",
tag="app",
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()

with toolkit.progress(title="Creating app...") as progress:
with handle_http_errors(progress):
app = _create_app(team.id, app_name)

progress.log(f"App created successfully! App slug: {app_data.slug}")
progress.log(f"App created successfully! App slug: {app.slug}")

app_config = AppConfig(app_id=app_data.id, team_id=team.id)
app_config = AppConfig(app_id=app.id, team_id=team.id)

write_app_config(path_to_deploy, app_config)

return app_config, app_data
return app_config, app


def _wait_for_deployment(
Expand Down
53 changes: 48 additions & 5 deletions tests/test_cli_deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def test_shows_teams(
def test_asks_for_app_name_after_team(
logged_in_cli: None, tmp_path: Path, respx_mock: respx.MockRouter
) -> None:
steps = [ENTER, ENTER, CTRL_C]
steps = [ENTER, ENTER, ENTER, CTRL_C]

respx_mock.get("/teams/").mock(
return_value=Response(
Expand Down Expand Up @@ -151,7 +151,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 = [ENTER, ENTER, *"demo", ENTER]
steps = [ENTER, ENTER, ENTER, *"demo", ENTER]

respx_mock.get("/teams/").mock(
return_value=Response(
Expand Down Expand Up @@ -181,11 +181,54 @@ def test_creates_app_on_backend(
assert "App created successfully" 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
) -> None:
steps = [ENTER, ENTER, RIGHT_ARROW, ENTER, *"demo", ENTER]

respx_mock.get("/teams/").mock(
return_value=Response(
200,
json={
"data": [
{"name": "team1", "slug": "team1", "id": "123"},
]
},
)
)

respx_mock.get("/apps/", params={"team_slug": "team1"}).mock(
return_value=Response(
200,
json={
"data": [
{
"name": "App called demo",
"slug": "app-called-demo",
"id": "1234",
},
]
},
)
)

with changing_dir(tmp_path), patch("click.getchar") as mock_getchar:
mock_getchar.side_effect = steps

result = runner.invoke(app, ["deploy"])

assert result.exit_code == 1

assert "Select the app you want to deploy to:" in result.output
assert "app-called-demo" in result.output


@pytest.mark.respx(base_url=settings.base_api_url)
def test_creates_and_uploads_deployment_then_fails(
logged_in_cli: None, tmp_path: Path, respx_mock: respx.MockRouter
) -> None:
steps = [ENTER, ENTER, *"demo", ENTER]
steps = [ENTER, ENTER, ENTER, *"demo", ENTER]

respx_mock.get("/teams/").mock(
return_value=Response(
Expand Down Expand Up @@ -264,7 +307,7 @@ def test_creates_and_uploads_deployment_then_fails(
def test_exists_successfully_when_deployment_is_done(
logged_in_cli: None, tmp_path: Path, respx_mock: respx.MockRouter
) -> None:
steps = [ENTER, ENTER, *"demo", ENTER]
steps = [ENTER, ENTER, ENTER, *"demo", ENTER]

respx_mock.get("/teams/").mock(
return_value=Response(
Expand Down Expand Up @@ -429,7 +472,7 @@ def test_shows_error_when_app_does_not_exist(
def test_can_skip_waiting(
logged_in_cli: None, tmp_path: Path, respx_mock: respx.MockRouter
) -> None:
steps = [ENTER, ENTER, *"demo", ENTER]
steps = [ENTER, ENTER, ENTER, *"demo", ENTER]

respx_mock.get("/teams/").mock(
return_value=Response(
Expand Down

0 comments on commit d4ec2cd

Please sign in to comment.