fix(release): package runtime SQL migrations
This commit is contained in:
@@ -14,6 +14,8 @@ from scripts import image_release
|
||||
COMMIT = "a" * 40
|
||||
DIGEST = "sha256:" + "b" * 64
|
||||
IMAGE_ID = "sha256:" + "c" * 64
|
||||
REPO = Path(__file__).resolve().parents[2]
|
||||
MIGRATION_DIR = REPO / "trex_core" / "adapters" / "persistence" / "sql"
|
||||
|
||||
|
||||
class RecordingRunner:
|
||||
@@ -78,16 +80,19 @@ def test_invalid_source_commit_is_rejected(commit):
|
||||
|
||||
def test_smoke_uses_exact_isolated_probes_and_cleans_containers():
|
||||
runner = RecordingRunner()
|
||||
image_release.smoke_image("candidate", runner, timeout=17)
|
||||
image_release.smoke_image("candidate", runner, timeout=17, migration_dir=MIGRATION_DIR)
|
||||
|
||||
runs = [call for call in runner.commands if call[0][:2] == ["docker", "run"]]
|
||||
removals = [call for call in runner.commands if call[0][:2] == ["docker", "rm"]]
|
||||
assert len(runs) == len(removals) == 4
|
||||
expected_migrations = tuple(sorted(path.name for path in MIGRATION_DIR.glob("*.sql")))
|
||||
assert expected_migrations
|
||||
assert len(runs) == len(removals) == 5
|
||||
assert [call[0][call[0].index("--entrypoint") + 1 :] for call in runs] == [
|
||||
["python", "candidate", "-c", "import trex_core"],
|
||||
["trex-core-daemon", "candidate", "--help"],
|
||||
["trex-core", "candidate", "--help"],
|
||||
["trex-core-reset", "candidate", "--help"],
|
||||
["python", "candidate", "-I", "-c", image_release.migration_inventory_code(expected_migrations)],
|
||||
]
|
||||
assert all("--network" in call[0] and "none" in call[0] for call in runs)
|
||||
assert all("--read-only" in call[0] and "--cap-drop" in call[0] for call in runs)
|
||||
@@ -95,6 +100,26 @@ def test_smoke_uses_exact_isolated_probes_and_cleans_containers():
|
||||
assert all("--config" not in call[0] and "--yes" not in call[0] for call in runs)
|
||||
|
||||
|
||||
def test_smoke_rejects_empty_canonical_migration_inventory(tmp_path):
|
||||
with pytest.raises(ValueError, match="canonical migration inventory is empty"):
|
||||
image_release.smoke_image("candidate", RecordingRunner(), migration_dir=tmp_path)
|
||||
|
||||
|
||||
def test_migration_inventory_probe_failure_propagates_after_cleanup():
|
||||
class FifthProbeFailsRunner(RecordingRunner):
|
||||
def run(self, command, *, input_text=None, timeout=None):
|
||||
run_count = len([call for call in self.commands if call[0][:2] == ["docker", "run"]])
|
||||
if list(command)[:2] == ["docker", "run"] and run_count == 4:
|
||||
self.commands.append((list(command), input_text, timeout))
|
||||
raise subprocess.CalledProcessError(1, command)
|
||||
return super().run(command, input_text=input_text, timeout=timeout)
|
||||
|
||||
runner = FifthProbeFailsRunner()
|
||||
with pytest.raises(RuntimeError, match="smoke probe 5 failed"):
|
||||
image_release.smoke_image("candidate", runner, migration_dir=MIGRATION_DIR)
|
||||
assert runner.commands[-1][0][:3] == ["docker", "rm", "--force"]
|
||||
|
||||
|
||||
def test_smoke_failure_propagates_after_cleanup():
|
||||
runner = RecordingRunner(fail_on=("docker", "run"))
|
||||
with pytest.raises(RuntimeError, match="smoke probe 1 failed"):
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import shutil
|
||||
import subprocess
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
REPO = Path(__file__).resolve().parents[2]
|
||||
MIGRATION_PACKAGE_PREFIX = "trex_core/adapters/persistence/sql/"
|
||||
|
||||
|
||||
def test_built_wheel_contains_exact_canonical_migration_inventory(tmp_path: Path):
|
||||
source = tmp_path / "source"
|
||||
source.mkdir()
|
||||
shutil.copy2(REPO / "pyproject.toml", source / "pyproject.toml")
|
||||
shutil.copytree(REPO / "trex_core", source / "trex_core")
|
||||
output = tmp_path / "dist"
|
||||
|
||||
subprocess.run(
|
||||
[
|
||||
"uv",
|
||||
"build",
|
||||
"--wheel",
|
||||
"--no-build-logs",
|
||||
"--no-create-gitignore",
|
||||
"--out-dir",
|
||||
str(output),
|
||||
str(source),
|
||||
],
|
||||
check=True,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
|
||||
wheels = list(output.glob("*.whl"))
|
||||
assert len(wheels) == 1
|
||||
expected = sorted(
|
||||
path.relative_to(REPO).as_posix()
|
||||
for path in (REPO / MIGRATION_PACKAGE_PREFIX).glob("*.sql")
|
||||
)
|
||||
assert expected
|
||||
with zipfile.ZipFile(wheels[0]) as wheel:
|
||||
actual = sorted(
|
||||
name
|
||||
for name in wheel.namelist()
|
||||
if name.startswith(MIGRATION_PACKAGE_PREFIX) and name.endswith(".sql")
|
||||
)
|
||||
assert actual == expected
|
||||
Reference in New Issue
Block a user