Fix Jenkins-update flow: redeploy_project pull + delete_image safety + delete_container
Bug fixes from product test: 1. redeploy_project: BUILD_FAILED now includes explicit image pull (stop → pull → start) 2. delete_image: Distinguishes running vs stopped containers, suggests system_prune for stopped refs 3. New tool delete_container: Verify stopped state before deletion, confirmation required Tests added for all three paths plus stopped-container edge cases. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -100,6 +100,7 @@ async def test_list_projects_tool():
|
||||
def decorator(fn):
|
||||
tools[fn.__name__] = fn
|
||||
return fn
|
||||
|
||||
return decorator
|
||||
|
||||
register_projects(MockMCP(), config, client)
|
||||
@@ -128,6 +129,7 @@ async def test_stop_project_requires_confirmation():
|
||||
def decorator(fn):
|
||||
tools[fn.__name__] = fn
|
||||
return fn
|
||||
|
||||
return decorator
|
||||
|
||||
register_projects(MockMCP(), config, client)
|
||||
@@ -154,6 +156,7 @@ async def test_redeploy_project_requires_confirmation():
|
||||
def decorator(fn):
|
||||
tools[fn.__name__] = fn
|
||||
return fn
|
||||
|
||||
return decorator
|
||||
|
||||
register_projects(MockMCP(), config, client)
|
||||
@@ -183,6 +186,7 @@ def make_projects_tools(client):
|
||||
def decorator(fn):
|
||||
tools[fn.__name__] = fn
|
||||
return fn
|
||||
|
||||
return decorator
|
||||
|
||||
register_projects(MockMCP(), config, client)
|
||||
@@ -249,7 +253,7 @@ async def test_redeploy_stopped_project_starts_directly():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_redeploy_build_failed_project():
|
||||
"""BUILD_FAILED project: force-stop (non-fatal), then start."""
|
||||
"""BUILD_FAILED project: stop, pull images, then start (3 steps)."""
|
||||
client = AsyncMock()
|
||||
calls = []
|
||||
|
||||
@@ -265,13 +269,16 @@ async def test_redeploy_build_failed_project():
|
||||
assert "redeployed successfully" in result
|
||||
methods = [m for _, m in calls]
|
||||
assert "stop" in methods
|
||||
assert "pull" in methods # New: pull step
|
||||
assert "start" in methods
|
||||
assert methods.index("stop") < methods.index("start")
|
||||
# Order: stop → pull → start
|
||||
assert methods.index("stop") < methods.index("pull")
|
||||
assert methods.index("pull") < methods.index("start")
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_redeploy_build_failed_stop_error_nonfatal():
|
||||
"""BUILD_FAILED: stop failure must not abort the redeploy."""
|
||||
"""BUILD_FAILED: stop/pull failure must not abort the redeploy."""
|
||||
from mcp_synology_container.dsm_client import SynologyError
|
||||
|
||||
client = AsyncMock()
|
||||
@@ -281,6 +288,8 @@ async def test_redeploy_build_failed_stop_error_nonfatal():
|
||||
return project_list("BUILD_FAILED")
|
||||
if method == "stop":
|
||||
raise SynologyError("already stopped", code=2101)
|
||||
if method == "pull":
|
||||
raise SynologyError("pull failed", code=2102)
|
||||
return {} # start succeeds
|
||||
|
||||
client.request.side_effect = mock_request
|
||||
|
||||
Reference in New Issue
Block a user