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
28 changes: 22 additions & 6 deletions src/fastapi_cloud_cli/commands/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,13 @@ def set(
help="A path to the folder containing the app you want to deploy"
),
] = None,
secret: Annotated[
bool,
typer.Option(
"--secret",
help="Mark the environment variable as secret",
),
] = False,
) -> Any:
"""
Set an environment variable for the app.
Expand Down Expand Up @@ -233,12 +240,18 @@ def set(
raise typer.Exit(1)

if not name:
name = toolkit.input("Enter the name of the environment variable to set:")
if secret:
name = toolkit.input("Enter the name of the secret to set:")
else:
name = toolkit.input(
"Enter the name of the environment variable to set:"
)

if not value:
value = toolkit.input(
"Enter the value of the environment variable to set:", password=True
)
if secret:
value = toolkit.input("Enter the secret value:", password=True)
else:
value = toolkit.input("Enter the value of the environment variable:")

with toolkit.progress(
"Setting environment variable", transient=True
Expand All @@ -247,6 +260,9 @@ def set(
assert value is not None

with handle_http_errors(progress):
_set_environment_variable(app_config.app_id, name, value)
_set_environment_variable(app_config.app_id, name, value, secret)

toolkit.print(f"Environment variable [bold]{name}[/] set.")
if secret:
toolkit.print(f"Secret environment variable [bold]{name}[/] set.")
else:
toolkit.print(f"Environment variable [bold]{name}[/] set.")
56 changes: 53 additions & 3 deletions tests/test_env_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,10 @@ def test_shows_a_message_if_app_is_not_configured(logged_in_cli: None) -> None:
def test_shows_a_message_if_something_is_wrong(
logged_in_cli: None, respx_mock: respx.MockRouter, configured_app: Path
) -> None:
respx_mock.post("/apps/123/environment-variables/").mock(return_value=Response(500))
respx_mock.post(
"/apps/123/environment-variables/",
json={"name": "SOME_VAR", "value": "secret", "is_secret": False},
).mock(return_value=Response(500))

with changing_dir(configured_app):
result = runner.invoke(app, ["env", "set", "SOME_VAR", "secret"])
Expand All @@ -63,7 +66,10 @@ def test_shows_a_message_if_something_is_wrong(
def test_shows_message_when_it_sets(
logged_in_cli: None, respx_mock: respx.MockRouter, configured_app: Path
) -> None:
respx_mock.post("/apps/123/environment-variables/").mock(return_value=Response(200))
respx_mock.post(
"/apps/123/environment-variables/",
json={"name": "SOME_VAR", "value": "secret", "is_secret": False},
).mock(return_value=Response(200))

with changing_dir(configured_app):
result = runner.invoke(app, ["env", "set", "SOME_VAR", "secret"])
Expand All @@ -78,7 +84,10 @@ def test_asks_for_name_and_value(
) -> None:
steps = [*"SOME_VAR", Keys.ENTER, *"secret", Keys.ENTER]

respx_mock.post("/apps/123/environment-variables/").mock(return_value=Response(200))
respx_mock.post(
"/apps/123/environment-variables/",
json={"name": "SOME_VAR", "value": "secret", "is_secret": False},
).mock(return_value=Response(200))

with (
changing_dir(configured_app),
Expand All @@ -93,4 +102,45 @@ def test_asks_for_name_and_value(

assert "Environment variable SOME_VAR set" in result.output


@pytest.mark.respx(base_url=settings.base_api_url)
def test_asks_for_name_and_value_for_secret(
logged_in_cli: None, respx_mock: respx.MockRouter, configured_app: Path
) -> None:
steps = [*"SOME_VAR", Keys.ENTER, *"secret", Keys.ENTER]

respx_mock.post(
"/apps/123/environment-variables/",
json={"name": "SOME_VAR", "value": "secret", "is_secret": True},
).mock(return_value=Response(200))

with (
changing_dir(configured_app),
patch("rich_toolkit.container.getchar", side_effect=steps),
):
result = runner.invoke(app, ["env", "set", "--secret"])

assert result.exit_code == 0

assert "Enter the name of the secret" in result.output
assert "Enter the secret value" in result.output

assert "Secret environment variable SOME_VAR set" in result.output

assert "*" * 6 in result.output


@pytest.mark.respx(base_url=settings.base_api_url)
def test_sets_secret_flag(
logged_in_cli: None, respx_mock: respx.MockRouter, configured_app: Path
) -> None:
respx_mock.post(
"/apps/123/environment-variables/",
json={"name": "SOME_VAR", "value": "secret", "is_secret": True},
).mock(return_value=Response(200))

with changing_dir(configured_app):
result = runner.invoke(app, ["env", "set", "SOME_VAR", "secret", "--secret"])

assert result.exit_code == 0
assert "Secret environment variable SOME_VAR set" in result.output