Simone Pelosi has proposed merging ~pelpsi/lpci:debug-shell-on-exception into lpci:main.
Commit message: Added new debug shell Shell into the environment if the run fails. Requested reviews: Launchpad code reviewers (launchpad-reviewers) For more details, see: https://code.launchpad.net/~pelpsi/lpci/+git/lpcraft/+merge/441108 -- Your team Launchpad code reviewers is requested to review the proposed merge of ~pelpsi/lpci:debug-shell-on-exception into lpci:main.
diff --git a/lpci/tests/test_main.py b/lpci/tests/test_main.py index b67da1e..d35b58b 100644 --- a/lpci/tests/test_main.py +++ b/lpci/tests/test_main.py @@ -78,6 +78,30 @@ class TestMain(TestCase): emitter.recorder.interactions[-1], ) + @patch("lpcraft.commands.run.RunCommand.run") + def test_debug_shell_mode(self, mock_run): + self.useFixture(MockPatch("sys.argv", ["lpcraft", "--debug-shell"])) + mock_run.side_effect = RuntimeError() + + with RecordingEmitterFixture() as emitter: + ret = main() + + self.assertEqual(1, ret) + self.assertEqual( + call( + "progress", + "Launching shell on build environment...", + permanent=True, + ), + emitter.recorder.interactions[-2], + ) + self.assertEqual( + call( + "error", CraftError("lpcraft internal error: RuntimeError()") + ), + emitter.recorder.interactions[-1], + ) + def test_quiet_mode(self): # temporary test until cli API is set and a more meaningful test is # possible diff --git a/lpcraft/main.py b/lpcraft/main.py new file mode 100644 index 0000000..cffa6c4 --- /dev/null +++ b/lpcraft/main.py @@ -0,0 +1,166 @@ +<<<<<<< lpcraft/main.py +======= +# Copyright 2021 Canonical Ltd. This software is licensed under the +# GNU General Public License version 3 (see the file LICENSE). + +"""Main entry point.""" + +import logging +import pathlib +import subprocess +import sys +from typing import List, Optional + +from craft_cli import ( + ArgumentParsingError, + CommandGroup, + CraftError, + Dispatcher, + EmitterMode, + GlobalArgument, + ProvideHelpException, + emit, +) + +from lpcraft._version import version_description as lpcraft_version +from lpcraft.commands.clean import CleanCommand +from lpcraft.commands.release import ReleaseCommand +from lpcraft.commands.run import RunCommand, RunOneCommand +from lpcraft.commands.version import VersionCommand + + +def _configure_logger(name: str) -> None: + """Configure a logger for use with craft-cli. + + Setting up a library's logger in DEBUG level causes its content to be + grabbed by craft-cli's Emitter. + """ + logger = logging.getLogger(name) + logger.setLevel(logging.DEBUG) + + +def _launch_shell(*, cwd: Optional[pathlib.Path] = None) -> None: + """Launch a user shell for debugging environment. + + :param cwd: Working directory to start user in. + """ + emit.progress("Launching shell on build environment...", permanent=True) + with emit.pause(): + subprocess.run(["bash"], check=False, cwd=cwd) + + +_configure_logger("craft_providers") + + +_basic_commands = [ + CleanCommand, + RunCommand, + RunOneCommand, + VersionCommand, +] +_launchpad_commands = [ + ReleaseCommand, +] + + +def main(argv: Optional[List[str]] = None) -> int: + """`lpcraft` runs Launchpad CI jobs.""" + if argv is None: + argv = sys.argv[1:] + debug_shell = False + emit.init(EmitterMode.BRIEF, "lpcraft", f"Starting {lpcraft_version}") + command_groups = [ + CommandGroup("Basic", _basic_commands), + CommandGroup("Launchpad", _launchpad_commands), + ] + summary = "Run Launchpad CI jobs." + extra_global_args = [ + GlobalArgument( + "version", + "flag", + "-V", + "--version", + "Show version information and exit", + ), + GlobalArgument( + "debugshell", + "flag", + "-ds", + "--debug-shell", + "Shell into the environment if the build fails", + ), + ] + + # dispatcher = Dispatcher( + # "lpcraft", + # command_groups, + # summary=summary, + # extra_global_args=extra_global_args, + # default_command=RunCommand, + # ) + # global_args = dispatcher.pre_parse_args(argv) + # if global_args["version"]: + # emit.message(lpcraft_version) + # emit.ended_ok() + # return 0 + # dispatcher.load_command(None) + # ret = dispatcher.run() or 0 + + try: + dispatcher = Dispatcher( + "lpcraft", + command_groups, + summary=summary, + extra_global_args=extra_global_args, + default_command=RunCommand, + ) + global_args = dispatcher.pre_parse_args(argv) + if global_args["debugshell"]: + debug_shell = True + if global_args["version"]: + emit.message(lpcraft_version) + emit.ended_ok() + return 0 + dispatcher.load_command(None) + ret = dispatcher.run() or 0 + except ArgumentParsingError as e: + if debug_shell: + emit.progress(str(e), permanent=True) + _launch_shell() + print(e, file=sys.stderr) + emit.ended_ok() + ret = 1 + except ProvideHelpException as e: + if debug_shell: + emit.progress(str(e), permanent=True) + _launch_shell() + print(e) + emit.ended_ok() + ret = 0 + except CraftError as e: + if debug_shell: + emit.progress(str(e), permanent=True) + _launch_shell() + emit.error(e) + ret = e.retcode + except KeyboardInterrupt as e: + error = CraftError("Interrupted.") + error.__cause__ = e + if debug_shell: + emit.progress(str(e), permanent=True) + _launch_shell() + emit.error(error) + ret = 1 + except Exception as e: + error = CraftError(f"lpcraft internal error: {e!r}") + error.__cause__ = e + if debug_shell: + emit.progress(str(e), permanent=True) + _launch_shell() + emit.error(error) + ret = 1 + else: + emit.ended_ok() + + return ret +>>>>>>> lpcraft/main.py
_______________________________________________ Mailing list: https://launchpad.net/~launchpad-reviewers Post to : launchpad-reviewers@lists.launchpad.net Unsubscribe : https://launchpad.net/~launchpad-reviewers More help : https://help.launchpad.net/ListHelp