Skip to content
Open
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
21 changes: 15 additions & 6 deletions src/flyte/_code_bundle/_packaging.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,12 +164,21 @@ def create_bundle(
# entry shouldn't abort the entire bundle.
logger.warning(f"Skipping {ws_file}: resolves outside source root {abs_source}")
continue
tar.add(
os.path.join(source, ws_file),
recursive=False,
arcname=rel_path,
filter=tar_strip_file_attributes,
)
try:
tar.add(
os.path.join(source, ws_file),
recursive=False,
arcname=rel_path,
filter=tar_strip_file_attributes,
)
except FileNotFoundError:
# The file list (``ls``) is computed by walking the source tree, but a
# file can vanish between listing and ``tar.add`` stat-ing it — most
# commonly transient artifacts like lock files (e.g.
# ".codegraph/codegraph.lock", FLYTE-SDK-52). A disappearing file is an
# environment race, not an SDK bug, and shouldn't abort the whole bundle.
logger.warning(f"Skipping {ws_file}: vanished before it could be added to the code bundle")
continue

size_mbs = tar_path.stat().st_size / 1024 / 1024
_compress_tarball(tar_path, archive_fname)
Expand Down
30 changes: 30 additions & 0 deletions tests/flyte/code_bundle/test_code_bundle.py
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,36 @@ def test_create_bundle_skips_symlinks_pointing_outside_source():
assert "python_bin" in member_names


def test_create_bundle_skips_files_that_vanish_before_add():
"""
Regression FLYTE-SDK-52: the file list is computed by walking the source tree, but a
file can disappear between listing and ``tar.add`` stat-ing it — most commonly a
transient lock file (e.g. ``.codegraph/codegraph.lock``). Previously this raised a raw
``FileNotFoundError`` and aborted the whole deploy. A vanished file should now be
skipped with a warning, and the rest of the bundle should still be produced.
"""
with tempfile.TemporaryDirectory() as tmpdir:
source = pathlib.Path(tmpdir)
output_dir = source / "output"
output_dir.mkdir()

(source / "main.py").write_text("print('hello')")
# A path that is in the file list but does not exist on disk — simulates a
# lock file that was deleted between listing and bundling.
vanished = source / ".codegraph" / "codegraph.lock"

files = [str(source / "main.py"), str(vanished)]

# Should succeed despite the missing file rather than raising FileNotFoundError.
archive_path, _, _ = create_bundle(source, output_dir, files, "test_digest")

with tarfile.open(archive_path, "r:gz") as tar:
member_names = tar.getnames()

assert "main.py" in member_names
assert ".codegraph/codegraph.lock" not in member_names


def test_list_all_files_returns_strings():
"""Test that list_all_files returns string paths (not pathlib.Path objects)."""
with tempfile.TemporaryDirectory() as tmpdir:
Expand Down
Loading