diff --git a/craft_application/services/provider.py b/craft_application/services/provider.py index ab386975..b99e65a2 100644 --- a/craft_application/services/provider.py +++ b/craft_application/services/provider.py @@ -289,10 +289,11 @@ def _get_instance_name( self, work_dir: pathlib.Path, build_info: models.BuildInfo ) -> str: work_dir_inode = work_dir.stat().st_ino - return ( - f"{self._app.name}-{self._project.name}-on-{build_info.build_on}-" - f"for-{build_info.build_for}-{work_dir_inode}" - ) + + # craft-providers will remove invalid characters from the name but replacing + # characters improves readability for multi-base platforms like "ubuntu@24.04:amd64" + platform = build_info.platform.replace(":", "-").replace("@", "-") + return f"{self._app.name}-{self._project.name}-{platform}-{work_dir_inode}" def _get_provider_by_name(self, name: str) -> craft_providers.Provider: """Get a provider by its name.""" diff --git a/tests/unit/services/test_provider.py b/tests/unit/services/test_provider.py index 0cae6d66..c525405b 100644 --- a/tests/unit/services/test_provider.py +++ b/tests/unit/services/test_provider.py @@ -241,6 +241,29 @@ def test_get_lxd_provider(monkeypatch, provider_service, lxd_remote, check): ) +@pytest.mark.parametrize( + ("platform", "platform_str"), + [ + pytest.param("test-platform", "test-platform", id="simple"), + pytest.param( + "ubuntu@24.04:amd64", "ubuntu-24.04-amd64", id="special-characters" + ), + ], +) +def test_get_instance_name(platform, platform_str, new_dir, provider_service): + build_info = models.BuildInfo( + platform, "riscv64", "riscv64", bases.BaseName("ubuntu", "24.04") + ) + inode_number = str(new_dir.stat().st_ino) + provider_service._build_plan = [build_info] + expected_name = f"testcraft-full-project-{platform_str}-{inode_number}" + + assert ( + provider_service._get_instance_name(work_dir=new_dir, build_info=build_info) + == expected_name + ) + + class TestGetProvider: """Test cases for `get_provider()`.""" @@ -492,7 +515,7 @@ def test_instance_clean_existing( if clean_existing: work_dir_inode = tmp_path.stat().st_ino - expected_name = f"testcraft-full-project-on-{arch}-for-{arch}-{work_dir_inode}" + expected_name = f"testcraft-full-project-{build_info.platform}-{work_dir_inode}" mock_provider.clean_project_environments.assert_called_once_with( instance_name=expected_name ) @@ -693,7 +716,7 @@ def test_instance_fetch_logs_missing_file( # A single build info, matching the current architecture ( [models.BuildInfo("foo", "current", "current", _test_base)], - ["on-current-for-current"], + ["foo"], ), # Two build infos, both matching the current architecture ( @@ -701,7 +724,7 @@ def test_instance_fetch_logs_missing_file( models.BuildInfo("foo", "current", "current", _test_base), models.BuildInfo("foo2", "current", "other", _test_base), ], - ["on-current-for-current", "on-current-for-other"], + ["foo", "foo2"], ), # Three build infos, only one matches current architecture ( @@ -710,7 +733,7 @@ def test_instance_fetch_logs_missing_file( models.BuildInfo("foo2", "other", "other", _test_base), models.BuildInfo("foo3", "other", "other2", _test_base), ], - ["on-current-for-current"], + ["foo"], ), # Two build infos, none matches current architecture (