fix: a game build is recognised before the archive integrity test, so re-extract no longer stalls on it
CI and images / lint (push) Successful in 2s
CI and images / extension-version (push) Successful in 2s
CI and images / frontend-build (push) Successful in 24s
CI and images / extension-test (push) Successful in 18s
CI and images / backend-lint-and-test (push) Successful in 47s
CI and images / integration (push) Successful in 2m44s
CI and images / sign-extension (push) Successful in 3s
CI and images / build-agent (push) Successful in 5s
CI and images / build-web (push) Successful in 2m1s
CI and images / smoke-web (push) Successful in 49s
CI and images / promote (push) Successful in 1s
CI and images / refresh-dev (push) Skipped
CI and images / unattended-failure (push) Skipped
CI and images / lint (push) Successful in 2s
CI and images / extension-version (push) Successful in 2s
CI and images / frontend-build (push) Successful in 24s
CI and images / extension-test (push) Successful in 18s
CI and images / backend-lint-and-test (push) Successful in 47s
CI and images / integration (push) Successful in 2m44s
CI and images / sign-extension (push) Successful in 3s
CI and images / build-agent (push) Successful in 5s
CI and images / build-web (push) Successful in 2m1s
CI and images / smoke-web (push) Successful in 49s
CI and images / promote (push) Successful in 1s
CI and images / refresh-dev (push) Skipped
CI and images / unattended-failure (push) Skipped
The archive probe read and checksummed every member before the importer looked at what the archive held. For a multi-gigabyte game build that is minutes of work on a file that is kept whole and never extracted, and it held a re-extract chunk far past its time budget. - The importer checks the archive's directory for a software build first, for the outer archive and for one nested inside an art pack, and only probes archives it may extract. - The probe rejects an archive over the size cap from its directory totals, before the integrity test decompresses anything. - Re-extract logs each archive as it starts and finishes, with its size and how long it took, so an archive that stalls a chunk is named in the log. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -305,3 +305,24 @@ def test_a_game_build_inside_an_art_pack_is_skipped_and_the_art_imported(importe
|
||||
assert r.status == "imported"
|
||||
assert len(r.member_image_ids) == 1
|
||||
assert importer.session.execute(select(func.count()).select_from(ImageRecord)).scalar_one() == 1
|
||||
|
||||
|
||||
def test_a_game_build_is_recognised_before_the_integrity_test(
|
||||
importer, import_layout, monkeypatch,
|
||||
):
|
||||
"""A multi-gigabyte build would spend minutes in the probe's read-everything
|
||||
test, only to be kept whole anyway, so its directory decides first."""
|
||||
from backend.app.utils import safe_probe
|
||||
|
||||
def _no_probe(_path, **_kw):
|
||||
raise AssertionError("a software build went through the archive probe")
|
||||
monkeypatch.setattr(safe_probe, "probe_archive", _no_probe)
|
||||
import_root, _ = import_layout
|
||||
arc = import_root / "Bob" / "MyGame-2.0-pc.zip"
|
||||
arc.parent.mkdir(parents=True, exist_ok=True)
|
||||
with zipfile.ZipFile(arc, "w") as zf:
|
||||
zf.writestr("MyGame/MyGame.exe", b"MZ")
|
||||
zf.writestr("MyGame/game/images/cg01.jpg", _split_bytes("v"))
|
||||
|
||||
assert importer.import_one(arc).status == "attached"
|
||||
assert importer.session.execute(select(func.count()).select_from(ImageRecord)).scalar_one() == 0
|
||||
|
||||
@@ -67,6 +67,23 @@ def test_run_probe_bomb_guard(tmp_path, monkeypatch):
|
||||
assert "bomb-guard cap" in detail
|
||||
|
||||
|
||||
def test_an_archive_over_the_cap_is_rejected_without_an_integrity_test(
|
||||
tmp_path, monkeypatch,
|
||||
):
|
||||
"""The size total is read from the directory, so an oversize archive never
|
||||
reaches the decompress-everything test."""
|
||||
monkeypatch.setattr(safe_probe, "MAX_ARCHIVE_UNCOMPRESSED_BYTES", 10)
|
||||
|
||||
def _no_test(_self):
|
||||
raise AssertionError("integrity test ran on an archive over the cap")
|
||||
monkeypatch.setattr(zipfile.ZipFile, "testzip", _no_test)
|
||||
z = tmp_path / "big.zip"
|
||||
_zip(z, {"big.txt": b"x" * 5000})
|
||||
status, detail = safe_probe._run_probe(str(z))
|
||||
assert status == "error"
|
||||
assert "bomb-guard cap" in detail
|
||||
|
||||
|
||||
def test_probe_video_non_video_is_not_ok(tmp_path):
|
||||
"""A text file is not a decodable video. Whether ffprobe is present
|
||||
(returncode != 0) or absent (OSError → 'unavailable'), the result is
|
||||
|
||||
Reference in New Issue
Block a user