Retain only the verified production latest image

This commit is contained in:
渡口浪人
2026-10-12 20:51:08 +08:00
parent df1eba74e8
commit b46fbea4c9
3 changed files with 47 additions and 30 deletions
+21 -11
View File
@@ -337,6 +337,12 @@ class Deploy:
def rollback(self, previous):
self.activate(previous)
self.verify(previous)
self.run(
"image",
"tag",
previous["services"]["pigway-frame-flow"]["image"],
self.env["PROD_IMAGE_REPO"] + ":latest",
)
print("ROLLBACK VERIFIED", flush=True)
def secret_config(self):
@@ -392,7 +398,9 @@ class Deploy:
command += ["--build-arg", key + "=" + value]
self.run(*command, str(ROOT))
service = config["services"]["pigway-frame-flow"]
service["image"] = image
latest = self.env["PROD_IMAGE_REPO"] + ":latest"
self.run("image", "tag", image, latest)
service["image"] = latest
proposed = self.secret_config()
service["environment"].update(proposed)
for key in ("SYNOLOGY_PHOTOS_URL", "SYNOLOGY_PHOTOS_CERT_SHA256"):
@@ -666,6 +674,7 @@ class Deploy:
self.state["status"] = "success"
self.state_io(self.state)
print("BOOTSTRAP VERIFIED", flush=True)
self.cleanup_images()
except BaseException:
print("BOOTSTRAP FAILED", flush=True)
self.diagnostics()
@@ -726,9 +735,9 @@ class Deploy:
print("Scoped container logs (redacted):", text, flush=True)
def cleanup_images(self):
"""Retain container references and the verified deployment's rollback baseline."""
"""Keep only latest after verification; protect unrelated container images."""
try:
protected = {self.state["previous_image"]}
protected = set()
referenced_tags = set()
container_ids = self.run("ps", "-aq").stdout.decode().split()
if container_ids:
@@ -758,22 +767,23 @@ class Deploy:
if not all(
re.fullmatch(
re.escape(repo)
+ r":(?:release-[0-9a-f]{40}-[0-9a-f]{8}(?:-rollback)?|rollback-[0-9a-f]{32})",
+ r":(?:latest|release-[0-9a-f]{40}-[0-9a-f]{8}(?:-rollback)?|rollback-[0-9a-f]{32})",
tag,
)
for tag in tags
):
continue
if image["Id"] == self.state["previous_image"]:
pin = self.state.get("rollback_tag")
# Untag duplicates only after the rollback alias is present.
if pin not in tags:
latest = repo + ":latest"
if image["Id"] in protected:
# Current production uses latest. Other containers retain
# their referenced tags and images, even when stopped.
if latest not in tags:
continue
tags = [
tag for tag in tags if tag != pin and tag not in referenced_tags
tag
for tag in tags
if tag != latest and tag not in referenced_tags
]
elif image["Id"] in protected:
continue
if not tags:
continue
result = self.run("image", "rm", *tags, check=False)