Coverage for src/fastapi_cloud_cli/commands/env/delete.py: 100%

58 statements  

« prev     ^ index     » next       coverage.py v7.16.0, created at 2026-11-09 00:25 +0000

1from pathlib import Path 1klmnopq

2from typing import Annotated, Any 1klmnopq

3 

4import typer 1klmnopq

5from pydantic import BaseModel, Field 1klmnopq

6from rich_toolkit import RichToolkit 1klmnopq

7from rich_toolkit.menu import Option 1klmnopq

8 

9from fastapi_cloud_cli.api import APIClient 1klmnopq

10from fastapi_cloud_cli.commands._auth import UserCommand, get_user_command_context 1klmnopq

11from fastapi_cloud_cli.commands.env._app import env_app 1klmnopq

12from fastapi_cloud_cli.utils.apps import resolve_app_id_or_fail 1klmnopq

13from fastapi_cloud_cli.utils.env import validate_environment_variable_name 1klmnopq

14from fastapi_cloud_cli.utils.execution import JsonOutputOption 1klmnopq

15 

16 

17class EnvironmentVariableDeleteOutput(BaseModel): 1klmnopq

18 app_id: str 1klmnopq

19 name: str 1klmnopq

20 deleted: bool = True 1klmnopq

21 show_tag: Annotated[bool, Field(exclude=True)] = True 1klmnopq

22 

23 

24def _render_environment_variable_delete_output( 1klhmniopqj

25 data: EnvironmentVariableDeleteOutput, toolkit: RichToolkit 

26) -> None: 

27 if data.show_tag: 1rahbscidteufjg

28 toolkit.print_title("environment variables") 1rhsituj

29 

30 toolkit.print_line() 1rahbscidteufjg

31 toolkit.print(f"Environment variable [bold]{data.name}[/] deleted.", bullet=False) 1rahbscidteufjg

32 

33 

34@env_app.command(cls=UserCommand) 1klmnopq

35def delete( 2k l xbm n ybo p q zb

36 ctx: typer.Context, 

37 name: str | None = typer.Argument( 

38 None, 

39 help="The name of the environment variable to delete", 

40 ), 

41 path_arg: Annotated[ 

42 Path | None, 

43 typer.Argument( 

44 help=( 

45 "Path to the directory with your app's pyproject.toml " 

46 "(defaults to current directory)" 

47 ), 

48 ), 

49 ] = None, 

50 path: Annotated[ 

51 Path | None, 

52 typer.Option( 

53 "--path", 

54 help=( 

55 "Path to the directory with your app's pyproject.toml " 

56 "(defaults to current directory)" 

57 ), 

58 ), 

59 ] = None, 

60 app_id: Annotated[ 

61 str | None, 

62 typer.Option( 

63 "--app-id", 

64 help="ID of the app whose environment variable should be deleted.", 

65 ), 

66 ] = None, 

67 yes: Annotated[ 

68 bool, 

69 typer.Option( 

70 "--yes", 

71 "-y", 

72 help="Confirm deletion without prompting.", 

73 ), 

74 ] = False, 

75 no_redeploy: Annotated[ 

76 bool, 

77 typer.Option( 

78 "--no-redeploy", 

79 help="Delete the environment variable without redeploying the app.", 

80 ), 

81 ] = False, 

82 json_output: JsonOutputOption = False, 

83) -> Any: 

84 """ 

85 Delete an environment variable and redeploy the app by default. 

86 

87 Succeeds even if the variable is already absent. 

88 """ 

89 

90 toolkit = get_user_command_context(ctx).toolkit 2X Y jb= ` J K kb{ Z 0 C v r a 1 2 lb? | L M mb} 3 4 D w h b 5 6 nb@ ~ N O obab7 8 E x s c 9 ! pb[ bbP Q qbcb# $ F y i d % ' rb] dbR S sbeb( ) G z t e * + tb^ fbT U ubgb, - H A u f . / vb_ hbV W wbib: ; I B j g

91 

92 target_app_id = resolve_app_id_or_fail( 2X Y jb= ` J K kb{ Z 0 C v r a 1 2 lb? | L M mb} 3 4 D w h b 5 6 nb@ ~ N O obab7 8 E x s c 9 ! pb[ bbP Q qbcb# $ F y i d % ' rb] dbR S sbeb( ) G z t e * + tb^ fbT U ubgb, - H A u f . / vb_ hbV W wbib: ; I B j g

93 toolkit, app_id=app_id, path=path or path_arg 

94 ) 

95 name_provided = name is not None 2X Y = ` J K { Z 0 C v r a 1 2 ? | L M } 3 4 D w h b 5 6 @ ~ N O ab7 8 E x s c 9 ! [ bbP Q cb# $ F y i d % ' ] dbR S eb( ) G z t e * + ^ fbT U gb, - H A u f . / _ hbV W ib: ; I B j g

96 

97 with APIClient() as client: 2X Y = ` J K { Z 0 C v r a 1 2 ? | L M } 3 4 D w h b 5 6 @ ~ N O ab7 8 E x s c 9 ! [ bbP Q cb# $ F y i d % ' ] dbR S eb( ) G z t e * + ^ fbT U gb, - H A u f . / _ hbV W ib: ; I B j g

98 if not name: 2X Y = ` J K { Z 0 C v r a 1 2 ? | L M } 3 4 D w h b 5 6 @ ~ N O ab7 8 E x s c 9 ! [ bbP Q cb# $ F y i d % ' ] dbR S eb( ) G z t e * + ^ fbT U gb, - H A u f . / _ hbV W ib: ; I B j g

99 if toolkit.mode == "json": 2` C a | D b ~ E c bbF d dbG e fbH f hbI g

100 toolkit.fail( 2` | ~ bbdbfbhb

101 "missing_required_input", 

102 "Environment variable name is required.", 

103 hint="Pass NAME to choose an environment variable.", 

104 ) 

105 

106 with toolkit.progress( 1CaDbEcFdGeHfIg

107 "Fetching environment variables...", transient=True 

108 ) as progress: 

109 with client.handle_http_errors(progress, toolkit=toolkit): 1CaDbEcFdGeHfIg

110 environment_variables = client.get_environment_variables( 1CaDbEcFdGeHfIg

111 app_id=target_app_id 

112 ) 

113 

114 toolkit.print_title("environment variables") 1CaDbEcFdGeHfIg

115 toolkit.print_line() 1CaDbEcFdGeHfIg

116 

117 if not environment_variables.data: 1CaDbEcFdGeHfIg

118 toolkit.print("No environment variables found.", bullet=False) 1CDEFGHI

119 return 1CDEFGHI

120 

121 name = toolkit.ask( 1abcdefg

122 "Select the environment variable to delete:", 

123 options=[ 

124 Option({"name": env_var.name, "value": env_var.name}) 

125 for env_var in environment_variables.data 

126 ], 

127 bullet=False, 

128 ) 

129 

130 assert name 1abcdefg

131 else: 

132 if not validate_environment_variable_name(name): 2X Y = J K { Z 0 v r 1 2 ? L M } 3 4 w h 5 6 @ N O ab7 8 x s 9 ! [ P Q cb# $ y i % ' ] R S eb( ) z t * + ^ T U gb, - A u . / _ V W ib: ; B j

133 toolkit.fail( 2{ } abcbebgbib

134 "invalid_input", 

135 f"The environment variable name [bold]{name}[/] is invalid.", 

136 ) 

137 

138 toolkit.print_line() 1XY=JKZ0vr12?LM34wh56@NO78xs9![PQ#$yi%']RS()zt*+^TU,-Au./_VW:;Bj

139 

140 if name_provided and not yes: 1XY=JKZ0vra12?LM34whb56@NO78xsc9![PQ#$yid%']RS()zte*+^TU,-Auf./_VW:;Bjg

141 if toolkit.mode == "json": 1=vr?wh@xs[yi]zt^Au_Bj

142 toolkit.fail( 1=?@[]^_

143 "missing_required_input", 

144 "Deletion confirmation is required.", 

145 hint="Pass --yes to confirm deletion.", 

146 ) 

147 

148 should_delete = toolkit.confirm( 1vrwhxsyiztAuBj

149 f"Delete [bold]{name}[/]?", 

150 default=False, 

151 bullet=False, 

152 ) 

153 if not should_delete: 1vrwhxsyiztAuBj

154 toolkit.print_title("environment variables") 1vwxyzAB

155 toolkit.print_line() 1vwxyzAB

156 toolkit.print("Deletion cancelled.", bullet=False) 1vwxyzAB

157 raise typer.Exit(0) 1vwxyzAB

158 toolkit.print_line() 1rhsituj

159 

160 with toolkit.progress( 1XYJKZ0ra12LM34hb56NO78sc9!PQ#$id%'RS()te*+TU,-uf./VW:;jg

161 "Deleting environment variable", transient=True 

162 ) as progress: 

163 with client.handle_http_errors(progress, toolkit=toolkit): 1XYJKZ0ra12LM34hb56NO78sc9!PQ#$id%'RS()te*+TU,-uf./VW:;jg

164 client.batch_environment_variables( 1XYJKZ0ra12LM34hb56NO78sc9!PQ#$id%'RS()te*+TU,-uf./VW:;jg

165 app_id=target_app_id, 

166 upsert={}, 

167 delete=[name], 

168 redeploy=not no_redeploy, 

169 ) 

170 

171 toolkit.success( 1JKraLMhbNOscPQidRSteTUufVWjg

172 EnvironmentVariableDeleteOutput( 

173 app_id=target_app_id, name=name, show_tag=name_provided 

174 ), 

175 render_output=_render_environment_variable_delete_output, 

176 )