From de95cac3ff22b14fdb02dcbcecc1d5c5c6e45285 Mon Sep 17 00:00:00 2001 From: Tejas-Raj01 Date: Sat, 25 Jul 2026 14:18:27 +0530 Subject: [PATCH] feat: add --project-dir support for remote-build --- docs/release-notes/snapcraft-9-0.rst | 5 +++ pyproject.toml | 2 +- snapcraft/commands/remote.py | 15 +++++++- .../snaps/project-dir/arguments.txt | 1 + .../snaps/project-dir/expected-snaps.txt | 1 + .../project-dir/my-subdir/snapcraft.yaml | 11 ++++++ tests/spread/core24/remote-build/task.yaml | 14 +++++--- tests/unit/commands/test_remote.py | 36 ++++++++++++++++++- uv.lock | 10 ++---- 9 files changed, 80 insertions(+), 15 deletions(-) create mode 100644 tests/spread/core24/remote-build/snaps/project-dir/arguments.txt create mode 100644 tests/spread/core24/remote-build/snaps/project-dir/expected-snaps.txt create mode 100644 tests/spread/core24/remote-build/snaps/project-dir/my-subdir/snapcraft.yaml diff --git a/docs/release-notes/snapcraft-9-0.rst b/docs/release-notes/snapcraft-9-0.rst index 08ea8bf43a..13c2e96ab1 100644 --- a/docs/release-notes/snapcraft-9-0.rst +++ b/docs/release-notes/snapcraft-9-0.rst @@ -93,6 +93,11 @@ sources. Minor features -------------- +Custom build paths for remote build +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The remote-build command now supports a ``--project-dir`` option to specify custom build paths for monorepo setups (`#6287`). + Snapcraft 9.0 brings the following minor changes. Promote edge channels with ``--yes`` diff --git a/pyproject.toml b/pyproject.toml index 6e28a99223..0d18b578f5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ dynamic = ["version"] dependencies = [ "catkin-pkg==1.1.0; sys_platform == 'linux'", "click>=8.3.3", - "craft-application[remote]>=7.1.0", + "craft-application[remote] @ git+https://github.com/canonical/craft-application.git@main", "craft-archives>=2.2.0", "craft-cli>=3.4.0", "craft-grammar>=2.3.0", diff --git a/snapcraft/commands/remote.py b/snapcraft/commands/remote.py index c726049a5d..80d86d809c 100644 --- a/snapcraft/commands/remote.py +++ b/snapcraft/commands/remote.py @@ -81,6 +81,14 @@ def _fill_parser(self, parser: argparse.ArgumentParser) -> None: dest="remote_build_build_fors", ) + parser.add_argument( + "--project-dir", + type=str, + metavar="path", + help="Directory containing the snap project to build", + dest="project_dir", + ) + @override def _pre_build(self, parsed_args: argparse.Namespace): """Perform pre-build validation. @@ -179,4 +187,9 @@ def _get_build_args(self, parsed_args: argparse.Namespace) -> dict[str, Any]: ) emit.debug(f"Architectures to build for: {humanize_list(archs, 'and')}") - return {"architectures": archs} + build_args: dict[str, Any] = {"architectures": archs} + + if getattr(parsed_args, "project_dir", None): + build_args["build_path"] = parsed_args.project_dir + + return build_args diff --git a/tests/spread/core24/remote-build/snaps/project-dir/arguments.txt b/tests/spread/core24/remote-build/snaps/project-dir/arguments.txt new file mode 100644 index 0000000000..434d12cb78 --- /dev/null +++ b/tests/spread/core24/remote-build/snaps/project-dir/arguments.txt @@ -0,0 +1 @@ +--project-dir my-subdir diff --git a/tests/spread/core24/remote-build/snaps/project-dir/expected-snaps.txt b/tests/spread/core24/remote-build/snaps/project-dir/expected-snaps.txt new file mode 100644 index 0000000000..8ca7eaa390 --- /dev/null +++ b/tests/spread/core24/remote-build/snaps/project-dir/expected-snaps.txt @@ -0,0 +1 @@ +my-remote-snap_0.1_amd64.snap diff --git a/tests/spread/core24/remote-build/snaps/project-dir/my-subdir/snapcraft.yaml b/tests/spread/core24/remote-build/snaps/project-dir/my-subdir/snapcraft.yaml new file mode 100644 index 0000000000..cfd942299a --- /dev/null +++ b/tests/spread/core24/remote-build/snaps/project-dir/my-subdir/snapcraft.yaml @@ -0,0 +1,11 @@ +name: my-remote-snap +base: core24 +version: '0.1' +summary: Test snap for project-dir remote build +description: A minimal project to test remote builds using project-dir. +grade: devel +confinement: devmode + +parts: + my-part: + plugin: nil diff --git a/tests/spread/core24/remote-build/task.yaml b/tests/spread/core24/remote-build/task.yaml index 0006dffeef..4e8b55b7f8 100644 --- a/tests/spread/core24/remote-build/task.yaml +++ b/tests/spread/core24/remote-build/task.yaml @@ -14,6 +14,7 @@ environment: SNAP/build_for: build-for SNAP/build_for_with_platforms: build-for-with-platforms SNAP/build_for_with_shorthand_platforms: build-for-with-shorthand-platforms + SNAP/project_dir: project-dir CREDENTIALS_FILE: "$HOME/.local/share/snapcraft/launchpad-credentials" prepare: | @@ -24,18 +25,20 @@ prepare: | exit 1 fi - # commit the project git config --global --add safe.directory "$PWD" git init - git add snapcraft.yaml + + if [[ -d "my-subdir" ]]; then + git add my-subdir/snapcraft.yaml + else + git add snapcraft.yaml + fi + git commit -m "Initial Commit" - # set up launchpad token mkdir -p "$(dirname "$CREDENTIALS_FILE")" echo -e "$LAUNCHPAD_TOKEN" > "$CREDENTIALS_FILE" - # build ids are based on the project contents - # adding a date ensures each test has a unique build id date > date.txt restore: | @@ -81,3 +84,4 @@ execute: | exit 1 fi fi +1 diff --git a/tests/unit/commands/test_remote.py b/tests/unit/commands/test_remote.py index 26fad469bc..b46ffb84bb 100644 --- a/tests/unit/commands/test_remote.py +++ b/tests/unit/commands/test_remote.py @@ -536,7 +536,7 @@ def test_unknown_build_for_error( ], ) @pytest.mark.usefixtures("emitter", "mock_argv", "mock_remote_start_builds") -def test_multiple_artifacts_per_build_on( +def test_multiple_artifacts_per_build_on( # noqa: PLR0917 default_project, fake_services, setup_project, @@ -567,3 +567,37 @@ def test_multiple_artifacts_per_build_on( ) for message in error_messages: check.is_in(message, err) + + +@pytest.mark.usefixtures("emitter") +def test_project_dir_argument( + default_project, + fake_services, + setup_project, + mock_remote_start_builds, + fake_app, + mocker, +): + """Test that `--project-dir` passes the build_path argument.""" + mocker.patch.object( + sys, + "argv", + [ + "snapcraft", + "remote-build", + "--launchpad-accept-public-upload", + "--project-dir", + "my-subdir", + ], + ) + setup_project( + fake_services, + {**default_project.marshal(), "base": "core24"}, + write_project=True, + ) + + fake_app.run() + + mock_remote_start_builds.assert_called_once_with( + ANY, architectures=[str(DebianArchitecture.from_host())], build_path="my-subdir" + ) diff --git a/uv.lock b/uv.lock index b492b47291..60939ef310 100644 --- a/uv.lock +++ b/uv.lock @@ -491,8 +491,8 @@ toml = [ [[package]] name = "craft-application" -version = "7.1.0" -source = { registry = "https://pypi.org/simple" } +version = "7.1.0.post20+g949d2df" +source = { git = "https://github.com/canonical/craft-application.git?rev=main#949d2dfe4ce1a1c7cd3c2ac1762e686b3c410886" } dependencies = [ { name = "annotated-types" }, { name = "craft-archives" }, @@ -513,10 +513,6 @@ dependencies = [ { name = "snap-http" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/6b/c3/be96c01c1b92a7a7eb6cafa881ccd09a6b9e1db1355835fc98f001680cc3/craft_application-7.1.0.tar.gz", hash = "sha256:e0a3fb2080bf1dd6daf8b570262716f79a5f307a87d3ed2b986eaca50e07efed", size = 663202, upload-time = "2026-07-07T22:02:40.491Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/eb/ce/169bdacdfbda0fe8a880d914be0794fc5379b7ec577546444f1572f4762d/craft_application-7.1.0-py3-none-any.whl", hash = "sha256:3319310644d1d935fd7e2fb285fa38bc87c490f3d4fb72fed934e6202164b7bc", size = 212571, upload-time = "2026-07-07T22:02:38.317Z" }, -] [package.optional-dependencies] remote = [ @@ -2519,7 +2515,7 @@ types = [ requires-dist = [ { name = "catkin-pkg", marker = "sys_platform == 'linux'", specifier = "==1.1.0" }, { name = "click", specifier = ">=8.3.3" }, - { name = "craft-application", extras = ["remote"], specifier = ">=7.1.0" }, + { name = "craft-application", extras = ["remote"], git = "https://github.com/canonical/craft-application.git?rev=main" }, { name = "craft-archives", specifier = ">=2.2.0" }, { name = "craft-cli", specifier = ">=3.4.0" }, { name = "craft-grammar", specifier = ">=2.3.0" },