← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~pelpsi/lpci:debug-shell-on-exception into lpci:main

 

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