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:
@@ -247,6 +247,76 @@ async def test_container_stats_found():
|
||||
assert "Block I/O" in result
|
||||
|
||||
|
||||
# ──────────────────────────────────────────────────────────────────────────────
|
||||
# delete_container
|
||||
# ──────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_delete_container_preview():
|
||||
from mcp_synology_container.modules.containers import register_containers
|
||||
|
||||
client = AsyncMock()
|
||||
|
||||
mcp, tools = make_mock_mcp()
|
||||
register_containers(mcp, make_config(), client)
|
||||
|
||||
result = await tools["delete_container"]("myapp_web", confirmed=False)
|
||||
assert "Preview" in result
|
||||
assert "myapp_web" in result
|
||||
client.request.assert_not_called()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_delete_container_not_found():
|
||||
from mcp_synology_container.modules.containers import register_containers
|
||||
|
||||
client = AsyncMock()
|
||||
client.request.return_value = None
|
||||
|
||||
mcp, tools = make_mock_mcp()
|
||||
register_containers(mcp, make_config(), client)
|
||||
|
||||
result = await tools["delete_container"]("nonexistent", confirmed=True)
|
||||
assert "not found" in result
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_delete_container_running_blocked():
|
||||
from mcp_synology_container.modules.containers import register_containers
|
||||
|
||||
client = AsyncMock()
|
||||
client.request.return_value = {
|
||||
"details": {"State": {"Running": True, "Status": "running"}},
|
||||
"profile": {"image": "nginx:latest"},
|
||||
}
|
||||
|
||||
mcp, tools = make_mock_mcp()
|
||||
register_containers(mcp, make_config(), client)
|
||||
|
||||
result = await tools["delete_container"]("myapp_web", confirmed=True)
|
||||
assert "running" in result.lower()
|
||||
assert "Cannot delete" in result
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_delete_container_stopped_confirmed():
|
||||
from mcp_synology_container.modules.containers import register_containers
|
||||
|
||||
client = AsyncMock()
|
||||
client.request.return_value = {
|
||||
"details": {"State": {"Running": False, "Status": "exited"}},
|
||||
"profile": {"image": "nginx:latest"},
|
||||
}
|
||||
|
||||
mcp, tools = make_mock_mcp()
|
||||
register_containers(mcp, make_config(), client)
|
||||
|
||||
result = await tools["delete_container"]("myapp_web", confirmed=True)
|
||||
assert "Deleted" in result
|
||||
assert "myapp_web" in result
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_container_stats_cpu_calculation():
|
||||
"""CPU% is computed via the standard Docker formula."""
|
||||
@@ -537,7 +607,10 @@ async def test_get_container_logs_resolves_hash_prefix():
|
||||
return HASH_PREFIXED_CONTAINERS_DATA
|
||||
if api == "SYNO.Docker.Container.Log" and method == "get":
|
||||
assert kwargs["params"]["name"] == "f93cb8b504f7_jenkins"
|
||||
return {"logs": [{"created": "2025-01-01", "stream": "stdout", "text": "started"}], "total": 1}
|
||||
return {
|
||||
"logs": [{"created": "2025-01-01", "stream": "stdout", "text": "started"}],
|
||||
"total": 1,
|
||||
}
|
||||
return {}
|
||||
|
||||
client = AsyncMock()
|
||||
|
||||
Reference in New Issue
Block a user