From 1f5e8256c284808db6525fb7750da8d99100c310 Mon Sep 17 00:00:00 2001 From: Alex Hoenig Date: Mon, 18 Aug 2025 15:41:29 -0400 Subject: [PATCH 1/2] Added --deployer, --deployer-folder, --deployer-package, and --format=json options to the workspace super-install command --- conan/cli/commands/workspace.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/conan/cli/commands/workspace.py b/conan/cli/commands/workspace.py index 8f85e1fc7bb..998180d5dd0 100644 --- a/conan/cli/commands/workspace.py +++ b/conan/cli/commands/workspace.py @@ -9,6 +9,7 @@ from conan.cli.args import add_reference_args, add_common_install_arguments, add_lockfile_args from conan.cli.command import conan_command, conan_subcommand from conan.cli.commands.list import print_serial +from conan.cli.formatters.graph import format_graph_json from conan.cli.printers import print_profiles from conan.cli.printers.graph import print_graph_packages, print_graph_basic from conan.errors import ConanException @@ -187,7 +188,7 @@ def _install_build(conan_api: ConanAPI, parser, subparser, build, *args): conan_api.command.run(cmd) -@conan_subcommand() +@conan_subcommand(formatters={"json": format_graph_json}) def workspace_super_install(conan_api: ConanAPI, parser, subparser, *args): """ Install the workspace as a monolith, installing only external dependencies to the workspace, @@ -197,6 +198,14 @@ def workspace_super_install(conan_api: ConanAPI, parser, subparser, *args): subparser.add_argument("-g", "--generator", action="append", help='Generators to use') subparser.add_argument("-of", "--output-folder", help='The root output folder for generated and build files') + subparser.add_argument("-d", "--deployer", action="append", + help="Deploy using the provided deployer to the output folder. " + "Built-in deployers: 'full_deploy', 'direct_deploy', 'runtime_deploy'") + subparser.add_argument("--deployer-folder", + help="Deployer output folder, base build folder by default if not set") + subparser.add_argument("--deployer-package", action="append", + help="Execute the deploy() method of the packages matching " + "the provided patterns") subparser.add_argument("--envs-generation", default=None, choices=["false"], help="Generation strategy for virtual environment files for the root") add_common_install_arguments(subparser) @@ -230,9 +239,16 @@ def workspace_super_install(conan_api: ConanAPI, parser, subparser, *args): lockfile=lockfile) print_graph_packages(ws_graph) conan_api.install.install_binaries(deps_graph=ws_graph, remotes=remotes) + ConanOutput().title("Finalizing install (deploy, generators)") output_folder = make_abs_path(args.output_folder) if args.output_folder else None conan_api.install.install_consumer(ws_graph, args.generator, ws_folder, output_folder, + deploy=args.deployer, deploy_package=args.deployer_package, + deploy_folder=args.deployer_folder, envs_generation=args.envs_generation) + ConanOutput().success("Install finished successfully") + + return {"graph": ws_graph, + "conan_api": conan_api} @conan_subcommand() From 38f9273c916e978db971e5e4c1e27fdf8f2ab6d1 Mon Sep 17 00:00:00 2001 From: memsharded Date: Wed, 19 Nov 2025 10:27:41 +0100 Subject: [PATCH 2/2] add test --- test/integration/workspace/test_workspace.py | 40 ++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/test/integration/workspace/test_workspace.py b/test/integration/workspace/test_workspace.py index b5c92f9a999..44c4f7814b7 100644 --- a/test/integration/workspace/test_workspace.py +++ b/test/integration/workspace/test_workspace.py @@ -785,6 +785,46 @@ def test_intermediate_non_editable(self): assert ("Workspace definition error. Package libb/0.1 in the Conan cache " "has dependencies to packages in the workspace: [liba/0.1]") in c.out + def test_deployers_json(self): + c = TestClient() + dep = textwrap.dedent(""" + import os + from conan.tools.files import save + from conan import ConanFile + class Dep(ConanFile): + name = "dep" + version = "1.0" + + def package(self): + save(self, os.path.join(self.package_folder, "myfile.txt"), "content") + """) + pkg = textwrap.dedent(""" + import os + from conan.tools.files import save + from conan import ConanFile + class Dep(ConanFile): + name = "pkg" + version = "1.0" + requires = "dep/1.0" + + def package(self): + save(self, os.path.join(self.package_folder, "myfile.txt"), "content") + """) + c.save({"dep/conanfile.py": dep, + "pkg/conanfile.py": pkg}) + c.run("workspace init") + c.run("create dep") + c.run("workspace add pkg") + c.run("workspace super-install --format=json --deployer=full_deploy") + graph = json.loads(c.stdout) + # Only 1 node, pkg is not a node in the graph! + assert graph["graph"]["nodes"]["1"]["name"] == "dep" + deploy_folder = os.path.join(c.current_folder, "full_deploy", "host") + folders = os.listdir(deploy_folder) + assert "dep" in folders + assert "pkg" not in folders + assert os.path.isfile(os.path.join(deploy_folder, "dep", "1.0", "myfile.txt")) + def test_workspace_with_local_recipes_index(): c3i_folder = temp_folder()