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
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ dependencies = [
"rich-toolkit >= 0.14.5",
"pydantic[email] >= 1.6.1",
"sentry-sdk >= 2.20.0",
"fastar >= 0.5.0",
"fastar >= 0.8.0",
]

[project.optional-dependencies]
Expand Down
2 changes: 1 addition & 1 deletion src/fastapi_cloud_cli/commands/deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def archive(path: Path, tar_path: Path) -> Path:
logger.debug("Archive will be created at: %s", tar_path)

file_count = 0
with fastar.open(tar_path, "w") as tar:
with fastar.open(tar_path, "w:zst") as tar:
for filename in files:
if filename.is_dir():
continue
Expand Down
88 changes: 60 additions & 28 deletions tests/test_archive.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import tarfile
from pathlib import Path

import fastar
import pytest

from fastapi_cloud_cli.commands.deploy import archive
Expand All @@ -13,6 +13,13 @@ def src_path(tmp_path: Path) -> Path:
return path


@pytest.fixture
def dst_path(tmp_path: Path) -> Path:
path = tmp_path / "destination"
path.mkdir()
return path


@pytest.fixture
def tar_path(tmp_path: Path) -> Path:
return tmp_path / "archive.tar"
Expand All @@ -29,7 +36,7 @@ def test_archive_creates_tar_file(src_path: Path, tar_path: Path) -> None:


def test_archive_excludes_venv_and_similar_folders(
src_path: Path, tar_path: Path
src_path: Path, tar_path: Path, dst_path: Path
) -> None:
"""Should exclude .venv directory from archive."""
# the only files we want to include
Expand All @@ -53,24 +60,38 @@ def test_archive_excludes_venv_and_similar_folders(

archive(src_path, tar_path)

with tarfile.open(tar_path, "r") as tar:
names = tar.getnames()
assert set(names) == {"main.py", "static/index.html"}
with fastar.open(tar_path, "r") as tar:
tar.unpack(dst_path)

assert set(dst_path.glob("**/*")) == {
dst_path / "main.py",
dst_path / "static",
dst_path / "static" / "index.html",
}


def test_archive_preserves_relative_paths(src_path: Path, tar_path: Path) -> None:
def test_archive_preserves_relative_paths(
src_path: Path, tar_path: Path, dst_path: Path
) -> None:
(src_path / "src").mkdir()
(src_path / "src" / "app").mkdir()
(src_path / "src" / "app" / "main.py").write_text("print('hello')")

archive(src_path, tar_path)

with tarfile.open(tar_path, "r") as tar:
names = tar.getnames()
assert names == ["src/app/main.py"]
with fastar.open(tar_path, "r") as tar:
tar.unpack(dst_path)

assert set(dst_path.glob("**/*")) == {
dst_path / "src",
dst_path / "src" / "app",
dst_path / "src" / "app" / "main.py",
}

def test_archive_respects_fastapicloudignore(src_path: Path, tar_path: Path) -> None:

def test_archive_respects_fastapicloudignore(
src_path: Path, tar_path: Path, dst_path: Path
) -> None:
"""Should exclude files specified in .fastapicloudignore."""
(src_path / "main.py").write_text("print('hello')")
(src_path / "config.py").write_text("CONFIG = 'value'")
Expand All @@ -82,16 +103,17 @@ def test_archive_respects_fastapicloudignore(src_path: Path, tar_path: Path) ->

archive(src_path, tar_path)

with tarfile.open(tar_path, "r") as tar:
names = tar.getnames()
assert set(names) == {
"main.py",
"config.py",
}
with fastar.open(tar_path, "r") as tar:
tar.unpack(dst_path)

assert set(dst_path.glob("**/*")) == {
dst_path / "main.py",
dst_path / "config.py",
}


def test_archive_respects_fastapicloudignore_unignore(
src_path: Path, tar_path: Path
src_path: Path, tar_path: Path, dst_path: Path
) -> None:
"""Test we can use .fastapicloudignore to unignore files inside .gitignore"""
(src_path / "main.py").write_text("print('hello')")
Expand All @@ -109,12 +131,20 @@ def test_archive_respects_fastapicloudignore_unignore(

archive(src_path, tar_path)

with tarfile.open(tar_path, "r") as tar:
names = tar.getnames()
assert set(names) == {"main.py", "static/build/style.css"}
with fastar.open(tar_path, "r") as tar:
tar.unpack(dst_path)

assert set(dst_path.glob("**/*")) == {
dst_path / "main.py",
dst_path / "static",
dst_path / "static" / "build",
dst_path / "static" / "build" / "style.css",
}

def test_archive_includes_hidden_files(src_path: Path, tar_path: Path) -> None:

def test_archive_includes_hidden_files(
src_path: Path, tar_path: Path, dst_path: Path
) -> None:
"""Should include hidden files in the archive by default."""
(src_path / "main.py").write_text("print('hello')")
(src_path / ".env").write_text("SECRET_KEY=xyz")
Expand All @@ -123,10 +153,12 @@ def test_archive_includes_hidden_files(src_path: Path, tar_path: Path) -> None:

archive(src_path, tar_path)

with tarfile.open(tar_path, "r") as tar:
names = tar.getnames()
assert set(names) == {
"main.py",
".env",
".config/settings.json",
}
with fastar.open(tar_path, "r") as tar:
tar.unpack(dst_path)

assert set(dst_path.glob("**/*")) == {
dst_path / "main.py",
dst_path / ".env",
dst_path / ".config",
dst_path / ".config" / "settings.json",
}