diff --git a/craft_providers/base.py b/craft_providers/base.py index d8b4477f3..4d398cdbf 100644 --- a/craft_providers/base.py +++ b/craft_providers/base.py @@ -1223,4 +1223,10 @@ def _execute_run( if verify_network and not cls._network_connected(executor=executor): raise NetworkError from exc raise + + if proc.stdout: + logger.debug("Command stdout: %s", proc.stdout) + if proc.stderr: + logger.debug("Command stderr: %s", proc.stderr) + return proc diff --git a/tests/unit/bases/test_ubuntu_buildd.py b/tests/unit/bases/test_ubuntu_buildd.py index c33273d0c..bbe136fb6 100644 --- a/tests/unit/bases/test_ubuntu_buildd.py +++ b/tests/unit/bases/test_ubuntu_buildd.py @@ -1674,6 +1674,53 @@ def test_execute_run_bad_check_verifynetwork_combination(fake_executor): ) +def test_execute_run_logs_output_at_debug(fake_executor, fake_process, logs): + """_execute_run() should log command stdout at debug level. + + Regression test for https://github.com/canonical/craft-providers/issues/250 + """ + base_config = ubuntu.BuilddBase(alias=ubuntu.BuilddBaseAlias.JAMMY) + command = ["the", "command"] + fake_process.register_subprocess( + [*DEFAULT_FAKE_CMD, *command], + returncode=0, + stdout=b"important command output", + ) + + base_config._execute_run(command, executor=fake_executor) + + assert "important command output" in logs.debug + + +def test_execute_run_output_included_in_error_details(fake_executor, fake_process): + """When a subprocess fails, its stdout must appear in the error details. + + Regression test for https://github.com/canonical/craft-providers/issues/250 + """ + base_config = ubuntu.BuilddBase(alias=ubuntu.BuilddBaseAlias.JAMMY) + + fake_process.register_subprocess( + [*DEFAULT_FAKE_CMD, "cat", "/etc/os-release"], + stdout="UBUNTU_CODENAME=jammy", + ) + fake_process.register_subprocess( + [*DEFAULT_FAKE_CMD, "apt-get", "update"], + returncode=100, + stdout=b"Err:1 http://archive.ubuntu.com/ubuntu jammy InRelease\n Connection refused", + ) + fake_process.register_subprocess( + [*DEFAULT_FAKE_CMD, "bash", "-c", "exec 3<> /dev/tcp/snapcraft.io/443"], + ) + + with pytest.raises(BaseConfigurationError) as exc_info: + base_config._pre_setup_packages(executor=fake_executor) + + assert "Connection refused" in str(exc_info.value), ( + "stdout from the failed subprocess must appear in the error details " + "so the user knows why apt-get update failed" + ) + + @pytest.mark.usefixtures("stub_verify_network") def test_network_connectivity_yes(fake_executor, fake_process): """Connectivity is ok."""