-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Add conan run command to run packages from Conan directly
#18972
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
50 commits
Select commit
Hold shift + click to select a range
be1a753
Initial sketch for conan run command
AbrilRBS 709d1f5
Sketch install built-in in run command
AbrilRBS a2b04d1
Fix test
AbrilRBS 6967d6b
Use conanfile run method which handles context and subprocess
perseoGI 49785fd
Add test assert
perseoGI 8253f02
Added test case for conan run with conanfile
perseoGI 0110713
Add missing os setting for tests
AbrilRBS fd72c3d
Updated default options according to Look Intos meet
perseoGI c2975b9
Merge branch 'develop2' into ar/conan-run-command
AbrilRBS 9d78a1b
Sketch output handling, might be reverted later
AbrilRBS 8d204f7
Sketch output handling, might be reverted later
AbrilRBS 58c02e1
Merge branch 'ar/conan-run-command' of github.com:AbrilRBS/conan into…
AbrilRBS d36d3d3
Warning for installation taking a while
AbrilRBS 6ca752f
Colour, make info so warnings as errors does not trigger
AbrilRBS e476de0
Bring back build-require, be consistent with conan build/install comm…
AbrilRBS e08cb7b
TODO for --no-remote
AbrilRBS 75f0f3f
This command is experimental
AbrilRBS 30edc55
use both envs by default
AbrilRBS a6fdc6f
--no-remote proposal
AbrilRBS bb6dc70
We have decided against it
AbrilRBS bcc7d1f
Test that host context has priority
AbrilRBS 180b016
Test cleanup
AbrilRBS 2383f5f
Update conan/cli/commands/run.py
AbrilRBS b95c4d9
Fix tests
AbrilRBS 3c109cd
Merge branch 'ar/conan-run-command' of github.com:AbrilRBS/conan into…
AbrilRBS eb6312c
Move files to temp
AbrilRBS d04f796
better output msgs
AbrilRBS e197c12
Format
AbrilRBS 4a1620f
Format
AbrilRBS 6d0960d
Shhh
AbrilRBS e256b1c
Shhh
AbrilRBS c165352
Cleanup APIs, dont rewrite for now
AbrilRBS 961c2a5
Public api
AbrilRBS 04d180a
Output error message
AbrilRBS f1544e6
Missing space
AbrilRBS 8832423
Merge branch 'develop2' into ar/conan-run-command
AbrilRBS 1c53422
Apply suggestion from @AbrilRBS
AbrilRBS 46005d4
Fix syntax
AbrilRBS 6b82b83
Add missing classmethod decorator
AbrilRBS a8b4982
Fix none assignation for log level
AbrilRBS 66f78d7
fix
AbrilRBS 7b57e54
Simplify command argument
AbrilRBS 0e8512e
Simplify output
AbrilRBS 7103087
Merge branch 'develop2' into ar/conan-run-command
AbrilRBS 2360264
Tests, fix merge
AbrilRBS b66796b
Reorder
AbrilRBS 9dc7a66
Better error check
AbrilRBS 03b28b9
Improve install apis and internal install-error propagation
AbrilRBS 5277cf0
Fix quiet usage in system package
AbrilRBS 69a98e3
Merge branch 'develop2' into ar/conan-run-command
AbrilRBS File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| import os | ||
| import tempfile | ||
|
|
||
| from conan.api.output import ConanOutput, LEVEL_STATUS, Color, LEVEL_ERROR, LEVEL_QUIET | ||
| from conan.cli.args import common_graph_args, validate_common_graph_args | ||
| from conan.cli.command import conan_command | ||
| from conan.cli.commands.install import _run_install_command | ||
| from conan.errors import ConanException | ||
|
|
||
|
|
||
| @conan_command(group="Consumer") | ||
| def run(conan_api, parser, *args): | ||
| """ | ||
| (Experimental) Run a command given a set of requirements from a recipe or from command line. | ||
| """ | ||
| common_graph_args(parser) | ||
| parser.add_argument("command", help="Command to run") | ||
| parser.add_argument("--context", help="Context to use, by default both contexts are activated " | ||
| "if not specified", | ||
| choices=["host", "build"], default=None) | ||
| parser.add_argument("--build-require", action='store_true', default=False, | ||
| help='Whether the provided path is a build-require') | ||
| args = parser.parse_args(*args) | ||
| validate_common_graph_args(args) | ||
| cwd = os.getcwd() | ||
|
|
||
| ConanOutput().info("Installing and building dependencies, this might take a while...", | ||
| fg=Color.BRIGHT_MAGENTA) | ||
| previous_log_level = ConanOutput.get_output_level() | ||
| if previous_log_level == LEVEL_STATUS: | ||
| ConanOutput.set_output_level(LEVEL_QUIET) | ||
|
|
||
| with tempfile.TemporaryDirectory("conanrun") as tmpdir: | ||
| # Default values for install | ||
| setattr(args, "output_folder", tmpdir) | ||
| setattr(args, "generator", []) | ||
| try: | ||
| deps_graph, lockfile, _ = _run_install_command(conan_api, args, cwd, | ||
| return_install_error=False) | ||
| except ConanException as e: | ||
| ConanOutput.set_output_level(previous_log_level) | ||
| ConanOutput().error("Error installing the dependencies. To debug this, you can either:\n" | ||
| " - Re-run the command with increased verbosity (-v, -vv)\n" | ||
| " - Run 'conan install' first to ensure dependencies are installed, " | ||
| "or to see errors during installation\n") | ||
| raise e | ||
|
|
||
| context_env_map = { | ||
| "build": "conanbuild", | ||
| "host": "conanrun", | ||
| } | ||
| envfiles = list(context_env_map.values()) if args.context is None \ | ||
| else [context_env_map.get(args.context)] | ||
| ConanOutput.set_output_level(LEVEL_ERROR) | ||
| deps_graph.root.conanfile.run(args.command, cwd=cwd, env=envfiles) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,105 @@ | ||
| import textwrap | ||
memsharded marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| import pytest | ||
| import platform | ||
|
|
||
| from conan.test.assets.genconanfile import GenConanfile | ||
| from conan.test.utils.tools import TestClient | ||
|
|
||
|
|
||
| executable = "myapp.bat" if platform.system() == "Windows" else "myapp.sh" | ||
|
|
||
|
|
||
| @pytest.fixture(scope="module") | ||
| def client(): | ||
| tc = TestClient(default_server_user=True) | ||
| conanfile = textwrap.dedent(""" | ||
| from conan import ConanFile | ||
| from conan.tools.files import save | ||
| import os | ||
|
|
||
| class Pkg(ConanFile): | ||
| name = "pkg" | ||
| version = "0.1" | ||
| # So that the requirement is run=True even for --requires | ||
| package_type = "application" | ||
| options = {"foo": [True, False, "bar"]} | ||
| default_options = {"foo": True} | ||
| settings = "os" | ||
|
|
||
| def package(self): | ||
| executable = os.path.join(self.package_folder, "bin", '""" + executable + """') | ||
| save(self, executable, f"echo Hello World! foo={self.options.foo}") | ||
| # Make it executable | ||
| os.chmod(executable, 0o755) | ||
| """) | ||
| tc.save({"pkg/conanfile.py": conanfile}) | ||
| tc.run("create pkg") | ||
| return tc | ||
|
|
||
|
|
||
| @pytest.mark.parametrize("context_flag", ["host", "build", None]) | ||
| @pytest.mark.parametrize("requires_context", ["host", "build",]) | ||
| @pytest.mark.parametrize("use_conanfile", [True, False]) | ||
| def test_run(client, context_flag, requires_context, use_conanfile): | ||
| context_arg = { | ||
| "host": "--context=host", | ||
| "build": "--context=build", | ||
| None: "", | ||
| }.get(context_flag) | ||
| should_find_binary = (context_flag == requires_context) or (context_flag is None) | ||
| if use_conanfile: | ||
| conanfile_consumer = GenConanfile("consumer", "1.0").with_settings("os") | ||
| if requires_context == "host": | ||
| conanfile_consumer.with_requires("pkg/0.1") | ||
| else: | ||
| conanfile_consumer.with_tool_requires("pkg/0.1") | ||
|
|
||
| client.save({"conanfile.py": conanfile_consumer}) | ||
| client.run(f"run {executable} {context_arg}", assert_error=not should_find_binary) | ||
| else: | ||
| requires = "requires" if requires_context == "host" else "tool-requires" | ||
| client.run(f"run {executable} --{requires}=pkg/0.1 {context_arg}", | ||
| assert_error=not should_find_binary) | ||
| if should_find_binary: | ||
| assert "Hello World!" in client.out | ||
| else: | ||
| if platform.system() == "Windows": | ||
| assert "not recognized as an internal or external command" in client.out | ||
| else: | ||
| assert "Error 127 while executing" in client.out | ||
|
|
||
|
|
||
| def test_run_context_priority(client): | ||
| client.run("create pkg -o=pkg/*:foo=False") | ||
|
|
||
| client.run(f"run {executable} --requires=pkg/0.1 --tool-requires=pkg/0.1 -o:b=pkg/*:foo=False") | ||
| # True is host, False is build, run gives priority to host | ||
| assert "Hello World! foo=True" in client.out | ||
|
|
||
|
|
||
| def test_run_missing_executable(client): | ||
| client.run(f"run a-binary-name-that-does-not-exist --requires=pkg/0.1", assert_error=True) | ||
| if platform.system() == "Windows": | ||
| assert "not recognized as an internal or external command" in client.out | ||
| else: | ||
| assert "Error 127 while executing" in client.out | ||
|
|
||
|
|
||
| def test_run_missing_binary(client): | ||
| client.run("run foo --requires=pkg/0.1 -o=pkg/*:foo=bar", assert_error=True) | ||
| assert "Error installing the dependencies" in client.out | ||
| assert "Missing prebuilt package for 'pkg/0.1'" in client.out | ||
|
|
||
|
|
||
| def test_run_missing_package(client): | ||
| client.run("run foo --requires=pkg/2.1", assert_error=True) | ||
| assert "Error installing the dependencies" in client.out | ||
| assert "Package 'pkg/2.1' not resolved" in client.out | ||
|
|
||
|
|
||
| @pytest.mark.skipif(platform.system() == "Windows", reason="Unix only") | ||
| def test_run_status_is_propagated(client): | ||
| client.run("run false --requires=pkg/0.1", assert_error=True) | ||
| assert "Error installing the dependencies" not in client.out | ||
| assert "ERROR: Error 1 while executing" in client.out | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.