fastapi-cloud-cli 0.22.1__tar.gz → 0.23.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/PKG-INFO +2 -2
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/pyproject.toml +2 -2
- fastapi_cloud_cli-0.23.0/src/fastapi_cloud_cli/__init__.py +1 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/deploy/cloud.py +23 -3
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/deploy/command.py +19 -1
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/deploy/upload.py +4 -1
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/utils/api.py +3 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/tests/test_cli_deploy.py +136 -0
- fastapi_cloud_cli-0.22.1/src/fastapi_cloud_cli/__init__.py +0 -1
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/LICENSE +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/README.md +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/scripts/add_latest_release_date.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/scripts/format.sh +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/scripts/lint.sh +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/scripts/prepare_release.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/scripts/test-cov-html.sh +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/scripts/test.sh +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/__main__.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/cli.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/__init__.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/_flow.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/apps/__init__.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/apps/create.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/apps/get.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/apps/link.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/apps/list.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/apps/unlink.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/apps/update.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/auth/__init__.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/auth/wait.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/ci/__init__.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/ci/print_workflow.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/deploy/__init__.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/deploy/archive.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/deploy/configure.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/deploy/wait.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/deployments.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/env/__init__.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/env/_shared.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/env/delete.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/env/get.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/env/list.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/env/set.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/login.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/logout.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/logs.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/setup_ci.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/teams/__init__.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/teams/get.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/tokens/__init__.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/tokens/create.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/tokens/delete.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/tokens/list.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/whoami.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/config.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/logging.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/py.typed +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/utils/__init__.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/utils/apps.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/utils/auth.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/utils/cli.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/utils/config.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/utils/dates.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/utils/env.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/utils/errors.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/utils/execution.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/utils/progress_file.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/utils/sentry.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/utils/version_check.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/tests/__init__.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/tests/conftest.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/tests/test_api_client.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/tests/test_archive.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/tests/test_auth.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/tests/test_cli.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/tests/test_cli_apps.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/tests/test_cli_ci.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/tests/test_cli_deployments.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/tests/test_cli_link.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/tests/test_cli_login.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/tests/test_cli_logout.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/tests/test_cli_setup_ci.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/tests/test_cli_teams.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/tests/test_cli_tokens.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/tests/test_cli_unlink.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/tests/test_cli_whoami.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/tests/test_config.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/tests/test_dates.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/tests/test_deploy_utils.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/tests/test_env_delete.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/tests/test_env_get.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/tests/test_env_list.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/tests/test_env_set.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/tests/test_logs.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/tests/test_prepare_release.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/tests/test_progress_file.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/tests/test_sentry.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/tests/test_utils_apps.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/tests/test_version_check.py +0 -0
- {fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/tests/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: fastapi-cloud-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.23.0
|
|
4
4
|
Summary: Deploy and manage FastAPI Cloud apps from the command line 🚀
|
|
5
5
|
Author-Email: Patrick Arminio <patrick@fastapilabs.com>
|
|
6
6
|
License: MIT
|
|
@@ -33,7 +33,7 @@ Requires-Dist: typer>=0.16.0
|
|
|
33
33
|
Requires-Dist: uvicorn[standard]>=0.17.6
|
|
34
34
|
Requires-Dist: rignore>=0.5.1
|
|
35
35
|
Requires-Dist: httpx>=0.27.0
|
|
36
|
-
Requires-Dist: rich-toolkit>=0.20.
|
|
36
|
+
Requires-Dist: rich-toolkit>=0.20.3
|
|
37
37
|
Requires-Dist: pydantic[email]>=2.7.4; python_version < "3.13"
|
|
38
38
|
Requires-Dist: pydantic[email]>=2.8.0; python_version == "3.13"
|
|
39
39
|
Requires-Dist: pydantic[email]>=2.12.0; python_version >= "3.14"
|
|
@@ -33,7 +33,7 @@ dependencies = [
|
|
|
33
33
|
"uvicorn[standard] >= 0.17.6",
|
|
34
34
|
"rignore >= 0.5.1",
|
|
35
35
|
"httpx >= 0.27.0",
|
|
36
|
-
"rich-toolkit>=0.20.
|
|
36
|
+
"rich-toolkit>=0.20.3",
|
|
37
37
|
"pydantic[email] >= 2.7.4; python_version < '3.13'",
|
|
38
38
|
"pydantic[email] >= 2.8.0; python_version == '3.13'",
|
|
39
39
|
"pydantic[email] >= 2.12.0; python_version >= '3.14'",
|
|
@@ -41,7 +41,7 @@ dependencies = [
|
|
|
41
41
|
"fastar >= 0.10.0",
|
|
42
42
|
"detect-installer>=0.1.0",
|
|
43
43
|
]
|
|
44
|
-
version = "0.
|
|
44
|
+
version = "0.23.0"
|
|
45
45
|
|
|
46
46
|
[project.license]
|
|
47
47
|
text = "MIT"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.23.0"
|
{fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/deploy/cloud.py
RENAMED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
from pydantic import BaseModel
|
|
2
2
|
|
|
3
|
-
from fastapi_cloud_cli.utils.api import
|
|
3
|
+
from fastapi_cloud_cli.utils.api import (
|
|
4
|
+
APIClient,
|
|
5
|
+
DeploymentStatus,
|
|
6
|
+
_get_response_error_message,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ArchiveTooLargeError(Exception):
|
|
11
|
+
pass
|
|
4
12
|
|
|
5
13
|
|
|
6
14
|
class Team(BaseModel):
|
|
@@ -57,8 +65,20 @@ def _create_app(
|
|
|
57
65
|
return AppResponse.model_validate(response.json())
|
|
58
66
|
|
|
59
67
|
|
|
60
|
-
def _create_deployment(
|
|
61
|
-
|
|
68
|
+
def _create_deployment(
|
|
69
|
+
client: APIClient, app_id: str, archive_size_bytes: int
|
|
70
|
+
) -> CreateDeploymentResponse:
|
|
71
|
+
response = client.post(
|
|
72
|
+
f"/apps/{app_id}/deployments/",
|
|
73
|
+
json={"archive_size_bytes": archive_size_bytes},
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
if response.status_code == 413:
|
|
77
|
+
raise ArchiveTooLargeError(
|
|
78
|
+
_get_response_error_message(response)
|
|
79
|
+
or "The app source code exceeds the maximum allowed size."
|
|
80
|
+
)
|
|
81
|
+
|
|
62
82
|
response.raise_for_status()
|
|
63
83
|
|
|
64
84
|
return CreateDeploymentResponse.model_validate(response.json())
|
|
@@ -9,6 +9,7 @@ from pydantic import BaseModel
|
|
|
9
9
|
from fastapi_cloud_cli.commands.deploy.archive import _get_large_files, archive
|
|
10
10
|
from fastapi_cloud_cli.commands.deploy.cloud import (
|
|
11
11
|
AppResponse,
|
|
12
|
+
ArchiveTooLargeError,
|
|
12
13
|
CreateDeploymentResponse,
|
|
13
14
|
_create_deployment,
|
|
14
15
|
_get_app,
|
|
@@ -313,6 +314,7 @@ def deploy(
|
|
|
313
314
|
logger.debug("Creating archive for deployment")
|
|
314
315
|
archive_path = Path(temp_dir) / "archive.tar"
|
|
315
316
|
archive(path_to_deploy, archive_path)
|
|
317
|
+
archive_size = archive_path.stat().st_size
|
|
316
318
|
|
|
317
319
|
with (
|
|
318
320
|
toolkit.progress(
|
|
@@ -324,7 +326,22 @@ def deploy(
|
|
|
324
326
|
client.handle_http_errors(progress, toolkit=toolkit),
|
|
325
327
|
):
|
|
326
328
|
logger.debug("Creating deployment for app: %s", app.id)
|
|
327
|
-
|
|
329
|
+
|
|
330
|
+
try:
|
|
331
|
+
deployment = _create_deployment(
|
|
332
|
+
client=client,
|
|
333
|
+
app_id=app.id,
|
|
334
|
+
archive_size_bytes=archive_size,
|
|
335
|
+
)
|
|
336
|
+
except ArchiveTooLargeError as e:
|
|
337
|
+
toolkit.fail(
|
|
338
|
+
"invalid_input",
|
|
339
|
+
str(e),
|
|
340
|
+
hint=(
|
|
341
|
+
"You can exclude files from the deployment "
|
|
342
|
+
"with a .fastapicloudignore file."
|
|
343
|
+
),
|
|
344
|
+
)
|
|
328
345
|
|
|
329
346
|
try:
|
|
330
347
|
progress.log(
|
|
@@ -335,6 +352,7 @@ def deploy(
|
|
|
335
352
|
fastapi_client=client,
|
|
336
353
|
deployment_id=deployment.id,
|
|
337
354
|
archive_path=archive_path,
|
|
355
|
+
archive_size=archive_size,
|
|
338
356
|
progress=progress,
|
|
339
357
|
)
|
|
340
358
|
|
|
@@ -43,9 +43,9 @@ def _upload_deployment(
|
|
|
43
43
|
fastapi_client: APIClient,
|
|
44
44
|
deployment_id: str,
|
|
45
45
|
archive_path: Path,
|
|
46
|
+
archive_size: int,
|
|
46
47
|
progress: Progress,
|
|
47
48
|
) -> CreateDeploymentResponse:
|
|
48
|
-
archive_size = archive_path.stat().st_size
|
|
49
49
|
archive_size_str = _format_size(archive_size)
|
|
50
50
|
|
|
51
51
|
progress.log(f"Uploading deployment ({archive_size_str})...")
|
|
@@ -79,6 +79,9 @@ def _upload_deployment(
|
|
|
79
79
|
files={"file": cast(BinaryIO, archive_file_with_progress)},
|
|
80
80
|
)
|
|
81
81
|
|
|
82
|
+
if upload_response.is_error:
|
|
83
|
+
logger.debug("File upload failed with response: %s", upload_response.text)
|
|
84
|
+
|
|
82
85
|
upload_response.raise_for_status()
|
|
83
86
|
logger.debug("File upload completed successfully")
|
|
84
87
|
|
|
@@ -146,6 +146,7 @@ class DeploymentStatus(str, Enum):
|
|
|
146
146
|
building = "building"
|
|
147
147
|
extracting = "extracting"
|
|
148
148
|
extracting_failed = "extracting_failed"
|
|
149
|
+
extracting_failed_archive_too_large = "extracting_failed_archive_too_large"
|
|
149
150
|
building_image = "building_image"
|
|
150
151
|
building_image_failed = "building_image_failed"
|
|
151
152
|
deploying = "deploying"
|
|
@@ -166,6 +167,7 @@ class DeploymentStatus(str, Enum):
|
|
|
166
167
|
cls.building: "Building",
|
|
167
168
|
cls.extracting: "Extracting Upload",
|
|
168
169
|
cls.extracting_failed: "Extraction Failed",
|
|
170
|
+
cls.extracting_failed_archive_too_large: "Archive Too Large",
|
|
169
171
|
cls.building_image: "Building Image",
|
|
170
172
|
cls.building_image_failed: "Build Failed",
|
|
171
173
|
cls.deploying: "Deploying Image",
|
|
@@ -186,6 +188,7 @@ FAILED_STATUSES = {
|
|
|
186
188
|
DeploymentStatus.deploying_failed,
|
|
187
189
|
DeploymentStatus.building_image_failed,
|
|
188
190
|
DeploymentStatus.extracting_failed,
|
|
191
|
+
DeploymentStatus.extracting_failed_archive_too_large,
|
|
189
192
|
}
|
|
190
193
|
TERMINAL_STATUSES = SUCCESSFUL_STATUSES | FAILED_STATUSES
|
|
191
194
|
|
|
@@ -1672,6 +1672,142 @@ def test_cancel_upload_swallows_exceptions(
|
|
|
1672
1672
|
assert "HTTPStatusError" not in result.output
|
|
1673
1673
|
|
|
1674
1674
|
|
|
1675
|
+
def _mock_deploy_until_upload(
|
|
1676
|
+
respx_mock: respx.MockRouter,
|
|
1677
|
+
tmp_path: Path,
|
|
1678
|
+
app_data: RandomApp,
|
|
1679
|
+
deployment_data: dict[str, str],
|
|
1680
|
+
upload_response: Response,
|
|
1681
|
+
) -> None:
|
|
1682
|
+
app_id = app_data["id"]
|
|
1683
|
+
|
|
1684
|
+
config_path = tmp_path / ".fastapicloud" / "cloud.json"
|
|
1685
|
+
config_path.parent.mkdir(parents=True, exist_ok=True)
|
|
1686
|
+
config_path.write_text(f'{{"app_id": "{app_id}", "team_id": "some-team-id"}}')
|
|
1687
|
+
|
|
1688
|
+
respx_mock.get(f"/apps/{app_id}").mock(return_value=Response(200, json=app_data))
|
|
1689
|
+
respx_mock.post(f"/apps/{app_id}/deployments/").mock(
|
|
1690
|
+
return_value=Response(201, json=deployment_data)
|
|
1691
|
+
)
|
|
1692
|
+
respx_mock.post(f"/deployments/{deployment_data['id']}/upload").mock(
|
|
1693
|
+
return_value=Response(
|
|
1694
|
+
200,
|
|
1695
|
+
json={"url": "http://test.com", "fields": {"key": "value"}},
|
|
1696
|
+
)
|
|
1697
|
+
)
|
|
1698
|
+
respx_mock.post("http://test.com", data={"key": "value"}).mock(
|
|
1699
|
+
return_value=upload_response
|
|
1700
|
+
)
|
|
1701
|
+
|
|
1702
|
+
|
|
1703
|
+
def _mock_deploy_until_deployment_creation(
|
|
1704
|
+
respx_mock: respx.MockRouter,
|
|
1705
|
+
tmp_path: Path,
|
|
1706
|
+
app_data: RandomApp,
|
|
1707
|
+
creation_response: Response,
|
|
1708
|
+
) -> respx.Route:
|
|
1709
|
+
app_id = app_data["id"]
|
|
1710
|
+
|
|
1711
|
+
config_path = tmp_path / ".fastapicloud" / "cloud.json"
|
|
1712
|
+
config_path.parent.mkdir(parents=True, exist_ok=True)
|
|
1713
|
+
config_path.write_text(f'{{"app_id": "{app_id}", "team_id": "some-team-id"}}')
|
|
1714
|
+
|
|
1715
|
+
respx_mock.get(f"/apps/{app_id}").mock(return_value=Response(200, json=app_data))
|
|
1716
|
+
|
|
1717
|
+
return respx_mock.post(f"/apps/{app_id}/deployments/").mock(
|
|
1718
|
+
return_value=creation_response
|
|
1719
|
+
)
|
|
1720
|
+
|
|
1721
|
+
|
|
1722
|
+
@pytest.mark.respx
|
|
1723
|
+
def test_deploy_shows_error_when_creation_rejects_archive_size(
|
|
1724
|
+
logged_in_cli: None, tmp_path: Path, respx_mock: respx.MockRouter
|
|
1725
|
+
) -> None:
|
|
1726
|
+
app_data = _get_random_app()
|
|
1727
|
+
|
|
1728
|
+
# no upload routes are mocked, any upload attempt would fail the test
|
|
1729
|
+
create_deployment_route = _mock_deploy_until_deployment_creation(
|
|
1730
|
+
respx_mock,
|
|
1731
|
+
tmp_path,
|
|
1732
|
+
app_data,
|
|
1733
|
+
Response(
|
|
1734
|
+
413,
|
|
1735
|
+
json={
|
|
1736
|
+
"detail": "App source code exceeds the maximum allowed size of 1000.0 MB"
|
|
1737
|
+
},
|
|
1738
|
+
),
|
|
1739
|
+
)
|
|
1740
|
+
|
|
1741
|
+
with changing_dir(tmp_path):
|
|
1742
|
+
result = runner.invoke(app, ["deploy"])
|
|
1743
|
+
|
|
1744
|
+
output = " ".join(result.output.split())
|
|
1745
|
+
|
|
1746
|
+
assert result.exit_code == 1
|
|
1747
|
+
assert "App source code exceeds the maximum allowed size of 1000.0 MB" in output
|
|
1748
|
+
assert ".fastapicloudignore" in output
|
|
1749
|
+
assert "Something went wrong" not in output
|
|
1750
|
+
|
|
1751
|
+
request_body = json.loads(create_deployment_route.calls.last.request.content)
|
|
1752
|
+
assert request_body["archive_size_bytes"] > 0
|
|
1753
|
+
|
|
1754
|
+
|
|
1755
|
+
@pytest.mark.respx
|
|
1756
|
+
def test_deploy_json_shows_error_when_creation_rejects_archive_size(
|
|
1757
|
+
logged_in_cli: None, tmp_path: Path, respx_mock: respx.MockRouter
|
|
1758
|
+
) -> None:
|
|
1759
|
+
app_data = _get_random_app()
|
|
1760
|
+
|
|
1761
|
+
_mock_deploy_until_deployment_creation(
|
|
1762
|
+
respx_mock,
|
|
1763
|
+
tmp_path,
|
|
1764
|
+
app_data,
|
|
1765
|
+
Response(
|
|
1766
|
+
413,
|
|
1767
|
+
json={
|
|
1768
|
+
"detail": "App source code exceeds the maximum allowed size of 1000.0 MB"
|
|
1769
|
+
},
|
|
1770
|
+
),
|
|
1771
|
+
)
|
|
1772
|
+
|
|
1773
|
+
with changing_dir(tmp_path):
|
|
1774
|
+
result = runner.invoke(app, ["deploy", "--json"])
|
|
1775
|
+
|
|
1776
|
+
assert result.exit_code == 1
|
|
1777
|
+
|
|
1778
|
+
error = json.loads(result.stdout)["error"]
|
|
1779
|
+
assert error["code"] == "invalid_input"
|
|
1780
|
+
assert (
|
|
1781
|
+
error["message"]
|
|
1782
|
+
== "App source code exceeds the maximum allowed size of 1000.0 MB"
|
|
1783
|
+
)
|
|
1784
|
+
assert error["hint"] == (
|
|
1785
|
+
"You can exclude files from the deployment with a .fastapicloudignore file."
|
|
1786
|
+
)
|
|
1787
|
+
|
|
1788
|
+
|
|
1789
|
+
@pytest.mark.respx
|
|
1790
|
+
def test_deploy_shows_error_when_upload_fails(
|
|
1791
|
+
logged_in_cli: None, tmp_path: Path, respx_mock: respx.MockRouter
|
|
1792
|
+
) -> None:
|
|
1793
|
+
app_data = _get_random_app()
|
|
1794
|
+
deployment_data = _get_random_deployment(app_id=app_data["id"])
|
|
1795
|
+
|
|
1796
|
+
_mock_deploy_until_upload(
|
|
1797
|
+
respx_mock,
|
|
1798
|
+
tmp_path,
|
|
1799
|
+
app_data,
|
|
1800
|
+
deployment_data,
|
|
1801
|
+
Response(400, text="not an xml body"),
|
|
1802
|
+
)
|
|
1803
|
+
|
|
1804
|
+
with changing_dir(tmp_path):
|
|
1805
|
+
result = runner.invoke(app, ["deploy"])
|
|
1806
|
+
|
|
1807
|
+
assert result.exit_code == 1
|
|
1808
|
+
assert "Something went wrong" in result.output
|
|
1809
|
+
|
|
1810
|
+
|
|
1675
1811
|
@pytest.mark.respx
|
|
1676
1812
|
def test_deploy_successfully_with_token(
|
|
1677
1813
|
logged_out_cli: None, tmp_path: Path, respx_mock: respx.MockRouter
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.22.1"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/__init__.py
RENAMED
|
File without changes
|
{fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/_flow.py
RENAMED
|
File without changes
|
|
File without changes
|
{fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/apps/create.py
RENAMED
|
File without changes
|
{fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/apps/get.py
RENAMED
|
File without changes
|
{fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/apps/link.py
RENAMED
|
File without changes
|
{fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/apps/list.py
RENAMED
|
File without changes
|
{fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/apps/unlink.py
RENAMED
|
File without changes
|
{fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/apps/update.py
RENAMED
|
File without changes
|
|
File without changes
|
{fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/auth/wait.py
RENAMED
|
File without changes
|
{fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/ci/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/deploy/wait.py
RENAMED
|
File without changes
|
{fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/deployments.py
RENAMED
|
File without changes
|
{fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/env/__init__.py
RENAMED
|
File without changes
|
{fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/env/_shared.py
RENAMED
|
File without changes
|
{fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/env/delete.py
RENAMED
|
File without changes
|
{fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/env/get.py
RENAMED
|
File without changes
|
{fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/env/list.py
RENAMED
|
File without changes
|
{fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/env/set.py
RENAMED
|
File without changes
|
{fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/login.py
RENAMED
|
File without changes
|
{fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/logout.py
RENAMED
|
File without changes
|
{fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/logs.py
RENAMED
|
File without changes
|
{fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/setup_ci.py
RENAMED
|
File without changes
|
|
File without changes
|
{fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/teams/get.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/tokens/list.py
RENAMED
|
File without changes
|
{fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/commands/whoami.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/utils/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/utils/execution.py
RENAMED
|
File without changes
|
{fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/utils/progress_file.py
RENAMED
|
File without changes
|
|
File without changes
|
{fastapi_cloud_cli-0.22.1 → fastapi_cloud_cli-0.23.0}/src/fastapi_cloud_cli/utils/version_check.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|