fix(docker_refresh): Skip recreation for unchanged images

This commit is contained in:
abdus committed 2026-10-04 14:00:24 +00:00
1 parent 48fe3f025e
commit e12feae399
2 files changed
+65 -11

No files matched your search

+38 -3
View File
@@ -46,6 +46,7 @@ def test_discovery_filters_and_groups_replicas(selected: set[str], expected: lis
("app:latest", True, "False", "other"),
]:
containers.append({
"Image": "sha256:running",
"State": {"Running": running},
"Config": {"Image": image, "Labels": {
"com.docker.compose.project": project,
@@ -60,6 +61,7 @@ def test_discovery_filters_and_groups_replicas(selected: set[str], expected: lis
assert [project.name for project in projects] == expected
for project in projects:
assert project.services == {"app"}
assert project.running_images == {"app": {"sha256:running"}}
assert project.files == (Path("/srv/web/compose.yml"), Path("/srv/web/override.yml"))
assert "--env-file" in project.command()
@@ -104,12 +106,45 @@ def test_refresh_commands_and_current_config_filtering(tmp_path: Path, dry_run:
"db": {"image": "db:16"},
},
}))
with patch.object(script.subprocess, "run", return_value=response) as run:
image_response = subprocess.CompletedProcess(args=[], returncode=0, stdout="sha256:new\n")
with patch.object(script.subprocess, "run", side_effect=[response, response, image_response, response]) as run:
script.refresh_project(project=project, dry_run=dry_run)
assert run.call_count == (1 if dry_run else 3)
assert run.call_count == (1 if dry_run else 4)
if not dry_run:
assert run.call_args_list[1].kwargs["args"] == [*project.command(), "pull", "--policy", "always", "app"]
assert run.call_args_list[2].kwargs["args"] == [*project.command(), "up", "--detach", "--no-deps", "--no-build", "--pull", "never", "app"]
assert run.call_args_list[2].kwargs["args"] == ["docker", "image", "inspect", "--format", "{{.Id}}", "app:latest"]
assert run.call_args_list[3].kwargs["args"] == [*project.command(), "up", "--detach", "--no-deps", "--no-build", "--pull", "never", "app"]
@pytest.mark.parametrize("running_images, expected_services", [
({"app": {"sha256:current"}, "worker": {"sha256:current"}}, []),
({"app": {"sha256:old"}, "worker": {"sha256:current"}}, ["app"]),
({"app": {"sha256:current", "sha256:old"}, "worker": {"sha256:current"}}, ["app"]),
({"app": {"sha256:old"}, "worker": {"sha256:old"}}, ["app", "worker"]),
])
def test_only_changed_services_are_redeployed(
tmp_path: Path, running_images: dict[str, set[str]], expected_services: list[str],
) -> None:
compose = tmp_path / "compose.yml"
compose.touch()
project = script.Project(
name="web", directory=tmp_path, files=(compose,), environment_files=(),
services={"app", "worker"}, running_images=running_images,
)
configuration = subprocess.CompletedProcess(args=[], returncode=0, stdout=json.dumps({
"services": {"app": {"image": "app:latest"}, "worker": {"image": "worker:latest"}},
}))
image_response = subprocess.CompletedProcess(args=[], returncode=0, stdout="sha256:current\n")
with patch.object(script.subprocess, "run", side_effect=[
configuration, configuration, image_response, image_response, configuration,
]) as run:
script.refresh_project(project=project, dry_run=False)
assert run.call_args_list[1].kwargs["args"] == [*project.command(), "pull", "--policy", "always", "app", "worker"]
assert run.call_count == (5 if expected_services else 4)
if expected_services:
assert run.call_args.kwargs["args"] == [
*project.command(), "up", "--detach", "--no-deps", "--no-build", "--pull", "never", *expected_services,
]
@pytest.mark.parametrize("build", [".", {"context": "."}])