Workflow health: Ability to view grouped triaged work orders in history page - #5151
Open
lmac-1 wants to merge 14 commits into
Open
Workflow health: Ability to view grouped triaged work orders in history page#5151lmac-1 wants to merge 14 commits into
lmac-1 wants to merge 14 commits into
Conversation
Step error type coalesces to the run's with `||`, and `"" || x` returns `""` since empty string is truthy in Elixir. A step reporting an empty error type produced its own signature instead of falling through, splitting one failure into two rows with identical labels and split counts. The run's error type can be empty the same way, and is read straight into the signature, so it splits the run-level rows too. Normalise "" to nil on both sides in to_signature/2.
Extracts the failing-step predicate, the two exit_reason/error_type coalesces, and the latest-run tiebreak from Stats into Lightning.Invocation.Query, alongside the failure-state list it already needs to share with the upcoming history filter. Stats composes them instead of inlining them; latest_runs/2 keeps its DISTINCT ON. Triage rows now merge on job_id rather than on every display field, so a job renamed (or adaptor-bumped) mid-window is one row, not two. The label is taken from the group's most recent failing snapshot, using the snapshot's lock_version as the tiebreak since the grouped rows carry no timestamp to compare by. job_id joins the signature map and the health JSON.
Adds exit_reason, error_type, and job_id to SearchParams and the LiveView filter types, and filter_by_signature/2 to scope any work order query to exactly the work orders behind one triage row. A present job_id reads as a step-level row, correlated against the latest run; an absent one reads as a run-level failure (lost, crashed, no step), matched against the inverted Run.state_reasons/0 map and failing closed on an unrecognised reason rather than dropping the filter, which would widen a bulk retry. Carries wo.state in failure_states() itself: a successful work order can hold a failing step under an on_job_failure handler that ran fine, so without this the filter would match work orders the triage row never counted.
Adds a chip to the history page's filter bar, alongside the existing work order ID chip, that renders when exit_reason is set and clears all three signature keys at once. search_workorders_query/2 is shared with bulk retry, bulk cancel and CSV export, so a signature filter with no visible indicator would be a way to silently act on the wrong group of work orders.
Each row now links to the history page filtered to exactly the work orders it counts, where the existing "retry all" can act on the group. job_id joins the signature so a job deleted and recreated with the same name doesn't collide with the row it replaced, and the adaptor renders without its version since a merged row can span more than one. A rejected row links through history's existing rejected status filter instead of the signature keys, since a rejected work order never got a run for the signature filter to match against server-side.
View is now a small filled pill with an arrow instead of a plain text link, easier to spot as an action. Work orders and View are middle- aligned in the row; only the two-line signature/tip cell stays pinned to the top. The scroll region bleeds out to the card's own edge so the scrollbar sits flush against it instead of floating in the middle of the card's padding, and the sticky header gets a z-index so a row's content can't paint above it while scrolling.
The workflow health page is still unreleased, so a Changed entry describing a fix to it is noise, not history: nobody saw the split- row bug this PR corrects. The Added entry for the page already describes the fixed behaviour on its own.
Security Review ✅
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## frank/con-106 #5151 +/- ##
===============================================
+ Coverage 90.8% 90.9% +0.1%
===============================================
Files 422 422
Lines 20846 20871 +25
===============================================
+ Hits 18928 18963 +35
+ Misses 1918 1908 -10 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Three fixture helpers replace the hand-built work order and run in every test. Drops the duplicate query in the no-op test: an absent key and a nil value cast to the same field, so both runs asked the same question.
exit_reason/2 and error_type/2 only ever ran for the health page's triage rows, so they move back into Stats as defp. The three that the history filter also calls stay in Query, two of them with a comment instead of a doc block.
The triage row nils an empty error_type before grouping, and so does the step-level branch of the signature filter. The run-level branch compared the raw column, so a crashed run with error_type "" was counted in the row but never matched by its own View button.
History derives search_fields from the query string and put_new's the result, so a link carrying none of the four keys lands with an empty list rather than the schema default, and the search box then matches nothing. Every server-built link fills these in via to_uri_params/1.
ViewButton took four props to build one URL, all of them already at the call site. It takes the href now, and the row keeps the guard: no exit reason, no link. Also drops a comment's pointer to a plan file the reader of this file cannot open.
The comment contrasted the key with "the whole map", which only means something to someone who saw the previous implementation.
from_uri/1 always set search_fields, so a link naming none of the four flags landed with an empty list and every search term then matched nothing. Each unticked box still arrives marked false, so "none present" can only mean a link that never mentioned them. Reverts the flags the triage View link carried to work around this. It was the first link built in the browser rather than through to_uri_params/1, so it was the first to hit this.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Adds a View button to each row of the workflow health page's triage table. It links to the history page filtered to exactly the work orders behind that row, where the existing "retry all" can act on the group.
Underneath the button:
job_idnow, not the resolved job name, so a rename or adaptor bump mid-window merges into one row instead of two.exit_reason,error_type,job_id), which also scope bulk retry, bulk cancel, and CSV export since they share one query.Also fixes a bug where an empty error type split one failure into two identical-looking triage rows.
Builds on #5108 (still open); this branch rebases onto it once it merges.
Closes CON-113
Validation steps
filters[rejected]=truerather than a signature.Additional notes for the reviewer
SearchParams.new/1raising on a malformed field limits how far that can reach.SearchParams.to_uri_params/1like every server-rendered link. So it has to carry history's four search-field flags itself, or the search box on the page it lands on matches nothing. Any filter key added later needs the same treatment.AI Usage
Please disclose whether you've used AI anywhere in this PR (it's cool, we just
want to know!):
You can read more details in our
Responsible AI Policy
Pre-submission checklist
/reviewwith Claude Code)
(e.g.,
:owner,:admin,:editor,:viewer)