diff --git a/docs/explanation/remote-build.rst b/docs/explanation/remote-build.rst index 8d287f9524..9e95faad52 100644 --- a/docs/explanation/remote-build.rst +++ b/docs/explanation/remote-build.rst @@ -90,11 +90,11 @@ Current :ref:`lifecycle commands`. ``--platform`` or ``--build-for`` can only be provided when the ``platforms`` -and ``architectures`` keywords are not defined in the project metadata +or ``architectures`` keywords are not defined in the project metadata (`[12]`_). -These keywords are mutually exclusive and must be a single debian architecture. -A list of comma-separated architectures is not supported (`[11]`_). +These keywords are mutually exclusive and must be a comma-separated list of +debian architectures. ``core22`` snaps can only use ``--build-for``. ``core24`` and newer snaps can use ``--platform`` or ``--build-for``. @@ -180,7 +180,6 @@ Launchpad is not able to parse this notation (`[9]`_). .. _`[8]`: https://bugs.launchpad.net/snapcraft/+bug/2007789 .. _`[9]`: https://bugs.launchpad.net/snapcraft/+bug/2042167 .. _`[10]`: https://github.com/canonical/snapcraft/issues/4885 -.. _`[11]`: https://github.com/canonical/snapcraft/issues/4990 .. _`[12]`: https://github.com/canonical/snapcraft/issues/4992 .. _`[13]`: https://github.com/canonical/snapcraft/issues/4996 .. _`[14]`: https://github.com/canonical/snapcraft/issues/4995 diff --git a/docs/reference/changelog.rst b/docs/reference/changelog.rst index 571faec3e1..8559a3c2ff 100644 --- a/docs/reference/changelog.rst +++ b/docs/reference/changelog.rst @@ -68,6 +68,22 @@ Changelog For a complete list of commits, check out the `X.Y.Z`_ release on GitHub. +8.3.4 (2024-Sep-13) +------------------- + +Core +==== + +Plugins +####### + +NPM +""" + +* Fix a bug where NPM parts fail to build if the ``pull`` and ``build`` steps + did not occur in the same execution of Snapcraft. + +For a complete list of commits, check out the `8.3.4`_ release on GitHub. 8.4.0 (2024-Sep-10) ------------------- @@ -1171,4 +1187,5 @@ For a complete list of commits, check out the `8.0.0`_ release on GitHub. .. _8.3.1: https://github.com/canonical/snapcraft/releases/tag/8.3.1 .. _8.3.2: https://github.com/canonical/snapcraft/releases/tag/8.3.2 .. _8.3.3: https://github.com/canonical/snapcraft/releases/tag/8.3.3 +.. _8.3.4: https://github.com/canonical/snapcraft/releases/tag/8.3.4 .. _8.4.0: https://github.com/canonical/snapcraft/releases/tag/8.4.0 diff --git a/requirements-devel.txt b/requirements-devel.txt index 714e376a69..cdd42303c3 100644 --- a/requirements-devel.txt +++ b/requirements-devel.txt @@ -28,7 +28,7 @@ craft-application==4.1.2 craft-archives==2.0.0 craft-cli==2.7.0 craft-grammar==2.0.0 -craft-parts==2.1.0 +craft-parts==2.1.1 craft-platforms==0.1.1 craft-providers==2.0.1 craft-store==3.0.0 diff --git a/requirements-docs.txt b/requirements-docs.txt index 11f007664e..61102c9523 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -23,7 +23,7 @@ craft-application==4.1.2 craft-archives==2.0.0 craft-cli==2.7.0 craft-grammar==2.0.0 -craft-parts==2.1.0 +craft-parts==2.1.1 craft-platforms==0.1.1 craft-providers==2.0.1 craft-store==3.0.0 diff --git a/requirements.txt b/requirements.txt index cd628a7231..75f6107ff1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,7 +11,7 @@ craft-application==4.1.2 craft-archives==2.0.0 craft-cli==2.7.0 craft-grammar==2.0.0 -craft-parts==2.1.0 +craft-parts==2.1.1 craft-platforms==0.1.1 craft-providers==2.0.1 craft-store==3.0.0 diff --git a/snapcraft/commands/remote.py b/snapcraft/commands/remote.py index fd815321d1..2ac7b0e2b3 100644 --- a/snapcraft/commands/remote.py +++ b/snapcraft/commands/remote.py @@ -77,51 +77,51 @@ class RemoteBuildCommand(ExtensibleCommand): @overrides def _fill_parser(self, parser: argparse.ArgumentParser) -> None: parser.add_argument( - "--recover", action="store_true", help="recover an interrupted build" + "--recover", action="store_true", help="Recover an interrupted build" ) parser.add_argument( "--launchpad-accept-public-upload", action="store_true", - help="acknowledge that uploaded code will be publicly available.", + help="Acknowledge that uploaded code will be publicly available", ) parser.add_argument( "--launchpad-timeout", type=int, default=0, metavar="", - help="Time in seconds to wait for launchpad to build.", + help="Time in seconds to wait for launchpad to build", ) parser.add_argument( - "--status", action="store_true", help="display remote build status" + "--status", action="store_true", help="Display remote build status" ) parser.add_argument( - "--build-id", metavar="build-id", help="specific build id to retrieve" + "--build-id", metavar="build-id", help="Specific build ID to retrieve" ) group = parser.add_mutually_exclusive_group() group.add_argument( "--platform", - type=str, + type=lambda arg: [arch.strip() for arch in arg.split(",")], metavar="name", default=os.getenv("CRAFT_PLATFORM"), - help="Set platform to build for", + help="Comma-separated list of platforms 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", + dest="remote_build_platforms", ) group.add_argument( "--build-for", - type=str, + type=lambda arg: [arch.strip() for arch in arg.split(",")], metavar="arch", default=os.getenv("CRAFT_BUILD_FOR"), - help="Set architecture to build for", + help="Comma-separated list of architectures 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", + dest="remote_build_build_fors", ) parser.add_argument( - "--project", help="upload to the specified Launchpad project" + "--project", help="Upload to the specified Launchpad project" ) def _validate(self, parsed_args: argparse.Namespace) -> None: @@ -154,9 +154,9 @@ def _validate(self, parsed_args: argparse.Namespace) -> None: 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 + build_fors = parsed_args.remote_build_build_fors or None + platforms = parsed_args.remote_build_platforms or None + parameter = "--build-for" if build_fors else "--platform" if platforms else None keyword = ( "architectures" if self.project._architectures_in_yaml @@ -171,7 +171,7 @@ def _validate(self, parsed_args: argparse.Namespace) -> None: retcode=os.EX_CONFIG, ) - if platform: + if platforms: if self.project.get_effective_base() == "core22": raise errors.RemoteBuildError( "'--platform' cannot be used for core22 snaps.", @@ -179,27 +179,30 @@ def _validate(self, parsed_args: argparse.Namespace) -> None: 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, - ) + for platform in platforms: + if platform not in SUPPORTED_ARCHS: + raise errors.RemoteBuildError( + f"Unsupported platform {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_fors: + for build_for in build_fors: + if build_for not in SUPPORTED_ARCHS: + raise errors.RemoteBuildError( + f"Unsupported build-for architecture {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, + ) self._validate_single_artifact_per_build_on() @@ -271,10 +274,10 @@ def _run( # noqa: PLR0915 [too-many-statements] emit.trace(f"Project directory: {project_dir}") self._validate(parsed_args) - 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] + if parsed_args.remote_build_build_fors: + architectures = parsed_args.remote_build_build_fors + elif parsed_args.remote_build_platforms: + architectures = parsed_args.remote_build_platforms else: architectures = self._get_project_build_fors() diff --git a/snapcraft/models/project.py b/snapcraft/models/project.py index 3642a2f795..507a1161cd 100644 --- a/snapcraft/models/project.py +++ b/snapcraft/models/project.py @@ -1222,8 +1222,8 @@ def get_build_plan(self) -> list[BuildInfo]: ) for platform_entry, platform in self.platforms.items(): - for build_for in platform.build_for or [SnapArch(platform_entry)]: - for build_on in platform.build_on or [SnapArch(platform_entry)]: + for build_for in platform.build_for or [SnapArch(platform_entry).value]: + for build_on in platform.build_on or [SnapArch(platform_entry).value]: build_infos.append( BuildInfo( platform=platform_entry, diff --git a/tests/spread/core22/remote-build/snaps/build-for-arg/arguments.txt b/tests/spread/core22/remote-build/snaps/build-for-arg/arguments.txt new file mode 100644 index 0000000000..c9eaf14f09 --- /dev/null +++ b/tests/spread/core22/remote-build/snaps/build-for-arg/arguments.txt @@ -0,0 +1 @@ +--build-for amd64,s390x diff --git a/tests/spread/core22/remote-build/snaps/build-for-arg/expected-snaps.txt b/tests/spread/core22/remote-build/snaps/build-for-arg/expected-snaps.txt new file mode 100644 index 0000000000..5b9051821a --- /dev/null +++ b/tests/spread/core22/remote-build/snaps/build-for-arg/expected-snaps.txt @@ -0,0 +1,2 @@ +test-snap-build-for-arg-core22_1.0_amd64.snap +test-snap-build-for-arg-core22_1.0_s390x.snap diff --git a/tests/spread/core22/remote-build/snaps/build-for-arg/snapcraft.yaml b/tests/spread/core22/remote-build/snaps/build-for-arg/snapcraft.yaml new file mode 100644 index 0000000000..4dede42d0d --- /dev/null +++ b/tests/spread/core22/remote-build/snaps/build-for-arg/snapcraft.yaml @@ -0,0 +1,12 @@ +name: test-snap-build-for-arg-core22 +base: core22 +version: "1.0" +summary: Test snap for remote build +description: Test snap for remote build + +grade: stable +confinement: strict + +parts: + my-part: + plugin: nil diff --git a/tests/spread/core22/remote-build/task.yaml b/tests/spread/core22/remote-build/task.yaml index 06faeb0703..feee247997 100644 --- a/tests/spread/core22/remote-build/task.yaml +++ b/tests/spread/core22/remote-build/task.yaml @@ -8,6 +8,7 @@ environment: SNAP/all: all SNAP/no_architectures: no-architectures SNAP/architectures: architectures + SNAP/build_for_arg: build-for-arg SNAPCRAFT_REMOTE_BUILD_STRATEGY: disable-fallback CREDENTIALS_FILE: "$HOME/.local/share/snapcraft/launchpad-credentials" CREDENTIALS_FILE/new_credentials: "$HOME/.local/share/snapcraft/launchpad-credentials" @@ -39,7 +40,13 @@ restore: | execute: | cd "./snaps/$SNAP" - snapcraft remote-build --launchpad-accept-public-upload + call_args="" + if [[ -e "arguments.txt" ]]; then + call_args=$(cat "arguments.txt") + fi + + # shellcheck disable=SC2086 + snapcraft remote-build --launchpad-accept-public-upload $call_args find . -maxdepth 1 -name "*.snap" | MATCH ".snap" diff --git a/tests/spread/core24/npm-reentrant/hello.js b/tests/spread/core24/npm-reentrant/hello.js new file mode 100644 index 0000000000..8001048aa4 --- /dev/null +++ b/tests/spread/core24/npm-reentrant/hello.js @@ -0,0 +1,3 @@ +#!/usr/bin/env node + +console.log('hello world'); diff --git a/tests/spread/core24/npm-reentrant/package-lock.json b/tests/spread/core24/npm-reentrant/package-lock.json new file mode 100644 index 0000000000..cf8ee3b99e --- /dev/null +++ b/tests/spread/core24/npm-reentrant/package-lock.json @@ -0,0 +1,5 @@ +{ + "name": "npm-hello", + "version": "1.0.0", + "lockfileVersion": 1 +} diff --git a/tests/spread/core24/npm-reentrant/package.json b/tests/spread/core24/npm-reentrant/package.json new file mode 100644 index 0000000000..c45d277657 --- /dev/null +++ b/tests/spread/core24/npm-reentrant/package.json @@ -0,0 +1,13 @@ +{ + "name": "npm-hello", + "version": "1.0.0", + "description": "Testing grounds for snapcraft integration tests", + "bin": { + "npm-hello": "hello.js" + }, + "scripts": { + "npm-hello": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "GPL-3.0" +} diff --git a/tests/spread/core24/npm-reentrant/snap/snapcraft.yaml b/tests/spread/core24/npm-reentrant/snap/snapcraft.yaml new file mode 100644 index 0000000000..7a75149e72 --- /dev/null +++ b/tests/spread/core24/npm-reentrant/snap/snapcraft.yaml @@ -0,0 +1,15 @@ +name: npm-reentrant +version: "1.0" +summary: test the npm plugin +description: Check that the npm plugin works across snapcraft calls + +confinement: strict +grade: devel +base: core24 + +parts: + hello: + source: . + plugin: npm + npm-include-node: true + npm-node-version: 22.1.0 diff --git a/tests/spread/core24/npm-reentrant/task.yaml b/tests/spread/core24/npm-reentrant/task.yaml new file mode 100644 index 0000000000..9ad7c48d5d --- /dev/null +++ b/tests/spread/core24/npm-reentrant/task.yaml @@ -0,0 +1,11 @@ +summary: Pull, then Build, a Node snap + +execute: | + snapcraft pull + snapcraft build + snapcraft pack + test -f npm-reentrant*.snap + +restore: | + snapcraft clean + rm -f ./*.snap diff --git a/tests/spread/core24/platforms/snaps/implicit-build-for/expected-snaps.txt b/tests/spread/core24/platforms/snaps/implicit-build-for/expected-snaps.txt new file mode 100644 index 0000000000..faafb3a420 --- /dev/null +++ b/tests/spread/core24/platforms/snaps/implicit-build-for/expected-snaps.txt @@ -0,0 +1 @@ +implicit-build-for_1.0_riscv64.snap diff --git a/tests/spread/core24/platforms/snaps/implicit-build-for/snap/snapcraft.yaml b/tests/spread/core24/platforms/snaps/implicit-build-for/snap/snapcraft.yaml new file mode 100644 index 0000000000..fd28c2073a --- /dev/null +++ b/tests/spread/core24/platforms/snaps/implicit-build-for/snap/snapcraft.yaml @@ -0,0 +1,15 @@ +name: implicit-build-for +version: "1.0" +summary: test +description: | + Use the platform name implicitly for the `build-for`. +confinement: strict +base: core24 + +platforms: + riscv64: + build-on: [amd64] + +parts: + my-part: + plugin: nil diff --git a/tests/spread/core24/platforms/task.yaml b/tests/spread/core24/platforms/task.yaml index 28c89d7ba5..a8a237553d 100644 --- a/tests/spread/core24/platforms/task.yaml +++ b/tests/spread/core24/platforms/task.yaml @@ -9,6 +9,7 @@ environment: SNAP/env_var_all: env-var-all SNAP/env_var_match: env-var-match SNAP/env_var_no_match: env-var-no-match + SNAP/implicit_build_for: implicit-build-for SNAP/multiple_build_for: multiple-build-for SNAP/platform_all: platform-all SNAP/platform_match: platform-match diff --git a/tests/spread/core24/remote-build/snaps/build-for-arg/arguments.txt b/tests/spread/core24/remote-build/snaps/build-for-arg/arguments.txt new file mode 100644 index 0000000000..c9eaf14f09 --- /dev/null +++ b/tests/spread/core24/remote-build/snaps/build-for-arg/arguments.txt @@ -0,0 +1 @@ +--build-for amd64,s390x diff --git a/tests/spread/core24/remote-build/snaps/build-for-arg/expected-snaps.txt b/tests/spread/core24/remote-build/snaps/build-for-arg/expected-snaps.txt new file mode 100644 index 0000000000..ecd71f79c8 --- /dev/null +++ b/tests/spread/core24/remote-build/snaps/build-for-arg/expected-snaps.txt @@ -0,0 +1,2 @@ +test-snap-build-for-arg-core24_1.0_amd64.snap +test-snap-build-for-arg-core24_1.0_s390x.snap diff --git a/tests/spread/core24/remote-build/snaps/build-for-arg/snapcraft.yaml b/tests/spread/core24/remote-build/snaps/build-for-arg/snapcraft.yaml new file mode 100644 index 0000000000..1bafa9fbc4 --- /dev/null +++ b/tests/spread/core24/remote-build/snaps/build-for-arg/snapcraft.yaml @@ -0,0 +1,12 @@ +name: test-snap-build-for-arg-core24 +base: core24 +version: "1.0" +summary: Test snap for remote build +description: Test snap for remote build + +grade: stable +confinement: strict + +parts: + my-part: + plugin: nil diff --git a/tests/spread/core24/remote-build/snaps/platform-arg/arguments.txt b/tests/spread/core24/remote-build/snaps/platform-arg/arguments.txt new file mode 100644 index 0000000000..dddd614311 --- /dev/null +++ b/tests/spread/core24/remote-build/snaps/platform-arg/arguments.txt @@ -0,0 +1 @@ +--platform amd64,s390x diff --git a/tests/spread/core24/remote-build/snaps/platform-arg/expected-snaps.txt b/tests/spread/core24/remote-build/snaps/platform-arg/expected-snaps.txt new file mode 100644 index 0000000000..1185b31b0c --- /dev/null +++ b/tests/spread/core24/remote-build/snaps/platform-arg/expected-snaps.txt @@ -0,0 +1,2 @@ +test-snap-platform-arg-core24_1.0_amd64.snap +test-snap-platform-arg-core24_1.0_s390x.snap diff --git a/tests/spread/core24/remote-build/snaps/platform-arg/snapcraft.yaml b/tests/spread/core24/remote-build/snaps/platform-arg/snapcraft.yaml new file mode 100644 index 0000000000..7f793ff460 --- /dev/null +++ b/tests/spread/core24/remote-build/snaps/platform-arg/snapcraft.yaml @@ -0,0 +1,12 @@ +name: test-snap-platform-arg-core24 +base: core24 +version: "1.0" +summary: Test snap for remote build +description: Test snap for remote build + +grade: stable +confinement: strict + +parts: + my-part: + plugin: nil diff --git a/tests/spread/core24/remote-build/task.yaml b/tests/spread/core24/remote-build/task.yaml index 14f7d0ca54..152d3abec4 100644 --- a/tests/spread/core24/remote-build/task.yaml +++ b/tests/spread/core24/remote-build/task.yaml @@ -11,6 +11,8 @@ environment: SNAP/all: all SNAP/platforms: platforms SNAP/no_platforms: no-platforms + SNAP/platform_arg: platform-arg + SNAP/build_for_arg: build-for-arg CREDENTIALS_FILE: "$HOME/.local/share/snapcraft/launchpad-credentials" CREDENTIALS_FILE/new_credentials: "$HOME/.local/share/snapcraft/launchpad-credentials" CREDENTIALS_FILE/old_credentials: "$HOME/.local/share/snapcraft/provider/launchpad/credentials" @@ -42,7 +44,13 @@ restore: | execute: | cd "./snaps/$SNAP" - snapcraft remote-build --launchpad-accept-public-upload + call_args="" + if [[ -e "arguments.txt" ]]; then + call_args=$(cat "arguments.txt") + fi + + # shellcheck disable=SC2086 + snapcraft remote-build --launchpad-accept-public-upload $call_args find . -maxdepth 1 -name "*.snap" | MATCH ".snap" diff --git a/tests/unit/commands/test_remote.py b/tests/unit/commands/test_remote.py index 0ffb10f9bb..c8e109ef91 100644 --- a/tests/unit/commands/test_remote.py +++ b/tests/unit/commands/test_remote.py @@ -546,7 +546,20 @@ def test_architecture_in_project_metadata( @pytest.mark.parametrize("base", const.CURRENT_BASES - {"core22", "devel"}) -@pytest.mark.parametrize("platform", const.SnapArch) +@pytest.mark.parametrize( + ("platforms", "expected_platforms"), + [ + *zip(const.SnapArch, [[arch] for arch in const.SnapArch]), + ("amd64,riscv64", ["amd64", "riscv64"]), + ("amd64,riscv64,s390x", ["amd64", "riscv64", "s390x"]), + pytest.param(" amd64 , riscv64 ", ["amd64", "riscv64"], id="with-whitespace"), + pytest.param( + "amd64,amd64,riscv64", + ["amd64", "amd64", "riscv64"], + id="launchpad-handles-duplicates", + ), + ], +) def test_platform_argument( mocker, snapcraft_yaml, @@ -554,14 +567,15 @@ def test_platform_argument( fake_services, mock_confirm, mock_remote_builder_fake_build_process, - platform, + platforms, + expected_platforms, ): """Use architectures provided by the `--platform` argument.""" snapcraft_yaml(base=base) mocker.patch.object( sys, "argv", - ["snapcraft", "remote-build", "--platform", platform], + ["snapcraft", "remote-build", "--platform", platforms], ) mock_start_builds = mocker.patch( "craft_application.services.remotebuild.RemoteBuildService.start_builds" @@ -569,11 +583,24 @@ def test_platform_argument( app = application.create_app() app.run() - mock_start_builds.assert_called_once_with(ANY, architectures=[platform]) + mock_start_builds.assert_called_once_with(ANY, architectures=expected_platforms) @pytest.mark.parametrize("base", const.CURRENT_BASES - {"devel"}) -@pytest.mark.parametrize("build_for", const.SnapArch) +@pytest.mark.parametrize( + ("build_fors", "expected_build_fors"), + [ + *zip(const.SnapArch, [[arch] for arch in const.SnapArch]), + ("amd64,riscv64", ["amd64", "riscv64"]), + ("amd64,riscv64,s390x", ["amd64", "riscv64", "s390x"]), + pytest.param(" amd64 , riscv64 ", ["amd64", "riscv64"], id="with-whitespace"), + pytest.param( + "amd64,amd64,riscv64", + ["amd64", "amd64", "riscv64"], + id="duplicates-passthrough-to-launchpad", + ), + ], +) def test_build_for_argument( mocker, snapcraft_yaml, @@ -581,14 +608,15 @@ def test_build_for_argument( fake_services, mock_confirm, mock_remote_builder_fake_build_process, - build_for, + build_fors, + expected_build_fors, ): """Use architectures provided by the `--build-for` argument.""" snapcraft_yaml(base=base) mocker.patch.object( sys, "argv", - ["snapcraft", "remote-build", "--build-for", build_for], + ["snapcraft", "remote-build", "--build-for", build_fors], ) mock_start_builds = mocker.patch( "craft_application.services.remotebuild.RemoteBuildService.start_builds" @@ -596,7 +624,7 @@ def test_build_for_argument( app = application.create_app() app.run() - mock_start_builds.assert_called_once_with(ANY, architectures=[build_for]) + mock_start_builds.assert_called_once_with(ANY, architectures=expected_build_fors) def test_architecture_defined_twice_error( @@ -667,11 +695,21 @@ def test_platform_defined_twice_error( ) in err +@pytest.mark.parametrize( + "platforms", + [ + "nonexistent", + "nonexistent,riscv64", + "riscv64,nonexistent", + "riscv64,nonexistent,amd64", + ], +) @pytest.mark.parametrize("base", const.CURRENT_BASES - {"core22"}) def test_unknown_platform_error( capsys, mocker, snapcraft_yaml, + platforms, base, fake_services, mock_confirm, @@ -686,7 +724,7 @@ def test_unknown_platform_error( mocker.patch.object( sys, "argv", - ["snapcraft", "remote-build", "--platform", "nonexistent"], + ["snapcraft", "remote-build", "--platform", platforms], ) app = application.create_app() @@ -700,11 +738,21 @@ def test_unknown_platform_error( ) in err +@pytest.mark.parametrize( + "build_fors", + [ + "nonexistent", + "nonexistent,riscv64", + "riscv64,nonexistent", + "riscv64,nonexistent,amd64", + ], +) @pytest.mark.parametrize("base", const.CURRENT_BASES - {"core22", "devel"}) def test_unknown_build_for_error( capsys, mocker, snapcraft_yaml, + build_fors, base, fake_services, mock_confirm, @@ -715,7 +763,7 @@ def test_unknown_build_for_error( mocker.patch.object( sys, "argv", - ["snapcraft", "remote-build", "--build-for", "nonexistent"], + ["snapcraft", "remote-build", "--build-for", build_fors], ) mocker.patch( "craft_application.services.remotebuild.RemoteBuildService.start_builds" diff --git a/tests/unit/models/test_projects.py b/tests/unit/models/test_projects.py index 1cb147d676..50b5b07adb 100644 --- a/tests/unit/models/test_projects.py +++ b/tests/unit/models/test_projects.py @@ -2068,6 +2068,37 @@ def test_root_packages_transform_no_affect(self, project_yaml_data): ], id="single_platform_as_arch", ), + pytest.param( + { + "s390x": { + "build-on": "s390x", + }, + "riscv64": { + "build-on": ["amd64", "riscv64"], + }, + }, + [ + BuildInfo( + build_on="s390x", + build_for="s390x", + base=BaseName(name="ubuntu", version="24.04"), + platform="s390x", + ), + BuildInfo( + build_on="amd64", + build_for="riscv64", + base=BaseName(name="ubuntu", version="24.04"), + platform="riscv64", + ), + BuildInfo( + build_on="riscv64", + build_for="riscv64", + base=BaseName(name="ubuntu", version="24.04"), + platform="riscv64", + ), + ], + id="implicit_build_for", + ), pytest.param( { "arm64": {