Retain current production image and one rollback baseline
This commit is contained in:
@@ -723,6 +723,50 @@ class Deploy:
|
||||
text = re.sub(r"https?://[^\s\"'<>]+", "[REDACTED-URL]", text)
|
||||
print("Scoped container logs (redacted):", text, flush=True)
|
||||
|
||||
def cleanup_images(self):
|
||||
"""Retain container references and the verified deployment's rollback baseline."""
|
||||
try:
|
||||
protected = {self.state["previous_image"]}
|
||||
container_ids = self.run("ps", "-aq").stdout.decode().split()
|
||||
if container_ids:
|
||||
containers = json.loads(self.run("inspect", *container_ids).stdout)
|
||||
protected.update(container["Image"] for container in containers)
|
||||
repo = self.env["PROD_IMAGE_REPO"]
|
||||
image_ids = (
|
||||
self.run("image", "ls", "--no-trunc", "-q", repo)
|
||||
.stdout.decode()
|
||||
.split()
|
||||
)
|
||||
if not image_ids:
|
||||
return
|
||||
images = json.loads(
|
||||
self.run("image", "inspect", *sorted(set(image_ids))).stdout
|
||||
)
|
||||
removed = 0
|
||||
for image in images:
|
||||
tags = image.get("RepoTags") or []
|
||||
# Shared images and unrelated tags are never cleanup targets.
|
||||
if image["Id"] in protected or not tags:
|
||||
continue
|
||||
if not all(
|
||||
re.fullmatch(
|
||||
re.escape(repo)
|
||||
+ r":(?:release-[0-9a-f]{40}-[0-9a-f]{8}|rollback-[0-9a-f]{32})",
|
||||
tag,
|
||||
)
|
||||
for tag in tags
|
||||
):
|
||||
continue
|
||||
result = self.run("image", "rm", *tags, check=False)
|
||||
if result.returncode:
|
||||
print("IMAGE RETENTION: referenced image retained", flush=True)
|
||||
else:
|
||||
removed += 1
|
||||
print(f"IMAGE RETENTION: removed {removed} obsolete images", flush=True)
|
||||
except Exception:
|
||||
# Cleanup failure must never roll back an already verified deployment.
|
||||
print("IMAGE RETENTION WARNING: cleanup deferred", flush=True)
|
||||
|
||||
def deploy(self):
|
||||
previous = self.preflight()
|
||||
self.lock()
|
||||
@@ -769,6 +813,7 @@ class Deploy:
|
||||
self.state["status"] = "success"
|
||||
self.state_io(self.state)
|
||||
print("DEPLOY VERIFIED", flush=True)
|
||||
self.cleanup_images()
|
||||
except BaseException as exc:
|
||||
print("DEPLOY FAILED:", type(exc).__name__, flush=True)
|
||||
self.diagnostics()
|
||||
|
||||
Reference in New Issue
Block a user