diff --git a/snapcraft/application.py b/snapcraft/application.py index 29a9f1683d..4e13807354 100644 --- a/snapcraft/application.py +++ b/snapcraft/application.py @@ -54,6 +54,7 @@ source_ignore_patterns=["*.snap"], project_variables=["version", "grade"], mandatory_adoptable_fields=["version", "summary", "description"], + docs_url="https://canonical-snapcraft.readthedocs-hosted.com/en/{version}", ) diff --git a/snapcraft/commands/remote.py b/snapcraft/commands/remote.py index 1987bfbfd2..6ff2101163 100644 --- a/snapcraft/commands/remote.py +++ b/snapcraft/commands/remote.py @@ -26,11 +26,11 @@ import lazr.restfulclient.errors from craft_application import errors -from craft_application.application import filter_plan from craft_application.commands import ExtensibleCommand from craft_application.errors import RemoteBuildError from craft_application.launchpad.models import Build, BuildState from craft_application.remote.utils import get_build_id +from craft_application.util import humanize_list from craft_cli import emit from overrides import overrides @@ -106,6 +106,9 @@ def _fill_parser(self, parser: argparse.ArgumentParser) -> None: metavar="name", default=os.getenv("CRAFT_PLATFORM"), help="Set platform to build for", + # '--platform' needs to be handled differently since remote-build can + # build for an architecture that is not in the project metadata + dest="remote_build_platform", ) group.add_argument( "--build-for", @@ -113,6 +116,9 @@ def _fill_parser(self, parser: argparse.ArgumentParser) -> None: metavar="arch", default=os.getenv("CRAFT_BUILD_FOR"), help="Set architecture to build for", + # '--build-for' needs to be handled differently since remote-build can + # build for architecture that is not in the project metadata + dest="remote_build_build_for", ) parser.add_argument( "--project", help="upload to the specified Launchpad project" @@ -143,8 +149,56 @@ def _validate(self, parsed_args: argparse.Namespace) -> None: "In non-interactive runs, please use the option " "`--launchpad-accept-public-upload`." ), + doc_slug="/explanation/remote-build.html", reportable=False, - retcode=77, + retcode=os.EX_NOPERM, + ) + + build_for = parsed_args.remote_build_build_for or None + platform = parsed_args.remote_build_platform or None + parameter = "--build-for" if build_for else "--platform" if platform else None + keyword = ( + "architectures" + if self.project._architectures_in_yaml + else "platforms" if self.project.platforms else None + ) + + if keyword and parameter: + raise errors.RemoteBuildError( + f"{parameter!r} cannot be used when {keyword!r} is in the snapcraft.yaml.", + resolution=f"Remove {parameter!r} from the command line or remove {keyword!r} in the snapcraft.yaml.", + doc_slug="/explanation/remote-build.html", + retcode=os.EX_CONFIG, + ) + + if platform: + if self.project.get_effective_base() == "core22": + raise errors.RemoteBuildError( + "'--platform' cannot be used for core22 snaps.", + resolution="Use '--build-for' instead.", + doc_slug="/explanation/remote-build.html", + retcode=os.EX_CONFIG, + ) + if platform not in SUPPORTED_ARCHS: + raise errors.RemoteBuildError( + f"Unsupported platform {parsed_args.remote_build_platform!r}.", + resolution=( + "Use a supported debian architecture. Supported " + f"architectures are: {humanize_list(SUPPORTED_ARCHS, 'and')}" + ), + doc_slug="/explanation/remote-build.html", + retcode=os.EX_CONFIG, + ) + + if build_for and build_for not in SUPPORTED_ARCHS: + raise errors.RemoteBuildError( + f"Unsupported build-for architecture {parsed_args.remote_build_build_for!r}.", + resolution=( + "Use a supported debian architecture. Supported " + f"architectures are: {humanize_list(SUPPORTED_ARCHS, 'and')}" + ), + doc_slug="/explanation/remote-build.html", + retcode=os.EX_CONFIG, ) def _run( # noqa: PLR0915 [too-many-statements] @@ -159,14 +213,13 @@ def _run( # noqa: PLR0915 [too-many-statements] if parsed_args.project: self._services.remote_build.set_project(parsed_args.project) - self._validate(parsed_args) emit.progress( "remote-build is experimental and is subject to change. Use with caution.", permanent=True, ) builder = self._services.remote_build - project = cast(models.Project, self._services.project) + self.project = cast(models.Project, self._services.project) config = cast(dict[str, Any], self.config) project_dir = ( Path(config.get("global_args", {}).get("project_dir") or ".") @@ -175,41 +228,22 @@ def _run( # noqa: PLR0915 [too-many-statements] ) emit.trace(f"Project directory: {project_dir}") + self._validate(parsed_args) - possible_build_plan = filter_plan( - self._app.BuildPlannerClass.unmarshal(project.marshal()).get_build_plan(), - platform=parsed_args.platform, - build_for=parsed_args.build_for, - host_arch=None, - ) - - architectures: list[str] | None = list( - {build_info.build_for for build_info in possible_build_plan} - ) - - if parsed_args.platform and not architectures: - emit.progress( - f"platform '{parsed_args.platform}' is not present in the build plan.", - permanent=True, - ) - return 78 # Configuration error - - if parsed_args.build_for and not architectures: - if parsed_args.build_for not in SUPPORTED_ARCHS: - raise errors.RemoteBuildError( - f"build-for '{parsed_args.build_for}' is not supported.", retcode=78 - ) - # Allow the user to build for a single architecture if snapcraft.yaml - # doesn't define architectures. - architectures = [parsed_args.build_for] + if parsed_args.remote_build_build_for: + architectures = [parsed_args.remote_build_build_for] + elif parsed_args.remote_build_platform: + architectures = [parsed_args.remote_build_platform] + else: + architectures = self._get_project_build_fors() - emit.debug(f"Architectures to build: {architectures}") + emit.debug(f"Architectures to build for: {architectures}") if parsed_args.launchpad_timeout: emit.debug(f"Setting timeout to {parsed_args.launchpad_timeout} seconds") builder.set_timeout(parsed_args.launchpad_timeout) - build_id = get_build_id(self._app.name, project.name, project_dir) + build_id = get_build_id(self._app.name, self.project.name, project_dir) if parsed_args.recover: emit.progress(f"Recovering build {build_id}") builds = builder.resume_builds(build_id) @@ -325,3 +359,18 @@ def _monitor_and_complete( # noqa: PLR0912, PLR0915 f"Artifacts: {', '.join(artifact_names)}" ) return return_code + + def _get_project_build_fors(self) -> list[str]: + """Get a unique list of build-for architectures from the project. + + :returns: A list of architectures. + """ + build_plan = self._app.BuildPlannerClass.unmarshal( + self.project.marshal() + ).get_build_plan() + emit.debug(f"Build plan: {build_plan}") + + build_fors = set({build_info.build_for for build_info in build_plan}) + emit.debug(f"Parsed build-for architectures from build plan: {build_fors}") + + return list(build_fors) diff --git a/snapcraft/models/project.py b/snapcraft/models/project.py index b13c88584b..3642a2f795 100644 --- a/snapcraft/models/project.py +++ b/snapcraft/models/project.py @@ -609,6 +609,7 @@ class Project(models.Project): ) = None grade: Literal["stable", "devel"] | None = None architectures: list[str | Architecture] | None = None + _architectures_in_yaml: bool | None = None platforms: dict[str, Platform] | None = None # type: ignore[assignment,reportIncompatibleVariableOverride] assumes: UniqueList[str] = pydantic.Field(default_factory=list) hooks: dict[str, Hook] | None = None @@ -759,8 +760,14 @@ def _validate_platforms_and_architectures(self) -> Self: f"'platforms' keyword is not supported for base {base!r}. " "Use 'architectures' keyword instead." ) - # set default value - if not self.architectures: + + # this is a one-shot - the value should not change when re-validating + if self.architectures and self._architectures_in_yaml is None: + # record if architectures are defined in the yaml for remote-build (#4881) + self._architectures_in_yaml = True + elif not self.architectures: + self._architectures_in_yaml = False + # set default value self.architectures = [ Architecture( build_on=[get_host_architecture()], diff --git a/tests/spread/core24/remote-build/task.yaml b/tests/spread/core24/remote-build/task.yaml index 4ab305f8c4..14f7d0ca54 100644 --- a/tests/spread/core24/remote-build/task.yaml +++ b/tests/spread/core24/remote-build/task.yaml @@ -8,9 +8,8 @@ systems: environment: LAUNCHPAD_TOKEN: "$(HOST: echo ${LAUNCHPAD_TOKEN})" SNAP: no-platforms - # launchpad can't parse `platforms` (https://github.com/canonical/snapcraft/issues/4858) - #SNAP/all: all - #SNAP/platforms: platforms + SNAP/all: all + SNAP/platforms: platforms SNAP/no_platforms: no-platforms CREDENTIALS_FILE: "$HOME/.local/share/snapcraft/launchpad-credentials" CREDENTIALS_FILE/new_credentials: "$HOME/.local/share/snapcraft/launchpad-credentials" diff --git a/tests/unit/commands/test_remote.py b/tests/unit/commands/test_remote.py index f64e521a61..dd54032c7e 100644 --- a/tests/unit/commands/test_remote.py +++ b/tests/unit/commands/test_remote.py @@ -410,8 +410,8 @@ def test_run_in_shallow_repo_unsupported( ###################### -@pytest.mark.parametrize("base", const.CURRENT_BASES) -def test_no_platform_defined_no_platform_or_build_for( +@pytest.mark.parametrize("base", const.CURRENT_BASES - {"devel"}) +def test_default_architecture( mocker, snapcraft_yaml, base, @@ -419,18 +419,9 @@ def test_no_platform_defined_no_platform_or_build_for( mock_confirm, mock_remote_builder_fake_build_process, ): - """Test that the remote-build command uses the host architecture if no platform is defined.""" - snapcraft_yaml_dict = { - "base": base, - "build-base": "devel", - "grade": "devel", - } - snapcraft_yaml(**snapcraft_yaml_dict) - mocker.patch.object( - sys, - "argv", - ["snapcraft", "remote-build"], - ) + """Default to the host architecture if not defined elsewhere.""" + snapcraft_yaml(base=base) + mocker.patch.object(sys, "argv", ["snapcraft", "remote-build"]) mock_start_builds = mocker.patch( "craft_application.services.remotebuild.RemoteBuildService.start_builds" ) @@ -442,7 +433,7 @@ def test_no_platform_defined_no_platform_or_build_for( ) -@pytest.mark.parametrize("base", const.CURRENT_BASES - {"core22"}) +@pytest.mark.parametrize("base", const.CURRENT_BASES - {"core22", "devel"}) def test_platform_build_for_all( mocker, snapcraft_yaml, @@ -451,10 +442,9 @@ def test_platform_build_for_all( mock_confirm, mock_remote_builder_fake_build_process, ): + """Use 'build-for: all' from the project metadata with the platforms keyword.""" snapcraft_yaml_dict = { "base": base, - "build-base": "devel", - "grade": "devel", "platforms": { "test-platform": {"build-on": "arm64", "build-for": "all"}, }, @@ -478,10 +468,9 @@ def test_platform_build_for_all_core22( mock_confirm, mock_remote_builder_fake_build_process, ): - """remote-build command uses all platforms if no platform or build-for is given.""" + """Use 'build-for: all' from the project metadata with the architectures keyword.""" snapcraft_yaml_dict = { "base": "core22", - "grade": "devel", "architectures": [ {"build-on": ["arm64"], "build-for": ["all"]}, ], @@ -498,8 +487,8 @@ def test_platform_build_for_all_core22( assert mock_start_builds.call_args[1]["architectures"] == ["all"] -@pytest.mark.parametrize("base", const.CURRENT_BASES - {"core22"}) -def test_platform_defined_no_platform_or_build_for( +@pytest.mark.parametrize("base", const.CURRENT_BASES - {"core22", "devel"}) +def test_platform_in_project_metadata( mocker, snapcraft_yaml, base, @@ -507,14 +496,13 @@ def test_platform_defined_no_platform_or_build_for( mock_confirm, mock_remote_builder_fake_build_process, ): - """remote-build command uses all platforms if no platform or build-for is given.""" + """Use the platform's build-for architectures from the project metadata.""" snapcraft_yaml_dict = { "base": base, - "build-base": "devel", - "grade": "devel", "platforms": { "rpi4": {"build-on": "arm64", "build-for": "arm64"}, "x86-64": {"build-on": "amd64", "build-for": "amd64"}, + "same-build-for-x86-64": {"build-on": "riscv64", "build-for": "amd64"}, }, } snapcraft_yaml(**snapcraft_yaml_dict) @@ -534,36 +522,26 @@ def test_platform_defined_no_platform_or_build_for( assert const.SnapArch.amd64 in mock_start_builds.call_args[1]["architectures"] -@pytest.mark.parametrize("base", const.CURRENT_BASES - {"core22"}) -@pytest.mark.parametrize( - ["platform", "arch"], - [("rpi4", const.SnapArch.arm64), ("x86-64", const.SnapArch.amd64)], -) -def test_platform( +def test_architecture_in_project_metadata( mocker, snapcraft_yaml, - base, fake_services, mock_confirm, mock_remote_builder_fake_build_process, - platform, - arch, ): - """Test that the remote-build command uses the platform if --platform is given.""" + """Use the build-for architectures from the project metadata.""" snapcraft_yaml_dict = { - "base": base, - "build-base": "devel", - "grade": "devel", - "platforms": { - "rpi4": {"build-on": "arm64", "build-for": "arm64"}, - "x86-64": {"build-on": "amd64", "build-for": "amd64"}, - }, + "base": "core22", + "architectures": [ + {"build-on": ["arm64"], "build-for": ["arm64"]}, + {"build-on": ["riscv64"], "build-for": ["riscv64"]}, + ], } snapcraft_yaml(**snapcraft_yaml_dict) mocker.patch.object( sys, "argv", - ["snapcraft", "remote-build", "--platform", platform], + ["snapcraft", "remote-build"], ) mock_start_builds = mocker.patch( "craft_application.services.remotebuild.RemoteBuildService.start_builds" @@ -571,51 +549,40 @@ def test_platform( app = application.create_app() app.run() - mock_start_builds.assert_called_once_with(ANY, architectures=[arch]) + mock_start_builds.assert_called_once() + assert mock_start_builds.call_args[1]["architectures"] == ["arm64", "riscv64"] -@pytest.mark.xfail( - reason="craft-application catches before it gets to the remote-build command" -) -@pytest.mark.parametrize("base", const.CURRENT_BASES - {"core22"}) -def test_platform_error( - emitter, +@pytest.mark.parametrize("base", const.CURRENT_BASES - {"core22", "devel"}) +@pytest.mark.parametrize("platform", const.SnapArch) +def test_platform_argument( mocker, snapcraft_yaml, base, fake_services, mock_confirm, + mock_remote_builder_fake_build_process, + platform, ): - """Test that the remote-build command errors if the given platform is not found.""" - snapcraft_yaml_dict = { - "base": base, - "build-base": "devel", - "grade": "devel", - "platforms": { - "rpi4": {"build-on": "arm64", "build-for": "arm64"}, - "x86-64": {"build-on": "amd64", "build-for": "amd64"}, - }, - } - snapcraft_yaml(**snapcraft_yaml_dict) + """Use architectures provided by the `--platform` argument.""" + snapcraft_yaml(base=base) mocker.patch.object( sys, "argv", - ["snapcraft", "remote-build", "--platform", "nonexistent"], + ["snapcraft", "remote-build", "--platform", platform], ) - - app = application.create_app() - assert app.run() == 1 - emitter.assert_progress( - "Platform 'nonexistent' not found in the project definition.", permanent=True + mock_start_builds = mocker.patch( + "craft_application.services.remotebuild.RemoteBuildService.start_builds" ) + app = application.create_app() + app.run() + mock_start_builds.assert_called_once_with(ANY, architectures=[platform]) -@pytest.mark.parametrize("base", const.CURRENT_BASES - {"core22"}) -@pytest.mark.parametrize( - ["build_for", "arch"], - [("amd64", const.SnapArch.amd64), ("arm64", const.SnapArch.arm64)], -) -def test_build_for( + +@pytest.mark.parametrize("base", const.CURRENT_BASES - {"devel"}) +@pytest.mark.parametrize("build_for", const.SnapArch) +def test_build_for_argument( mocker, snapcraft_yaml, base, @@ -623,19 +590,9 @@ def test_build_for( mock_confirm, mock_remote_builder_fake_build_process, build_for, - arch, ): - """Test that the remote-build command uses the build-for if --build-for is given.""" - snapcraft_yaml_dict = { - "base": base, - "build-base": "devel", - "grade": "devel", - "platforms": { - "rpi4": {"build-on": "arm64", "build-for": "arm64"}, - "x86-64": {"build-on": "amd64", "build-for": "amd64"}, - }, - } - snapcraft_yaml(**snapcraft_yaml_dict) + """Use architectures provided by the `--build-for` argument.""" + snapcraft_yaml(base=base) mocker.patch.object( sys, "argv", @@ -647,66 +604,122 @@ def test_build_for( app = application.create_app() app.run() - mock_start_builds.assert_called_once_with(ANY, architectures=[arch]) + mock_start_builds.assert_called_once_with(ANY, architectures=[build_for]) -@pytest.mark.parametrize("base", const.CURRENT_BASES) -@pytest.mark.parametrize( - ["build_for", "arch"], - [("amd64", const.SnapArch.amd64), ("arm64", const.SnapArch.arm64)], -) -def test_build_for_no_platforms( +def test_architecture_defined_twice_error( + capsys, mocker, snapcraft_yaml, + fake_services, + mock_confirm, +): + """Error if architectures are in the project metadata and as a build argument.""" + snapcraft_yaml_dict = { + "base": "core22", + "architectures": [{"build-on": ["riscv64"], "build-for": ["riscv64"]}], + } + snapcraft_yaml(**snapcraft_yaml_dict) + mocker.patch.object( + sys, + "argv", + ["snapcraft", "remote-build", "--build-for", "riscv64"], + ) + app = application.create_app() + app.run() + + _, err = capsys.readouterr() + + assert ( + "'--build-for' cannot be used when 'architectures' is in the snapcraft.yaml." + ) in err + assert ( + "Remove '--build-for' from the command line or remove 'architectures' in the snapcraft.yaml." + ) in err + + +@pytest.mark.parametrize("base", const.CURRENT_BASES - {"core22", "devel"}) +@pytest.mark.parametrize("argument", ["--build-for", "--platform"]) +def test_platform_defined_twice_error( base, + argument, + capsys, + mocker, + snapcraft_yaml, fake_services, mock_confirm, - mock_remote_builder_fake_build_process, - build_for, - arch, ): - """remote-build command uses the build-for if --build-for is given without platforms.""" + """Error if platforms are in the project metadata and as a build argument.""" snapcraft_yaml_dict = { "base": base, - "build-base": "devel", - "grade": "devel", + "platforms": { + "riscv64": {"build-on": "riscv64", "build-for": "riscv64"}, + }, } snapcraft_yaml(**snapcraft_yaml_dict) mocker.patch.object( sys, "argv", - ["snapcraft", "remote-build", "--build-for", build_for], - ) - mock_start_builds = mocker.patch( - "craft_application.services.remotebuild.RemoteBuildService.start_builds" + ["snapcraft", "remote-build", argument, "riscv64"], ) app = application.create_app() app.run() - mock_start_builds.assert_called_once_with(ANY, architectures=[arch]) + _, err = capsys.readouterr() + + assert ( + f"{argument!r} cannot be used when 'platforms' is in the snapcraft.yaml." + ) in err + assert ( + f"Remove {argument!r} from the command line or remove 'platforms' in the snapcraft.yaml." + ) in err @pytest.mark.parametrize("base", const.CURRENT_BASES - {"core22"}) -def test_build_for_error( +def test_unknown_platform_error( capsys, mocker, snapcraft_yaml, base, fake_services, mock_confirm, - mock_remote_builder_fake_build_process, ): - """Test that the remote-build command errors if the given build-for is not found.""" + """Error if `--platform` is not a valid debian architecture.""" snapcraft_yaml_dict = { "base": base, "build-base": "devel", "grade": "devel", - "platforms": { - "rpi4": {"build-on": "arm64", "build-for": "arm64"}, - "x86-64": {"build-on": "amd64", "build-for": "amd64"}, - }, } snapcraft_yaml(**snapcraft_yaml_dict) + mocker.patch.object( + sys, + "argv", + ["snapcraft", "remote-build", "--platform", "nonexistent"], + ) + + app = application.create_app() + assert app.run() == os.EX_CONFIG + + _, err = capsys.readouterr() + assert "Unsupported platform 'nonexistent'" in err + assert ( + "Recommended resolution: Use a supported debian architecture. " + "Supported architectures are:" + ) in err + + +@pytest.mark.parametrize("base", const.CURRENT_BASES - {"core22", "devel"}) +def test_unknown_build_for_error( + capsys, + mocker, + snapcraft_yaml, + base, + fake_services, + mock_confirm, + mock_remote_builder_fake_build_process, +): + """Error if `--build-for` is not a valid debian architecture.""" + snapcraft_yaml(base=base) mocker.patch.object( sys, "argv", @@ -716,11 +729,42 @@ def test_build_for_error( "craft_application.services.remotebuild.RemoteBuildService.start_builds" ) app = application.create_app() - assert app.run() == 1 + assert app.run() == os.EX_CONFIG + + _, err = capsys.readouterr() + + assert "Unsupported build-for architecture 'nonexistent'" in err + assert ( + "Recommended resolution: Use a supported debian architecture. " + "Supported architectures are:" + ) in err + + +def test_platform_core22_error( + capsys, + mocker, + snapcraft_yaml, + fake_services, + mock_confirm, + mock_remote_builder_fake_build_process, +): + """Error on `--platform` for core22 snaps.""" + snapcraft_yaml(base="core22") + mocker.patch.object( + sys, + "argv", + ["snapcraft", "remote-build", "--platform", "amd64"], + ) + mocker.patch( + "craft_application.services.remotebuild.RemoteBuildService.start_builds" + ) + app = application.create_app() + assert app.run() == os.EX_CONFIG _, err = capsys.readouterr() - assert "Architecture 'nonexistent' is not supported." in err + assert "--platform' cannot be used for core22 snaps" in err + assert "Use '--build-for' instead." in err ######################## diff --git a/tests/unit/models/test_projects.py b/tests/unit/models/test_projects.py index 32e2e946d9..1cb147d676 100644 --- a/tests/unit/models/test_projects.py +++ b/tests/unit/models/test_projects.py @@ -1999,6 +1999,30 @@ def test_architectures_not_allowed(self, project_yaml_data): with pytest.raises(pydantic.ValidationError, match=error): Project.unmarshal(project_yaml_data(**CORE24_DATA, architectures=["amd64"])) + @pytest.mark.parametrize( + ("data", "expected"), + [ + ({"base": "core22", "architectures": ["amd64"]}, True), + ({"base": "core22"}, False), + # core24 and newer do not set this field + ({"base": "core24"}, None), + ], + ) + def test_architectures_in_yaml(self, project_yaml_data, data, expected): + """Check if architectures were present in the yaml before unmarshalling.""" + project_yaml = project_yaml_data(**data) + + project = Project.unmarshal(project_yaml) + + assert project._architectures_in_yaml is expected + + # adding architectures after unmarshalling does not change the field + if project.base == "core22": + project.architectures = [ + Architecture(build_on=["amd64"], build_for=["amd64"]) + ] + assert project._architectures_in_yaml is expected + class TestApplyRootPackages: """Test Transform the Project.""" diff --git a/tests/unit/parts/test_lifecycle.py b/tests/unit/parts/test_lifecycle.py index 0747c0070c..6f5b598b02 100644 --- a/tests/unit/parts/test_lifecycle.py +++ b/tests/unit/parts/test_lifecycle.py @@ -25,13 +25,14 @@ import pytest from craft_cli import EmitterMode, emit from craft_parts import Action, Features, ProjectInfo, Step, callbacks +from craft_platforms import DebianArchitecture from craft_providers.bases.ubuntu import BuilddBaseAlias from snapcraft import errors from snapcraft.elf import ElfFile from snapcraft.models import MANDATORY_ADOPTABLE_FIELDS, Project from snapcraft.parts import lifecycle as parts_lifecycle -from snapcraft.parts import set_global_environment +from snapcraft.parts import set_global_environment, yaml_utils from snapcraft.parts.plugins import KernelPlugin, MatterSdkPlugin from snapcraft.parts.update_metadata import update_project_metadata from snapcraft.utils import get_host_architecture @@ -146,7 +147,9 @@ def test_snapcraft_yaml_load(new_dir, snapcraft_yaml, filename, mocker): ), ) - project = Project.unmarshal(yaml_data) + arch = DebianArchitecture.from_host().value + applied_yaml = yaml_utils.apply_yaml(yaml_data, arch, arch) + project = Project.unmarshal(applied_yaml) if filename == "build-aux/snap/snapcraft.yaml": assets_dir = Path("build-aux/snap") @@ -198,7 +201,9 @@ def test_lifecycle_run_with_components( ), ) - project = Project.unmarshal(yaml_data) + arch = DebianArchitecture.from_host().value + applied_yaml = yaml_utils.apply_yaml(yaml_data, arch, arch) + project = Project.unmarshal(applied_yaml) assert mock_run_command.mock_calls == [ call( @@ -247,7 +252,9 @@ def test_lifecycle_run_no_components(new_dir, snapcraft_yaml, mocker): ), ) - project = Project.unmarshal(yaml_data) + arch = DebianArchitecture.from_host().value + applied_yaml = yaml_utils.apply_yaml(yaml_data, arch, arch) + project = Project.unmarshal(applied_yaml) assert mock_run_command.mock_calls == [ call(