-
Notifications
You must be signed in to change notification settings - Fork 24
feat: modify run_docker_command to always return EntrypointOutput #613
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?
feat: modify run_docker_command to always return EntrypointOutput #613
Conversation
- Always store STDOUT to disk for memory efficiency - Add returncode and stderr properties to EntrypointOutput for backward compatibility - Update all callers in standard tests to use EntrypointOutput return type - Improve error analysis and readability in test failure outputs - Maintain strict backward compatibility through enhanced EntrypointOutput properties Co-Authored-By: AJ Steers <aj@airbyte.io>
Original prompt from AJ Steers:
|
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
Co-Authored-By: AJ Steers <aj@airbyte.io>
@@ -68,6 +69,7 @@ def __init__( | |||
uncaught_exception: Optional[BaseException] = None, | |||
*, | |||
message_file: Path | None = None, | |||
completed_process: Optional[subprocess.CompletedProcess[str]] = None, |
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.
Remove this from the constructor. Instead add a @classmethod factory function "from_completed_process()".
@property | ||
def returncode(self) -> int | None: | ||
"""Return the exit code of the process, if available.""" | ||
return self._completed_process.returncode if self._completed_process else None | ||
|
||
@property | ||
def stderr(self) -> str | None: | ||
"""Return the stderr output of the process, if available.""" | ||
return self._completed_process.stderr if self._completed_process else None | ||
|
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.
We can delete these as not needed.
- Remove completed_process parameter from constructor as requested - Add @classmethod from_completed_process() factory method - Remove returncode and stderr properties as they are not needed - Update callers to use EntrypointOutput.errors for failure detection - Addresses GitHub PR feedback from @aaronsteers Co-Authored-By: AJ Steers <aj@airbyte.io>
cls, | ||
completed_process: subprocess.CompletedProcess[str], | ||
*, | ||
message_file: Path | None = None, |
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.
Let's call this stdout_file
- since we're talking about the stdout stream in this context. (It's also the message file, but in the context of process completion, I think stdout_file
is more clear.
- Rename parameter from message_file to stdout_file for better clarity - Update caller in run_docker_command() to use new parameter name - Addresses GitHub PR feedback from @aaronsteers Co-Authored-By: AJ Steers <aj@airbyte.io>
"""Create EntrypointOutput from a completed subprocess with optional message file.""" | ||
instance = cls(message_file=message_file) | ||
"""Create EntrypointOutput from a completed subprocess with optional stdout file.""" | ||
instance = cls(message_file=stdout_file) |
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.
If stdout_file is none, then completed_process.stdout
might have valid output. Since stdout_file
is optional, we should fall back to a "captured stdout" scenario, where stdout
was captured in memory, and in that case would be available in the completed_process object.
- Handle case when stdout_file is None by falling back to completed_process.stdout - Create EntrypointOutput from captured stdout messages when no file provided - Maintain backward compatibility for both file-based and memory-based stdout - Addresses GitHub PR feedback from @aaronsteers Co-Authored-By: AJ Steers <aj@airbyte.io>
@@ -76,6 +77,7 @@ def __init__( | |||
|
|||
self._messages: list[AirbyteMessage] | None = None | |||
self._message_file: Path | None = message_file | |||
self._completed_process: Optional[subprocess.CompletedProcess[str]] = None |
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.
I don't think we need _completed_process
- if we can pass along all critical data during the from_completed_process() implementation, then we don't need to store the completed process object itself.
- Remove _completed_process field from EntrypointOutput class - No functionality lost as the attribute was never used after assignment - Simplifies the class by not storing unnecessary references - Addresses GitHub PR feedback from @aaronsteers Co-Authored-By: AJ Steers <aj@airbyte.io>
messages = completed_process.stdout.splitlines() | ||
instance = cls(messages=messages) | ||
else: | ||
instance = cls() |
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.
Let's raise a ValueError here. Either stdout_file
should be provided, or completed_process.stdout
should not be None
.
…ted_process - Replace empty EntrypointOutput creation with ValueError - Add clear error message when both stdout_file and completed_process.stdout are None - Improves error handling and prevents silent failures - Addresses GitHub PR feedback from @aaronsteers Co-Authored-By: AJ Steers <aj@airbyte.io>
if read_result.errors: | ||
error_messages = [ | ||
f"Error message: {error.trace.error.message}" | ||
for error in read_result.errors | ||
if error.trace and error.trace.error | ||
] | ||
if not error_messages: | ||
error_messages = ["No structured error messages found"] |
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.
Devin - Let's move the "whet the heck happened?" logic into a method on the EntrypointOutput class.
if read_result.errors: | |
error_messages = [ | |
f"Error message: {error.trace.error.message}" | |
for error in read_result.errors | |
if error.trace and error.trace.error | |
] | |
if not error_messages: | |
error_messages = ["No structured error messages found"] | |
if read_result.errors: | |
error_message = read_result.get_error_message() |
- Move error message extraction logic from test code into reusable method - Simplify error handling in docker_base.py test - Improve code maintainability and reduce duplication - Addresses GitHub PR feedback from @aaronsteers Co-Authored-By: AJ Steers <aj@airbyte.io>
feat: modify run_docker_command to always return EntrypointOutput
Summary
This PR modifies the
run_docker_command()
function to always return anEntrypointOutput
object instead of a rawsubprocess.CompletedProcess
, with the goal of improving error analysis and readability in standard test failures. The key changes include:returncode
,stderr
) to EntrypointOutputThe motivation for this change is that standard tests like
test_docker_image_build_and_check
currently produce unreadable failure outputs with raw stdout/stderr text, making debugging difficult. EntrypointOutput provides structured parsing of Airbyte protocol messages, cleaner error formatting, and access to specific message types.Review & Testing Checklist for Human
run_docker_command()
callers - I updated the callers I found, but there may be others that expectCompletedProcess
return typeRecommended test plan: Run
test_docker_image_build_and_check
with a connector that has known failures and compare error output quality before/after this change.Diagram
Notes
returncode
andstderr
properties to EntrypointOutput so existing code patterns still workRisk: This is a breaking change to a core utility function. While I've tried to maintain compatibility through EntrypointOutput properties, any code directly expecting
CompletedProcess
will need updates.