diff --git a/craft_providers/multipass/multipass.py b/craft_providers/multipass/multipass.py index fc2b5b60..aa25825a 100644 --- a/craft_providers/multipass/multipass.py +++ b/craft_providers/multipass/multipass.py @@ -159,7 +159,17 @@ def is_supported_version(self) -> bool: minimum_version = packaging.version.parse(self.minimum_required_version) version, _ = self.version() - return packaging.version.parse(version) >= minimum_version + parsed_version = None + while parsed_version is None: + try: + parsed_version = packaging.version.parse(version) + except packaging.version.InvalidVersion: + # This catches versions such as: 1.15.0-dev.2929.pr661, which are + # compliant, but not pep440 compliant. We can lob off sections until + # we get a pep440 cempliant version. + version = version.rpartition(".")[0] + + return parsed_version >= minimum_version def launch( self, diff --git a/tests/unit/multipass/test_multipass.py b/tests/unit/multipass/test_multipass.py index 2c3722d8..a4014502 100644 --- a/tests/unit/multipass/test_multipass.py +++ b/tests/unit/multipass/test_multipass.py @@ -201,20 +201,31 @@ def test_info_error(fake_process, mock_details_from_process_error): ) -def test_is_supported_version(fake_process): - fake_process.register_subprocess( - ["multipass", "version"], stdout=b"multipass 1.7.0\nmultipassd 1.7.0\n" - ) +@pytest.mark.parametrize( + "version_output", + [ + b"multipass 1.7.0\nmultipassd 1.7.0\n", + b"multipass 1.15.0-dev.354+g533e02ffc\nmultipassd 1.15.0-dev.354+g533e02ffc\n", # Snap multipass, edge channel + b"multipass 1.15.0-dev.2929.pr661+gc67ef6641.mac\nmultipassd 1.15.0-dev.2929.pr661+gc67ef6641.mac", # Dev build on a mac + ], +) +def test_is_supported_version(fake_process, version_output): + fake_process.register_subprocess(["multipass", "version"], stdout=version_output) assert Multipass().is_supported_version() is True assert len(fake_process.calls) == 1 -def test_is_supported_version_false(fake_process): - fake_process.register_subprocess( - ["multipass", "version"], stdout=b"multipass 1.4.0\nmultipassd 1.4.0\n" - ) +@pytest.mark.parametrize( + "version_output", + [ + b"multipass 1.4.0\nmultipassd 1.4.0\n", + b"multipass 1.invalid.15.999\nmultipassd 999\n", + ], +) +def test_is_supported_version_false(fake_process, version_output): + fake_process.register_subprocess(["multipass", "version"], stdout=version_output) assert Multipass().is_supported_version() is False @@ -718,6 +729,16 @@ def test_wait_until_ready_timeout_error( ), ("1.6.2", "1.6.3"), ), + pytest.param( + b"multipass 1.15.0-dev.354+g533e02ffc\nmultipassd 1.15.0-dev.354+g533e02ffc\n", + ("1.15.0-dev.354", "1.15.0-dev.354"), + id="snap-edge-channel", + ), + pytest.param( + b"multipass 1.15.0-dev.2929.pr661+gc67ef6641.mac\nmultipassd 1.15.0-dev.2929.pr661+gc67ef6641.mac", + ("1.15.0-dev.2929.pr661", "1.15.0-dev.2929.pr661"), + id="macos-dev-build", + ), ], ) def test_version(fake_process, output, expected):