Log workflow output - #14301
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #14301 +/- ##
==========================================
+ Coverage 91.75% 91.77% +0.01%
==========================================
Files 485 486 +1
Lines 34700 34849 +149
==========================================
+ Hits 31840 31983 +143
- Misses 2860 2866 +6
Flags with carried forward coverage won't be shown. Click here to find out more.
|
| @contextlib.contextmanager | ||
| def capture(self) -> Iterator[io.StringIO]: | ||
| """Record what the calling thread writes for the duration of the block.""" | ||
| buffer = io.StringIO() |
There was a problem hiding this comment.
shouldn't all of this be in the try block rather than only the yield?
There was a problem hiding this comment.
I meant more like if this fails buffers = self._buffers, but I guess then we don't want to remove it from the list.
So it might be good 👍
| CANCELLED = "cancelled" | ||
|
|
||
|
|
||
| def _job_description( |
There was a problem hiding this comment.
This can't be a WorkflowJobResult member / function?
xjules
left a comment
There was a problem hiding this comment.
It looks already very good!
Had only a smaller comments.
Also, there are way to many articles in the test names: remove the, a and an
cebcb52 to
5682c06
Compare
Internal python workflow jobs wrote straight to sys.stdout/sys.stderr, so their output was visible in the terminal but not available to ERT itself. External jobs captured their subprocess output but did not pass stdout on to the terminal. Replace sys.stdout/sys.stderr with a proxy while a job runs, recording what the calling thread writes while still forwarding it to the real stream. Capture is per-thread, so concurrently running jobs do not pick up each other's output. Also stop reporting a failing external job with an ERT stack trace: the new ExternalScriptError carries the exit code, since the traceback would only show ERT internals. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
WorkflowJobRunner.run() set the running flag before validating its arguments but only cleared it on the success path, so a job rejected for too few or too many arguments kept reporting that it was still running. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
workflowReport() is keyed by job name, so a workflow running the same job more than once kept only the output of the last invocation. Add WorkflowJobResult, recording name, index, arguments, output, status and timestamp per invocation, and expose the ordered list through workflowJobResults(). workflowReport() is left as it is, since the run workflow tool and the CLI still use it. Jobs skipped because the workflow was cancelled are recorded too, so a cancelled workflow can be told apart from one that never ran. A job that stops the workflow is now recorded before the error is raised, so its output is not lost. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Workflow carried no name of its own, so anything reporting on a workflow had to fall back to the source file path. LOAD_WORKFLOW lets a workflow be given a name, and that is the name users recognise. Store the name on Workflow, defaulting to the file name when none is given, so it can be reported alongside the jobs that were run. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Workflow job output only reached the terminal ERT was started from, so it was lost once that terminal was gone, and a job run outside a terminal left no record at all. Write one entry per job invocation to the ERT log, naming the hook, the workflow and the job, and quoting the arguments, stdout and stderr. This covers hooked workflows, 'ert workflow' and the GUI Run workflow tool, since all three go through WorkflowRunner. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the failed/cancelled boolean pair on WorkflowJobResult with a single WorkflowJobStatus enum. The two booleans could express states that do not exist, and a job interrupted mid-run was reported as failed because only the pre-start cancellation path set cancelled=True. Such a job is now reported as cancelled. Also rename workflowJobResults to workflow_job_results and fix the heading underline length in the workflow documentation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
_CaptureProxy overrode six members that io.IOBase already provides identically. encoding, errors and newlines are kept because TextIOBase defines them as descriptors returning None, so __getattr__ never sees them, and writable is kept because IOBase defaults it to False. The starting and result log lines both began with "Workflow job" but meant different things. They now share one description and always state the hook, using hook=None for runs outside a hook. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The stream proxy and its context manager are self-contained and have nothing to do with ErtScript beyond the single call that uses them, so they crowded out the module they lived in. The new module opens by stating why contextlib.redirect_stdout is not used, since that is the first thing a reader is likely to wonder. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The log line format is a concern of the runner, not of the result it records: WorkflowJobResult is also persisted, and the starting line has to be written before any result exists. Move the formatting onto WorkflowRunner so both lines are built in one place and the dataclass stays pure data. Also drop articles from the test names added here and describe LOAD_WORKFLOW's second argument as a name, matching the documentation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
5682c06 to
33034fb
Compare


Issue
Part of #13320
Closes #14308
Approach
First of two PRs splitting the original "Store workflow output" work. This one
covers capturing workflow job output and writing it to the ERT log; the
follow-up (#14062) adds the
WorkflowEventand persists events to experiment storage.Workflow job output previously only reached the terminal ERT was started from,
so it was lost once that terminal was gone, and a job run outside a terminal
left no record at all.
sys.stdout/sys.stderrwith a thread-aware_CaptureProxywhile ajob runs, recording what the calling thread writes while still forwarding it
to the real stream. Concurrently running jobs do not pick up each other's
output.
WorkflowJobResult, recording name, index, arguments, output, status andtimestamp per invocation.
workflowReport()is keyed by job name, so aworkflow running the same job twice previously kept only the last invocation's
output.
LOAD_WORKFLOWalias, so reporting can use thename users recognise rather than the source file path.
Covers hooked workflows,
ert workflowand the GUI Run workflow tool, sinceall three go through
WorkflowRunner.Also fixes two latent bugs found along the way: the running flag was not cleared
when a job was rejected for bad arguments, and a job that stopped the workflow
had its output dropped before it could be recorded.
git rebase -i main --exec 'just rapid-tests')When applicable
merge screenshot-PR in ert-testdata before merging this PR.