From 17666fb25259b73f8055f099d45a4df0a51a0c7a Mon Sep 17 00:00:00 2001 From: Sheng Yu Date: Wed, 24 Jan 2024 15:54:18 -0500 Subject: [PATCH] fix(lifecycle): return correct base when using devel for build-base (#4523) --- snapcraft/parts/lifecycle.py | 2 +- snapcraft/parts/yaml_utils.py | 2 +- snapcraft/projects.py | 9 +++++++++ snapcraft/providers.py | 1 + snapcraft/utils.py | 14 ++++++++++---- tests/unit/commands/test_remote.py | 5 ++++- tests/unit/test_utils.py | 2 ++ 7 files changed, 28 insertions(+), 7 deletions(-) diff --git a/snapcraft/parts/lifecycle.py b/snapcraft/parts/lifecycle.py index d470a0bb8a..6d8ed2625d 100644 --- a/snapcraft/parts/lifecycle.py +++ b/snapcraft/parts/lifecycle.py @@ -432,7 +432,7 @@ def _run_in_provider( # noqa PLR0915 snapcraft_base = project.get_effective_base() build_base = providers.SNAPCRAFT_BASE_TO_PROVIDER_BASE[snapcraft_base] - if snapcraft_base == "devel": + if snapcraft_base in ("devel", "core24"): emit.progress( "Running snapcraft with a devel instance is for testing purposes only.", permanent=True, diff --git a/snapcraft/parts/yaml_utils.py b/snapcraft/parts/yaml_utils.py index ca2bba350d..053c957c8b 100644 --- a/snapcraft/parts/yaml_utils.py +++ b/snapcraft/parts/yaml_utils.py @@ -33,7 +33,7 @@ _CORE_PART_NAME = "snapcraft/core" # All bases recognized by snapcraft -BASES = {"core", "core18", "core20", "core22", "devel"} +BASES = {"core", "core18", "core20", "core22", "core24", "devel"} # Bases no longer supported by the current version of snapcraft ESM_BASES = {"core", "core18"} # Bases handled by the legacy snapcraft codebase diff --git a/snapcraft/projects.py b/snapcraft/projects.py index 2acd889547..feadca15d7 100644 --- a/snapcraft/projects.py +++ b/snapcraft/projects.py @@ -591,6 +591,15 @@ def _validate_grade_and_build_base(cls, values): raise ValueError("grade must be 'devel' when build-base is 'devel'") return values + @pydantic.validator("base", always=True) + @classmethod + def _validate_base(cls, base, values): + """Not allowed to use unstable base without devel build-base.""" + if values.get("base") == "core24" and values.get("build_base") != "devel": + raise ValueError("build-base must be 'devel' when base is 'core24'") + + return base + @pydantic.validator("build_base", always=True) @classmethod def _validate_build_base(cls, build_base, values): diff --git a/snapcraft/providers.py b/snapcraft/providers.py index 268904ef3e..6f676258fd 100644 --- a/snapcraft/providers.py +++ b/snapcraft/providers.py @@ -42,6 +42,7 @@ "core18": bases.BuilddBaseAlias.BIONIC, "core20": bases.BuilddBaseAlias.FOCAL, "core22": bases.BuilddBaseAlias.JAMMY, + "core24": bases.BuilddBaseAlias.DEVEL, "devel": bases.BuilddBaseAlias.DEVEL, } diff --git a/snapcraft/utils.py b/snapcraft/utils.py index 77c76c6b0e..8dcdb84f14 100644 --- a/snapcraft/utils.py +++ b/snapcraft/utils.py @@ -216,14 +216,20 @@ def get_effective_base( ) -> Optional[str]: """Return the base to use to create the snap. - Returns build-base if set, but if not, name is returned if the - snap is of type base. For all other snaps, the base is returned - as the build-base. + Return the build-base if set. + Exception: + "base" snaps will return name if build-base is not set. + "devel" snaps, return the base, where the true base is, except "base" snaps. """ + if project_type == "base": + return build_base if build_base else name + if build_base is not None: + if build_base == "devel": + return base return build_base - return name if project_type == "base" else base + return base def get_parallel_build_count() -> int: diff --git a/tests/unit/commands/test_remote.py b/tests/unit/commands/test_remote.py index ac9232562b..8b0dd5a720 100644 --- a/tests/unit/commands/test_remote.py +++ b/tests/unit/commands/test_remote.py @@ -277,7 +277,10 @@ def test_get_effective_base_with_build_base( cli.run() - mock_run_new_or_fallback_remote_build.assert_called_once_with(build_base) + if build_base == "devel": + mock_run_new_or_fallback_remote_build.assert_called_once_with(base) + else: + mock_run_new_or_fallback_remote_build.assert_called_once_with(build_base) @pytest.mark.usefixtures("mock_argv", "mock_confirm") diff --git a/tests/unit/test_utils.py b/tests/unit/test_utils.py index 9807f5ec5c..35c1aa904a 100644 --- a/tests/unit/test_utils.py +++ b/tests/unit/test_utils.py @@ -118,6 +118,8 @@ def test_strtobool_value_error(value: str): (None, None, "other", "name", None), ("base", "build_base", "other", "name", "build_base"), ("base", None, "other", "name", "base"), + ("base", "devel", "other", "name", "base"), + ("base", "devel", "base", "name", "devel"), ], ) def test_get_effective_base(base, build_base, project_type, name, expected_base):