refactor(image-cache): replace warn_if_stale with StaleImageError; add launch template
- image_cache: StaleImageError exception + check_stale/check_stale_path (raise instead of warn) - BottleBackend.launch: template method (skip_stale flag) that calls _image_stale_checks then _launch_impl - Each backend: _image_stale_checks delegates to a stale_checks() function in its launch module; _launch_impl replaces launch override - macos_container: adds image_created_at to util, cached-image support in _build_images, stale_checks - cli/start.py: catches StaleImageError, prompts interactively, retries with skip_stale=True; headless mode dies on it
This commit is contained in:
@@ -45,7 +45,7 @@ from ...git_gate import (
|
||||
provision_git_gate_dynamic_keys,
|
||||
revoke_git_gate_provisioned_keys,
|
||||
)
|
||||
from ...image_cache import warn_if_stale_path
|
||||
from ...image_cache import check_stale_path
|
||||
from ...log import die, info, warn
|
||||
from ...bottle_state import (
|
||||
egress_state_dir,
|
||||
@@ -471,8 +471,6 @@ def _agent_from_path(plan: SmolmachinesBottlePlan) -> Path:
|
||||
committed_path = Path(committed)
|
||||
if committed_path.is_file():
|
||||
info(f"using committed smolmachine {str(committed_path)!r}")
|
||||
if _image_policy(plan) == "cached":
|
||||
warn_if_stale_path("agent smolmachine artifact", committed_path)
|
||||
return committed_path
|
||||
|
||||
if _image_policy(plan) == "cached":
|
||||
@@ -488,6 +486,32 @@ def _agent_from_path(plan: SmolmachinesBottlePlan) -> Path:
|
||||
)
|
||||
|
||||
|
||||
def stale_checks(plan: SmolmachinesBottlePlan) -> None:
|
||||
"""Raise StaleImageError if a cached smolmachine artifact is older than the
|
||||
configured threshold. Only runs when image_policy is 'cached'. Checks the
|
||||
committed agent artifact first, then the cache-keyed agent and sidecar
|
||||
artifacts. Called by the backend class's _image_stale_checks before any
|
||||
resources are allocated."""
|
||||
if _image_policy(plan) != "cached":
|
||||
return
|
||||
committed = read_committed_image(plan.slug)
|
||||
if committed:
|
||||
committed_path = Path(committed)
|
||||
if committed_path.is_file():
|
||||
check_stale_path("agent smolmachine artifact", committed_path)
|
||||
elif docker_mod.image_exists(plan.agent_image):
|
||||
digest = docker_mod.image_id(plan.agent_image).split(":", 1)[-1][:16]
|
||||
artifact = _SMOLMACHINE_CACHE_DIR / f"{digest}.smolmachine.smolmachine"
|
||||
if artifact.is_file():
|
||||
check_stale_path("agent smolmachine artifact", artifact)
|
||||
sidecar_image = _bundle.SIDECAR_BUNDLE_IMAGE
|
||||
if docker_mod.image_exists(sidecar_image):
|
||||
digest = docker_mod.image_id(sidecar_image).split(":", 1)[-1][:16]
|
||||
sidecar_artifact = _SMOLMACHINE_CACHE_DIR / f"{digest}.smolmachine.smolmachine"
|
||||
if sidecar_artifact.is_file():
|
||||
check_stale_path("sidecar smolmachine artifact", sidecar_artifact)
|
||||
|
||||
|
||||
def _image_policy(plan: object) -> str:
|
||||
spec = getattr(plan, "spec", None)
|
||||
return str(getattr(spec, "image_policy", "fresh"))
|
||||
@@ -513,7 +537,6 @@ def _cached_smolmachine(image_ref: str, *, label: str) -> Path:
|
||||
"run without --cached-images to build it"
|
||||
)
|
||||
info(f"using cached {label} smolmachine {str(sidecar)!r}")
|
||||
warn_if_stale_path(f"{label} smolmachine artifact", sidecar)
|
||||
return sidecar
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user