Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions devservices/utils/docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from devservices.exceptions import ContainerHealthcheckFailedError
from devservices.exceptions import DockerDaemonNotRunningError
from devservices.exceptions import DockerError
from devservices.utils.console import Console
from devservices.utils.console import Status


Expand All @@ -20,14 +21,21 @@ class ContainerNames(NamedTuple):

def check_docker_daemon_running() -> None:
"""Checks if the Docker daemon is running. Raises DockerDaemonNotRunningError if not."""
console = Console()
try:
subprocess.run(
["docker", "info"],
capture_output=True,
text=True,
check=True,
)
return
except subprocess.CalledProcessError:
console.info("Docker daemon is not running. Checking if colima is available")
try:
subprocess.run(["devenv", "colima", "start"], check=True)
except subprocess.CalledProcessError as e:
console.failure("Failed to start colima")
raise DockerDaemonNotRunningError from e
Comment on lines +35 to 39
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential bug: The `try...except` block for `devenv colima start` only handles `CalledProcessError`, risking an unhandled `FileNotFoundError` if the `devenv` command is missing.
  • Description: The subprocess.run call to start devenv colima is wrapped in a try...except block that only catches subprocess.CalledProcessError. However, subprocess.run can also raise a FileNotFoundError if the devenv executable is not found in the system's PATH. This unhandled exception would propagate up, causing a crash with a raw traceback instead of the expected DockerDaemonNotRunningError. This violates the function's contract and prevents graceful failure handling for callers expecting that specific exception type.
  • Suggested fix: Broaden the except clause to catch (subprocess.CalledProcessError, FileNotFoundError). This ensures that if the devenv command is missing, the function still raises the expected DockerDaemonNotRunningError, maintaining consistent error handling.
    severity: 0.65, confidence: 0.9

Did we get this right? 👍 / 👎 to inform future reviews.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.



Expand Down
27 changes: 21 additions & 6 deletions tests/utils/test_docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import pytest
from freezegun import freeze_time

from devservices.constants import Color
from devservices.constants import DEVSERVICES_ORCHESTRATOR_LABEL
from devservices.constants import DOCKER_NETWORK_NAME
from devservices.constants import HEALTHCHECK_INTERVAL
Expand All @@ -25,15 +26,29 @@


@mock.patch("subprocess.run")
def test_check_docker_daemon_running_error(mock_run: mock.Mock) -> None:
def test_check_docker_daemon_running_error(
mock_run: mock.Mock, capsys: pytest.CaptureFixture[str]
) -> None:
mock_run.side_effect = subprocess.CalledProcessError(1, "cmd")
with pytest.raises(DockerDaemonNotRunningError):
check_docker_daemon_running()
mock_run.assert_called_once_with(
["docker", "info"],
capture_output=True,
text=True,
check=True,
mock_run.assert_has_calls(
[
mock.call(
["docker", "info"],
capture_output=True,
text=True,
check=True,
),
mock.call(
["devenv", "colima", "start"],
check=True,
),
]
)
assert (
capsys.readouterr().out
== f"Docker daemon is not running. Checking if colima is available\n{Color.RED}Failed to start colima{Color.RESET}\n"
)


Expand Down
5 changes: 4 additions & 1 deletion tests/utils/test_docker_compose.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,10 @@ def test_check_docker_compose_invalid_version(

@mock.patch(
"subprocess.run",
side_effect=[subprocess.CalledProcessError(returncode=1, cmd="docker info")],
side_effect=[
subprocess.CalledProcessError(returncode=1, cmd="docker info"),
subprocess.CalledProcessError(returncode=1, cmd="devenv colima start"),
],
)
@mock.patch(
"devservices.utils.docker_compose.install_docker_compose", side_effect=lambda: None
Expand Down
Loading