-
Notifications
You must be signed in to change notification settings - Fork 251
unbreq plugin: log standard outputs of failed commands #1686
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
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces a helper function, _run_subprocess, to centralize subprocess calls and log their output on failure, which is a great improvement for debuggability. The refactoring is applied consistently throughout the plugin. My feedback includes a couple of suggestions for the new helper function to enhance the logging format and make its error handling more flexible for the different use cases within this file.
mock/py/mockbuild/plugins/unbreq.py
Outdated
| def _run_subprocess( | ||
| command: list[str], *args: Any, expected_returncode: int = 0, **kwargs: Any | ||
| ) -> subprocess.CompletedProcess: | ||
| """ | ||
| Helper function which calls `subprocess.run` but logs standard outputs in | ||
| case of a failure. | ||
| """ | ||
| kwargs.setdefault("stdin", subprocess.DEVNULL) | ||
| kwargs.setdefault("stdout", subprocess.PIPE) | ||
| kwargs.setdefault("stderr", subprocess.PIPE) | ||
| kwargs.setdefault("text", True) | ||
| kwargs.setdefault("check", False) | ||
|
|
||
| process = subprocess.run(command, *args, **kwargs) | ||
| if process.returncode != expected_returncode: | ||
| for line in process.stdout.splitlines(): | ||
| getLog().error("%s", line) | ||
| for line in process.stderr.splitlines(): | ||
| getLog().error("%s", line) | ||
| raise subprocess.CalledProcessError( | ||
| process.returncode, " ".join(process.args), process.stdout, process.stderr | ||
| ) | ||
| return process |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new _run_subprocess function always raises an exception on failure. This is a good default, but some call sites, like in _PostDepsHook, previously ignored failures by using check=False. This pull request changes that behavior to fail-fast.
If this is not intended, consider adding a check: bool = True parameter to _run_subprocess to control whether it raises an exception. You could then call it with check=False in _PostDepsHook to preserve the old behavior.
If you decide to do this, please also note that the logic following the call in _PostDepsHook should be updated to check process.returncode, as the existing if mount_options_process: is always truthy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point but yes, I believe if the plugin can not invoke /usr/bin/findmnt then it probably can not behave correctly, so the new behaviour is good. I should remove the questioning comment though.
mock/py/mockbuild/plugins/unbreq.py
Outdated
| for line in process.stdout.splitlines(): | ||
| getLog().error("%s", line) | ||
| for line in process.stderr.splitlines(): | ||
| getLog().error("%s", line) | ||
| raise subprocess.CalledProcessError( | ||
| process.returncode, " ".join(process.args), process.stdout, process.stderr | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current implementation logs stdout and stderr line by line, which can make logs hard to read if they are interleaved with other messages. As you considered in the pull request description, logging each stream as a single block with a header would be more readable.
Additionally, using mockbuild.util.cmd_pretty to format the command for the exception is more robust than " ".join as it correctly handles arguments with spaces.
| for line in process.stdout.splitlines(): | |
| getLog().error("%s", line) | |
| for line in process.stderr.splitlines(): | |
| getLog().error("%s", line) | |
| raise subprocess.CalledProcessError( | |
| process.returncode, " ".join(process.args), process.stdout, process.stderr | |
| ) | |
| if process.stdout: | |
| getLog().error("stdout:\n%s", process.stdout.strip()) | |
| if process.stderr: | |
| getLog().error("stderr:\n%s", process.stderr.strip()) | |
| raise subprocess.CalledProcessError( | |
| process.returncode, mockbuild.util.cmd_pretty(process.args), process.stdout, process.stderr | |
| ) |
4e729ad to
9355514
Compare
mock/py/mockbuild/plugins/unbreq.py
Outdated
| @traceLog() | ||
| def _run_subprocess( | ||
| command: list[str], *args: Any, expected_returncode: int = 0, **kwargs: Any | ||
| ) -> subprocess.CompletedProcess: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This starts looking like do_with_status() https://github.com/rpm-software-management/mock/blob/main/mock/py/mockbuild/util.py#L527
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I will try to see if it could be replaced.
7a774c8 to
2f96871
Compare
|
This PR has grown in size from the initial one, but there should be no more changes. |
…d by any installed RPM Fixes: rpm-software-management#1690
In case that
subprocess.runfails, the raised exception does not print the outputs of the command. Those outputs are very important for debugging and should be logged.I was not sure about the exact format:
An alternative I considered was: