refactor: BottleImages dataclass, prelaunch_checks, build_or_load_images
Addresses review comments 3098, 3099, 3100 on PR #336: - Add BottleImages(agent, sidecar) dataclass to backend/__init__.py. Docker/macOS backends use str image refs; smolmachines uses Path artifacts. Replaces the singular `image` variable from the canonical pattern in comment 3100. - Replace _image_stale_checks/skip_stale with public prelaunch_checks(). CLI now calls backend.prelaunch_checks(plan) before backend.launch(plan); if StaleImageError is raised and the operator confirms, launch proceeds without re-checking. Removes the while-True/skip_stale retry loop. - Add abstract _build_or_load_images(plan) -> BottleImages to BottleBackend. launch() calls it then passes images to _launch_impl. Each backend implements both methods. - Fix comment 3098 (macos-container): _build_images is removed. build_or_load_images() has separate fresh/cached code paths — the cached path never calls a build helper. - Update _start_bundle (smolmachines) to accept sidecar_artifact: Path directly. Sidecar artifact resolution moves to _sidecar_from_path(), called by build_or_load_images alongside _agent_from_path().
This commit is contained in:
@@ -11,7 +11,7 @@ from typing import cast
|
||||
from unittest.mock import patch
|
||||
|
||||
from bot_bottle.agent_provider import AgentProvisionPlan
|
||||
from bot_bottle.backend import BottleSpec
|
||||
from bot_bottle.backend import BottleImages, BottleSpec
|
||||
from bot_bottle.backend.macos_container import launch
|
||||
from bot_bottle.backend.macos_container.bottle_plan import MacosContainerBottlePlan
|
||||
from bot_bottle.egress import EgressPlan
|
||||
@@ -339,9 +339,9 @@ class TestMacosContainerLaunchCommittedImage(unittest.TestCase):
|
||||
), patch.object(
|
||||
launch.container_mod, "build_image", side_effect=fake_build,
|
||||
), patch.object(launch, "info"):
|
||||
updated = launch._build_images(plan)
|
||||
images = launch.build_or_load_images(plan)
|
||||
|
||||
self.assertEqual("bot-bottle-committed-dev-abc:latest", updated.image)
|
||||
self.assertEqual("bot-bottle-committed-dev-abc:latest", images.agent)
|
||||
self.assertEqual(1, len(calls))
|
||||
self.assertEqual(launch.SIDECAR_BUNDLE_IMAGE, calls[0][0])
|
||||
|
||||
@@ -360,9 +360,9 @@ class TestMacosContainerLaunchCommittedImage(unittest.TestCase):
|
||||
), patch.object(
|
||||
launch.container_mod, "build_image", side_effect=fake_build,
|
||||
):
|
||||
updated = launch._build_images(plan)
|
||||
images = launch.build_or_load_images(plan)
|
||||
|
||||
self.assertEqual("bot-bottle-agent:latest", updated.image)
|
||||
self.assertEqual("bot-bottle-agent:latest", images.agent)
|
||||
self.assertEqual(2, len(calls))
|
||||
self.assertEqual("bot-bottle-agent:latest", calls[1][0])
|
||||
|
||||
@@ -395,7 +395,7 @@ class TestMacosContainerLaunchCachedImages(unittest.TestCase):
|
||||
launch, "die", side_effect=Die(),
|
||||
):
|
||||
with self.assertRaises(Die):
|
||||
launch._build_images(plan)
|
||||
launch.build_or_load_images(plan)
|
||||
|
||||
def test_cached_mode_dies_when_sidecar_image_missing(self) -> None:
|
||||
plan = self._cached_plan()
|
||||
@@ -411,7 +411,7 @@ class TestMacosContainerLaunchCachedImages(unittest.TestCase):
|
||||
launch, "die", side_effect=Die(),
|
||||
):
|
||||
with self.assertRaises(Die):
|
||||
launch._build_images(plan)
|
||||
launch.build_or_load_images(plan)
|
||||
|
||||
def test_cached_mode_both_present_returns_unchanged_plan(self) -> None:
|
||||
plan = self._cached_plan()
|
||||
@@ -422,10 +422,10 @@ class TestMacosContainerLaunchCachedImages(unittest.TestCase):
|
||||
), patch.object(
|
||||
launch.container_mod, "build_image",
|
||||
) as build, patch.object(launch, "info"):
|
||||
result = launch._build_images(plan)
|
||||
images = launch.build_or_load_images(plan)
|
||||
|
||||
build.assert_not_called()
|
||||
self.assertEqual(plan.image, result.image)
|
||||
self.assertEqual(plan.image, images.agent)
|
||||
|
||||
def test_committed_image_plus_cached_skips_sidecar_build(self) -> None:
|
||||
plan = self._cached_plan()
|
||||
@@ -437,11 +437,11 @@ class TestMacosContainerLaunchCachedImages(unittest.TestCase):
|
||||
), patch.object(
|
||||
launch.container_mod, "build_image",
|
||||
) as build, patch.object(launch, "info"):
|
||||
result = launch._build_images(plan)
|
||||
images = launch.build_or_load_images(plan)
|
||||
|
||||
# In cached mode with a committed image, no builds should fire.
|
||||
build.assert_not_called()
|
||||
self.assertEqual("bot-bottle-committed-dev-abc:latest", result.image)
|
||||
self.assertEqual("bot-bottle-committed-dev-abc:latest", images.agent)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user