@@ -272,6 +272,27 @@ def job_unit(name):
272272 return target , (m .group (1 ) or m .group (2 )) if m else "unknown"
273273
274274
275+ HOST_JOB_RE = re .compile (r"^host / (?:Run|Build) / (.+) \((.+)\)$" )
276+
277+
278+ def job_urls (run_id ):
279+ """(unit, ref) -> the URL of the job that ran it.
280+
281+ Linking the run only makes a reader hunt through 250 jobs for the red one.
282+ """
283+ out = {}
284+ for j in all_jobs (run_id ):
285+ name , url = j .get ("name" , "" ), j .get ("html_url" )
286+ m = HOST_JOB_RE .match (name )
287+ if m :
288+ out [(m .group (1 ), m .group (2 ))] = url
289+ continue
290+ t , ref = job_unit (name )
291+ if t :
292+ out [(t , ref )] = url
293+ return out
294+
295+
275296def classify_jobs (run_id , attempt , retry_note ):
276297 def by_unit (jobs ):
277298 out = defaultdict (list )
@@ -814,6 +835,7 @@ def report(attempt, retry_note):
814835 issues = {store .parse_fp (i .get ("body" , "" )): i for i in open_issues ()}
815836 issues .pop (None , None )
816837
838+ urls = job_urls (RUN_ID )
817839 total = len (all_jobs (RUN_ID ))
818840 prev = previous_job_count ()
819841 close_allowed = not (prev and total < 0.5 * prev )
@@ -870,10 +892,26 @@ def report(attempt, retry_note):
870892 "failing" : fail_refs .get (eid , []) if observation != store .PASS else [],
871893 "log" : logs .get (eid , "" )[- LOG_TAIL_CHARS :],
872894 }
895+ # The real failing target + its error + a link to the job that ran it.
896+ # This used to be a hardcoded "-" profile column and a bare ":x: fail",
897+ # which told a reader nothing they could act on.
873898 rows = [
874- {"profile" : "-" , "ref" : ref , "status" : ":x: fail" }
875- for ref in fail_refs .get (eid , [])
876- ] or [{"profile" : "-" , "ref" : "all" , "status" : ":white_check_mark: pass" }]
899+ {
900+ "test" : r .get ("target" ) or r .get ("stage" , "build" ),
901+ "ref" : r .get ("ref" , "?" ),
902+ "detail" : (r .get ("detail" ) or "" ).strip (),
903+ "url" : urls .get ((eid , r .get ("ref" ))),
904+ }
905+ for r in results
906+ if r ["id" ] == eid and r ["status" ] == "fail"
907+ ]
908+ # cross targets emit no results rows, so fall back to the job itself
909+ if not rows and observation != store .PASS :
910+ rows = [
911+ {"test" : eid , "ref" : ref , "detail" : "job failed" ,
912+ "url" : urls .get ((eid , ref ))}
913+ for ref in fail_refs .get (eid , ["unknown" ])
914+ ]
877915 # collected, not read back from `issues`: a dir filed for the first time
878916 # tonight is not in that map, and its card entry would have no link
879917 filed [eid ] = apply (eid , observation , issue , verdicts .get (eid ), state , rows ,
0 commit comments