From cb8e0cbc1f1e8c62538254ac24ec15d0259a6ec0 Mon Sep 17 00:00:00 2001 From: Sheng Yu Date: Tue, 27 Feb 2024 16:21:38 -0500 Subject: [PATCH 1/3] feat(craft-application): support root packages for core24 This allows the user to use "build-packages" and "build-snaps" at the root level of the snapcraft.yaml file. --- snapcraft/application.py | 5 +++-- snapcraft/models/project.py | 27 +++++++++++++++++++++++++++ tests/unit/models/test_projects.py | 18 ++++++++++++++++++ 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/snapcraft/application.py b/snapcraft/application.py index a361c18f86..605efbcd9e 100644 --- a/snapcraft/application.py +++ b/snapcraft/application.py @@ -38,7 +38,7 @@ from snapcraft.commands import unimplemented from snapcraft.extensions import apply_extensions from snapcraft.models import Architecture -from snapcraft.models.project import validate_architectures +from snapcraft.models.project import root_packages_transform, validate_architectures from snapcraft.providers import SNAPCRAFT_BASE_TO_PROVIDER_BASE from snapcraft.utils import get_effective_base, get_host_architecture @@ -170,7 +170,8 @@ def _extra_yaml_transform( ) -> dict[str, Any]: arch = build_on target_arch = build_for if build_for else get_host_architecture() - return apply_extensions(yaml_data, arch=arch, target_arch=target_arch) + new_yaml_data = apply_extensions(yaml_data, arch=arch, target_arch=target_arch) + return root_packages_transform(new_yaml_data) @override def _get_dispatcher(self) -> craft_cli.Dispatcher: diff --git a/snapcraft/models/project.py b/snapcraft/models/project.py index 1c89f73d4d..af5e637005 100644 --- a/snapcraft/models/project.py +++ b/snapcraft/models/project.py @@ -16,6 +16,7 @@ """Project file definition and helpers.""" +import copy import re from typing import TYPE_CHECKING, Any, Dict, List, Literal, Optional, Tuple, Union, cast @@ -171,6 +172,32 @@ def _validate_architectures_all_keyword(architectures): ) +def root_packages_transform(yaml_data: dict[str, Any]) -> dict[str, Any]: + """Support Root Packages in Snapcraft. + + This allows the user to use "build-packages" and "build-snaps" + at the root level of the snapcraft.yaml file. + """ + if "build-packages" not in yaml_data and "build-snaps" not in yaml_data: + return yaml_data + + yaml_data = copy.deepcopy(yaml_data) + yaml_data.setdefault("parts", {}) + yaml_data["parts"]["snapcraft/core"] = {"plugin": "nil"} + + if "build-packages" in yaml_data: + yaml_data["parts"]["snapcraft/core"]["build-packages"] = yaml_data.pop( + "build-packages" + ) + + if "build-snaps" in yaml_data: + yaml_data["parts"]["snapcraft/core"]["build-snaps"] = yaml_data.pop( + "build-snaps" + ) + + return yaml_data + + class Socket(models.CraftBaseModel): """Snapcraft app socket definition.""" diff --git a/tests/unit/models/test_projects.py b/tests/unit/models/test_projects.py index d63bdd9beb..ec99b28bb0 100644 --- a/tests/unit/models/test_projects.py +++ b/tests/unit/models/test_projects.py @@ -29,6 +29,7 @@ Hook, Project, ) +from snapcraft.models.project import root_packages_transform from snapcraft.utils import get_host_architecture @@ -1782,3 +1783,20 @@ def test_project_get_build_for_arch_triplet_all(self, project_yaml_data): arch_triplet = project.get_build_for_arch_triplet() assert not arch_triplet + + +class TestProjectTransform: + """Test Transform the Project.""" + + def test_root_packages_transform(self, project_yaml_data): + """Test transforming the project.""" + data = project_yaml_data() + data["build-packages"] = ["pkg1", "pkg2"] + data["build-snaps"] = ["snap3", "snap4"] + + data_transformed = root_packages_transform(data) + + project = Project.unmarshal(data_transformed) + + assert project.parts["snapcraft/core"]["build-packages"] == ["pkg1", "pkg2"] + assert project.parts["snapcraft/core"]["build-snaps"] == ["snap3", "snap4"] From 887a78488ac44dae5071cfa36a57ac86cb79f2d3 Mon Sep 17 00:00:00 2001 From: Sheng Yu Date: Wed, 28 Feb 2024 13:19:22 -0500 Subject: [PATCH 2/3] fix: feedback --- snapcraft/application.py | 7 +++++-- snapcraft/models/project.py | 2 +- tests/unit/models/test_projects.py | 16 ++++++++++++++-- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/snapcraft/application.py b/snapcraft/application.py index 605efbcd9e..64b8785dfe 100644 --- a/snapcraft/application.py +++ b/snapcraft/application.py @@ -38,7 +38,10 @@ from snapcraft.commands import unimplemented from snapcraft.extensions import apply_extensions from snapcraft.models import Architecture -from snapcraft.models.project import root_packages_transform, validate_architectures +from snapcraft.models.project import ( + apply_root_packages_transform, + validate_architectures, +) from snapcraft.providers import SNAPCRAFT_BASE_TO_PROVIDER_BASE from snapcraft.utils import get_effective_base, get_host_architecture @@ -171,7 +174,7 @@ def _extra_yaml_transform( arch = build_on target_arch = build_for if build_for else get_host_architecture() new_yaml_data = apply_extensions(yaml_data, arch=arch, target_arch=target_arch) - return root_packages_transform(new_yaml_data) + return apply_root_packages_transform(new_yaml_data) @override def _get_dispatcher(self) -> craft_cli.Dispatcher: diff --git a/snapcraft/models/project.py b/snapcraft/models/project.py index af5e637005..d0f3626c04 100644 --- a/snapcraft/models/project.py +++ b/snapcraft/models/project.py @@ -172,7 +172,7 @@ def _validate_architectures_all_keyword(architectures): ) -def root_packages_transform(yaml_data: dict[str, Any]) -> dict[str, Any]: +def apply_root_packages_transform(yaml_data: dict[str, Any]) -> dict[str, Any]: """Support Root Packages in Snapcraft. This allows the user to use "build-packages" and "build-snaps" diff --git a/tests/unit/models/test_projects.py b/tests/unit/models/test_projects.py index ec99b28bb0..e07fbbaec4 100644 --- a/tests/unit/models/test_projects.py +++ b/tests/unit/models/test_projects.py @@ -29,7 +29,7 @@ Hook, Project, ) -from snapcraft.models.project import root_packages_transform +from snapcraft.models.project import apply_root_packages_transform from snapcraft.utils import get_host_architecture @@ -1794,9 +1794,21 @@ def test_root_packages_transform(self, project_yaml_data): data["build-packages"] = ["pkg1", "pkg2"] data["build-snaps"] = ["snap3", "snap4"] - data_transformed = root_packages_transform(data) + data_transformed = apply_root_packages_transform(data) project = Project.unmarshal(data_transformed) assert project.parts["snapcraft/core"]["build-packages"] == ["pkg1", "pkg2"] assert project.parts["snapcraft/core"]["build-snaps"] == ["snap3", "snap4"] + + def test_root_packages_transform_no_affect(self, project_yaml_data): + """Test transforming the project without root packages.""" + data = project_yaml_data() + + data_transformed = apply_root_packages_transform(data) + + project = Project.unmarshal(data_transformed) + + assert project.build_packages is None + assert project.build_snaps is None + assert "snapcraft/core" not in project.parts From 40097265a1bff9d9f1207dbf4f33435b4f917a68 Mon Sep 17 00:00:00 2001 From: Sheng Yu Date: Wed, 28 Feb 2024 16:51:26 -0500 Subject: [PATCH 3/3] fix: change wording --- snapcraft/application.py | 7 ++----- snapcraft/models/project.py | 10 ++++++---- tests/unit/models/test_projects.py | 14 +++++++------- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/snapcraft/application.py b/snapcraft/application.py index 4070b008fc..0c0e8db5aa 100644 --- a/snapcraft/application.py +++ b/snapcraft/application.py @@ -38,10 +38,7 @@ from snapcraft.commands import unimplemented from snapcraft.extensions import apply_extensions from snapcraft.models import Architecture -from snapcraft.models.project import ( - apply_root_packages_transform, - validate_architectures, -) +from snapcraft.models.project import apply_root_packages, validate_architectures from snapcraft.providers import SNAPCRAFT_BASE_TO_PROVIDER_BASE from snapcraft.utils import get_effective_base, get_host_architecture @@ -174,7 +171,7 @@ def _extra_yaml_transform( arch = build_on target_arch = build_for if build_for else get_host_architecture() new_yaml_data = apply_extensions(yaml_data, arch=arch, target_arch=target_arch) - return apply_root_packages_transform(new_yaml_data) + return apply_root_packages(new_yaml_data) @override def _get_dispatcher(self) -> craft_cli.Dispatcher: diff --git a/snapcraft/models/project.py b/snapcraft/models/project.py index d0f3626c04..4ab62f55c4 100644 --- a/snapcraft/models/project.py +++ b/snapcraft/models/project.py @@ -172,11 +172,13 @@ def _validate_architectures_all_keyword(architectures): ) -def apply_root_packages_transform(yaml_data: dict[str, Any]) -> dict[str, Any]: - """Support Root Packages in Snapcraft. +def apply_root_packages(yaml_data: dict[str, Any]) -> dict[str, Any]: + """Create a new part with root level attributes. - This allows the user to use "build-packages" and "build-snaps" - at the root level of the snapcraft.yaml file. + Root level attributes such as build-packages and build-snaps + are known to Snapcraft but not Craft Parts. Create a new part + "snapcraft/core" with these attributes and apply it to the + current yaml_data. """ if "build-packages" not in yaml_data and "build-snaps" not in yaml_data: return yaml_data diff --git a/tests/unit/models/test_projects.py b/tests/unit/models/test_projects.py index e07fbbaec4..b35390ae97 100644 --- a/tests/unit/models/test_projects.py +++ b/tests/unit/models/test_projects.py @@ -29,7 +29,7 @@ Hook, Project, ) -from snapcraft.models.project import apply_root_packages_transform +from snapcraft.models.project import apply_root_packages from snapcraft.utils import get_host_architecture @@ -1785,16 +1785,16 @@ def test_project_get_build_for_arch_triplet_all(self, project_yaml_data): assert not arch_triplet -class TestProjectTransform: +class TestApplyRootPackages: """Test Transform the Project.""" - def test_root_packages_transform(self, project_yaml_data): - """Test transforming the project.""" + def test_apply_root_packages(self, project_yaml_data): + """Test creating a part with root level build-packages and build-snaps.""" data = project_yaml_data() data["build-packages"] = ["pkg1", "pkg2"] data["build-snaps"] = ["snap3", "snap4"] - data_transformed = apply_root_packages_transform(data) + data_transformed = apply_root_packages(data) project = Project.unmarshal(data_transformed) @@ -1802,10 +1802,10 @@ def test_root_packages_transform(self, project_yaml_data): assert project.parts["snapcraft/core"]["build-snaps"] == ["snap3", "snap4"] def test_root_packages_transform_no_affect(self, project_yaml_data): - """Test transforming the project without root packages.""" + """Test that nothing is applied if there are not build-packages or build-snaps.""" data = project_yaml_data() - data_transformed = apply_root_packages_transform(data) + data_transformed = apply_root_packages(data) project = Project.unmarshal(data_transformed)