github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/dashboard/app/templates.html (about)

     1  {{/*
     2  Copyright 2017 syzkaller project authors. All rights reserved.
     3  Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
     4  */}}
     5  
     6  {{/* Info icon with a link, invoked with an URL string */}}
     7  {{define "info_link"}}
     8  <a href="{{.}}" title="help" target="_blank" class="info_link">🛈</a>
     9  {{end}}
    10  
    11  {{/* Common page head part, invoked with *uiHeader */}}
    12  {{define "head"}}
    13  	<link rel="stylesheet" href="/static/style.css"/>
    14  	<script src="/static/common.js"></script>
    15  	{{if .AnalyticsTrackingID}}
    16  		<script async src="https://www.googletagmanager.com/gtag/js?id={{.AnalyticsTrackingID}}"></script>
    17  		<script>
    18  			window.dataLayer = window.dataLayer || [];
    19  			function gtag() { dataLayer.push(arguments); }
    20  			gtag('js', new Date());
    21  			gtag('config', '{{.AnalyticsTrackingID}}');
    22  		</script>
    23  	{{end}}
    24  {{end}}
    25  
    26  {{/* Common page header, invoked with *uiHeader */}}
    27  {{define "header"}}
    28  	<header id="topbar">
    29  		<table class="position_table">
    30  			<tr>
    31  				<td>
    32  					<h1><a href="/{{$.Namespace}}">syzbot</a></h1>
    33  				</td>
    34  				<td class="namespace_td">
    35  					<select class="namespace" onchange="window.location.href = '/' + this.value + '{{.Subpage}}';">
    36  						{{if .Admin}}
    37  							<option value="admin" {{if eq $.Namespace "admin"}}selected="1"{{end}}>Admin</option>
    38  						{{end}}
    39  						{{- range $ns := .Namespaces}}
    40  							<option value="{{$ns.Name}}" {{if eq $.Namespace $ns.Name}}selected="1"{{end}}>
    41  								{{- $ns.Caption -}}
    42  							</option>
    43  						{{- end -}}
    44  					</select>
    45  				</td>
    46  				<td class="search">
    47  					{{if .Admin}}
    48  						<a href="/admin">admin</a> |
    49  					{{end}}
    50  					{{if .LoginLink}}
    51  						<a href="{{.LoginLink}}">sign-in</a> |
    52  					{{end}}
    53  					<a href="https://groups.google.com/forum/#!forum/syzkaller" target="_blank">mailing list</a> |
    54  					<a href="https://github.com/google/syzkaller" target="_blank">source</a> |
    55  					<a href="https://github.com/google/syzkaller/blob/master/docs/syzbot.md" target="_blank">docs</a>
    56  				</td>
    57  			</tr>
    58  		</table>
    59  		{{if not (eq .URLPath "/admin")}}
    60  		<table class="position_table">
    61  			<tr>
    62  				<td class="navigation">
    63  					<a class="navigation_tab{{if eq .URLPath (printf "/%v" $.Namespace)}}_selected{{end}}" href='/{{$.Namespace}}'>
    64  						<span style="color:DeepPink;">🐞</span> Open [{{$.BugCounts.Open}}]</a>
    65  					{{if .ShowSubsystems}}
    66  					<a class="navigation_tab{{if eq .URLPath (printf "/%v/subsystems" $.Namespace)}}_selected{{end}}" href='/{{$.Namespace}}/subsystems'>
    67  						<span style="color:DeepPink;">≡</span> Subsystems</a>
    68  					{{end}}
    69                                          <a class="navigation_tab{{if eq .URLPath (printf "/%v/fixed" $.Namespace)}}_selected{{end}}" href='/{{$.Namespace}}/fixed'>
    70  						<span style="color:ForestGreen;">🐞</span> Fixed [{{$.BugCounts.Fixed}}]</a>
    71  					<a class="navigation_tab{{if eq .URLPath (printf "/%v/invalid" $.Namespace)}}_selected{{end}}" href='/{{$.Namespace}}/invalid'>
    72  						<span style="color:RoyalBlue;">🐞</span> Invalid [{{$.BugCounts.Invalid}}]</a>
    73  					{{if gt .MissingBackports 0}}
    74                                          <a class="navigation_tab{{if eq .URLPath (printf "/%v/backports" $.Namespace)}}_selected{{end}}" href='/{{$.Namespace}}/backports'>
    75  						<span style="color:ForestGreen;">⬇</span> Missing Backports [{{$.MissingBackports}}]</a>
    76  					{{end}}
    77  					<a class="navigation_tab{{if eq .URLPath (printf "/%v/graph/bugs" $.Namespace)}}_selected{{end}}" href='/{{$.Namespace}}/graph/bugs'>
    78  						<span style="color:DarkOrange;">📈</span> Kernel Health</a>
    79  					<a class="navigation_tab{{if eq .URLPath (printf "/%v/graph/lifetimes" $.Namespace)}}_selected{{end}}" href='/{{$.Namespace}}/graph/lifetimes'>
    80  						<span style="color:DarkOrange;">📈</span> Bug Lifetimes</a>
    81  					<a class="navigation_tab{{if eq .URLPath (printf "/%v/graph/fuzzing" $.Namespace)}}_selected{{end}}" href='/{{$.Namespace}}/graph/fuzzing'>
    82  					  <span style="color:DarkOrange;">📈</span> Fuzzing</a>
    83  					<a class="navigation_tab{{if eq .URLPath (printf "/%v/graph/crashes" $.Namespace)}}_selected{{end}}" href='/{{$.Namespace}}/graph/crashes'>
    84  						<span style="color:DarkOrange;">📈</span> Crashes</a> 
    85  				</td>
    86                                  {{if .ContactEmail}}
    87  				<td class="navigation-right">
    88  					<a class="navigation_tab" href='mailto:{{.ContactEmail}}'>
    89  						<span style="color:ForestGreen;">💬</span> Send us feedback</a>
    90  				</td>
    91                                  {{end}}
    92  			</tr>
    93  		</table>
    94  		{{end}}
    95  	</header>
    96  	<br>
    97  {{end}}
    98  
    99  {{/* List of enabled filters, invoked with *uiBugFilter */}}
   100  {{define "bug_filter"}}
   101  {{if .Filter.Any}}
   102  	<b>Applied filters: </b>
   103  	{{if .Filter.Manager}}
   104  		Manager={{.Filter.Manager}} ({{link (call .DropURL "manager" "") "drop"}})
   105  	{{end}}
   106  	{{if .Filter.OnlyManager}}
   107  		Only Manager={{.Filter.OnlyManager}} ({{link (call .DropURL "only_manager" "") "drop"}})
   108  	{{end}}
   109  	{{if .Filter.NoSubsystem}}
   110  		NoSubsystem={{.Filter.NoSubsystem}} ({{link (call .DropURL "no_subsystem" "") "drop"}})
   111  	{{end}}
   112  	{{$drop := .DropURL}}
   113  	{{range .Filter.Labels}}
   114  		Label={{.}} ({{link (call $drop "label" .) "drop"}})
   115  	{{end}}
   116  	<br>
   117  {{end}}
   118  {{end}}
   119  
   120  {{/* List of bugs, invoked with *uiBugGroup */}}
   121  {{define "bug_list"}}
   122  {{if .}}
   123  {{if .Bugs}}
   124  <table class="list_table">
   125  	{{if $.Caption}}
   126  		{{if $.Fragment}}
   127  			<caption id="{{$.Fragment}}"><a class="plain" href="#{{$.Fragment}}">
   128  		{{else}}
   129  			<caption>
   130  		{{end}}
   131  		{{$.Caption}} ({{len $.Bugs}}):
   132  		{{if $.Fragment}}</a>{{end}}
   133  		</caption>
   134  	{{end}}
   135  	<thead>
   136  	<tr>
   137  		{{if $.ShowNamespace}}
   138  			<th><a onclick="return sortTable(this, 'Kernel', textSort)" href="#">Kernel</a></th>
   139  		{{end}}
   140  		<th><a onclick="return sortTable(this, 'Title', textSort)" href="#">Title</a></th>
   141  		<th><a onclick="return sortTable(this, 'Repro', reproSort)" href="#">Repro</a></th>
   142  		<th><a onclick="return sortTable(this, 'Cause bisect', textSort)" href="#">Cause bisect</a></th>
   143  		<th><a onclick="return sortTable(this, 'Fix bisect', textSort)" href="#">Fix bisect</a></th>
   144  		<th><a onclick="return sortTable(this, 'Count', numSort)" href="#">Count</a></th>
   145  		<th><a onclick="return sortTable(this, 'Last', timeSort)" href="#">Last</a></th>
   146  		<th><a onclick="return sortTable(this, 'Reported', timeSort)" href="#">Reported</a></th>
   147  		{{if $.DispLastAct}}
   148  		<th><a onclick="return sortTable(this, 'Last activity', timeSort, desc=true)" href="#">Last activity</a></th>
   149  		{{end}}
   150  		{{if $.DispDiscuss}}
   151  		<th><a onclick="return sortTable(this, 'Discussions', timeSort, desc=true)" href="#">Discussions</a></th>
   152  		{{end}}
   153  		{{if $.ShowPatched}}
   154  			<th><a onclick="return sortTable(this, 'Patched', patchedSort)" href="#">Patched</a></th>
   155  		{{end}}
   156  		{{if $.ShowStatus}}
   157  			<th><a onclick="return sortTable(this, 'Status', textSort)" href="#">Status</a></th>
   158  		{{end}}
   159  		{{if $.ShowPatch}}
   160  			<th><a onclick="return sortTable(this, 'Closed', timeSort)" href="#">Closed</a></th>
   161  			<th><a onclick="return sortTable(this, 'Patch', textSort)" href="#">Patch</a></th>
   162  		{{end}}
   163  	</tr>
   164  	</thead>
   165  	<tbody>
   166  	{{range $b := .Bugs}}
   167  		<tr>
   168  			{{if $.ShowNamespace}}<td>{{$b.Namespace}}</td>{{end}}
   169  			<td class="title">
   170  				<a href="{{$b.Link}}">{{$b.Title}}</a>
   171  				{{- range $b.Labels}}
   172  					<span class="bug-label">{{link .Link .Name}}</span>
   173  				{{- end}}
   174  			</td>
   175  			<td class="stat">{{formatReproLevel $b.ReproLevel}}</td>
   176  			<td class="bisect_status">{{print $b.BisectCause}}</td>
   177  			<td class="bisect_status">{{print $b.BisectFix}}</td>
   178  			<td class="stat {{if $b.NumCrashesBad}}bad{{end}}">{{$b.NumCrashes}}</td>
   179  			<td class="stat">{{formatLateness $.Now $b.LastTime}}</td>
   180  			<td class="stat">
   181  				{{if $b.ExternalLink}}
   182  					<a href="{{$b.ExternalLink}}">{{formatLateness $.Now $b.ReportedTime}}</a>
   183  				{{else}}
   184  					{{formatLateness $.Now $b.ReportedTime}}
   185  				{{end}}
   186  			</td>
   187  			{{if $.DispLastAct}}
   188  				<td class="stat">{{formatLateness $.Now $b.LastActivity}}</td>
   189  			{{end}}
   190  			{{if $.DispDiscuss}}
   191  			{{$d := $b.Discussions}}
   192  			<td class="discussions" sort-value="{{formatLateness $.Now $d.LastMessage}}">
   193  			{{- if not $d.LastPatchMessage.IsZero -}}
   194  				<b>PATCH</b> [{{formatLateness $.Now $d.LastPatchMessage}}]
   195  			{{- else if $d.ExternalMessages -}}
   196  				<span class="icon">&#128172;</span> {{$d.ExternalMessages}} [{{formatLateness $.Now $d.LastMessage}}]
   197  			{{- end -}}
   198  			</td>
   199  			{{end}}
   200  			{{if $.ShowPatched}}
   201  				<td class="patched" {{if $b.Commits}}title="{{with $com := index $b.Commits 0}}{{$com.Title}}{{end}}"{{end}}>{{len $b.PatchedOn}}/{{$b.NumManagers}}</td>
   202  			{{end}}
   203  			{{if $.ShowStatus}}
   204  				<td class="status">
   205  					{{if $b.ExternalLink}}
   206  						<a href="{{$b.ExternalLink}}">{{$b.Status}}</a>
   207  					{{else}}
   208  						{{$b.Status}}
   209  					{{end}}
   210  				</td>
   211  			{{end}}
   212  			{{if $.ShowPatch}}
   213  				<td class="stat">{{formatLateness $.Now $b.ClosedTime}}</td>
   214  				<td class="commit_list">{{template "fix_commits" $b.Commits}}</td>
   215  			{{end}}
   216  		</tr>
   217  	{{end}}
   218  	</tbody>
   219  </table>
   220  {{end}}
   221  {{end}}
   222  {{end}}
   223  
   224  {{/* List of managers, invoked with []*uiManager */}}
   225  {{define "manager_list"}}
   226  {{if .}}
   227  <table class="list_table">
   228  	<caption id="managers">Instances [{{link .RepoLink "tested repos"}}]:</caption>
   229  	<thead>
   230  	<tr>
   231  		<th>Name</th>
   232  		<th>Last active</th>
   233  		<th>Uptime</th>
   234  		<th>Corpus</th>
   235  		<th>Coverage {{template "info_link" "https://github.com/google/syzkaller/blob/master/docs/coverage.md"}}</th>
   236  		<th>Crashes</th>
   237  		<th>Execs</th>
   238  		<th colspan="4">Kernel build</th>
   239  		<th colspan="3">syzkaller build</th>
   240  	</tr>
   241  	<tr>
   242  		<th></th>
   243  		<th></th>
   244  		<th></th>
   245  		<th></th>
   246  		<th></th>
   247  		<th></th>
   248  		<th></th>
   249  		<th>Commit</th>
   250  		<th>Config</th>
   251  		<th>Freshness</th>
   252  		<th>Status</th>
   253  		<th>Commit</th>
   254  		<th>Freshness</th>
   255  		<th>Status</th>
   256  	</tr>
   257  	</thead>
   258  	<tbody>
   259  	{{range $mgr := .List}}
   260  		<tr>
   261  			<td>{{link $mgr.PageLink $mgr.Name}}</td>
   262  			<td class="stat {{if not $mgr.CurrentUpTime}}bad{{end}}">{{formatLateness $mgr.Now $mgr.LastActive}}</td>
   263  			<td class="stat">{{formatDuration $mgr.CurrentUpTime}}</td>
   264  			<td class="stat">{{formatStat $mgr.MaxCorpus}}</td>
   265  			<td class="stat">
   266  				{{if $mgr.CoverLink}}
   267  					<a href="{{$mgr.CoverLink}}" target="_blank">
   268  				{{end}}
   269  				{{formatStat $mgr.MaxCover}}
   270  				{{if $mgr.CoverLink}}
   271  					</a>
   272  				{{end}}
   273  			</td>
   274  			<td class="stat">{{formatStat $mgr.TotalCrashes}}</td>
   275  			{{if $mgr.TotalExecsBad}}
   276  				<td class="stat bad">broken</td>
   277  			{{else}}
   278  				<td class="stat">{{formatStat $mgr.TotalExecs}}</td>
   279  			{{end}}
   280  			{{with $build := $mgr.CurrentBuild}}
   281  				<td class="stat" title="[{{$build.KernelAlias}}] {{$build.KernelCommitTitle}}">{{link $build.KernelCommitLink (formatTagHash $build.KernelCommit)}}</td>
   282  				<td class="stat">{{link $build.KernelConfigLink ".config"}}</td>
   283  				<td class="stat" title="{{formatTime $build.KernelCommitDate}}" {{if $mgr.FailedBuildBugLink}}class="bad"{{end}}>{{formatLateness $mgr.Now $build.KernelCommitDate}}</td>
   284  				<td class="stat">{{if $mgr.FailedBuildBugLink}}<a href="{{$mgr.FailedBuildBugLink}}" class="bad">failing</a>{{end}}</td>
   285  				<td class="stat">{{link $build.SyzkallerCommitLink (formatShortHash $build.SyzkallerCommit)}}</td>
   286  				<td class="stat" title="{{formatTime $build.SyzkallerCommitDate}}" {{if $mgr.FailedSyzBuildBugLink}}class="bad"{{end}}>{{formatLateness $mgr.Now $build.SyzkallerCommitDate}}</td>
   287  				<td class="stat">{{if $mgr.FailedSyzBuildBugLink}}<a href="{{$mgr.FailedSyzBuildBugLink}}" class="bad">failing</a>{{end}}</td>
   288  			{{else}}
   289  				<td></td>
   290  				<td></td>
   291  				<td></td>
   292  				<td></td>
   293  				<td></td>
   294  				<td></td>
   295  				<td></td>
   296  			{{end}}
   297  		</tr>
   298  	{{end}}
   299  	</tbody>
   300  </table>
   301  {{end}}
   302  {{end}}
   303  
   304  {{/* List of fixing commits, invoked with []*uiCommit */}}
   305  {{define "fix_commits"}}
   306  {{range $com := .}}
   307  	<span class="mono">
   308  		{{if $com.Hash}}
   309  			{{formatTagHash $com.Hash}}
   310  		{{end}}
   311  		{{link $com.Link $com.Title}}
   312  	</span>
   313  {{end}}
   314  {{end}}
   315  
   316  {{/* Bisection result, invoked with *uiJob */}}
   317  {{/* Show bisection results */}}
   318  {{define "bisect_results"}}
   319  {{if .}}
   320  	{{$causeJob := 1}}
   321  	{{$fixJob := 2}}
   322  	{{if .ErrorLink}}
   323  		{{if eq .Type $causeJob}}
   324  			<b>Cause bisection: failed</b>
   325  		{{else if eq .Type $fixJob}}
   326  			{{if .FixCandidate}}
   327  				<b>Fix candidate bisection: failed</b>
   328  			{{else}}
   329  			        <b>Fix bisection: failed</b>
   330  			{{end}}
   331  		{{end}}
   332  		<b>({{link .ErrorLink "error log"}}{{if .LogLink}}, {{link .LogLink "bisect log"}}{{end}})</b><br>
   333  	{{else if .Commit}}
   334  		{{if eq .Type $causeJob}}
   335  			<b>Cause bisection: introduced by</b>
   336  		{{else if eq .Type $fixJob}}
   337  			{{if .FixCandidate}}
   338  				<b>Fix commit to backport</b>
   339  			{{else}}
   340  			        <b>Fix bisection: fixed by</b>
   341  			{{end}}
   342  		{{end}}
   343  		<b>({{link .LogLink "bisect log"}})</b> <span class="bad">{{print .Flags}}</span>:<br>
   344  		<span class="mono">
   345  		{{if .FixCandidate}}tree: {{link .KernelLink .KernelAlias}}<br>{{end}}
   346  		commit {{.Commit.Hash}}<br>
   347  		Author: {{.Commit.Author}}<br>
   348  		Date:   {{formatKernelTime .Commit.Date}}<br>
   349  		<br>
   350  		&nbsp;&nbsp;{{link .Commit.Link .Commit.Title}}<br>
   351  		</span><br>
   352  	{{else if .Commits}}
   353  		{{if eq .Type $causeJob}}
   354  			<b>Cause bisection: the cause commit could be any of</b>
   355  		{{else if eq .Type $fixJob}}
   356  			<b>{{if .FixCandidate}}Fix candidate detection{{else}}Fix bisection{{end}}
   357  			the fix commit could be any of</b>
   358  			{{end}}
   359  		<b>({{link .LogLink "bisect log"}}):</b><br>
   360  		<span class="mono">
   361  		{{range $com := .Commits}}
   362  			&nbsp;&nbsp;{{formatTagHash $com.Hash}} {{link $com.Link $com.Title}}<br>
   363  		{{end}}
   364  		</span>
   365  	{{else}}
   366  		{{if eq .Type $causeJob}}
   367  			<b>Cause bisection: the issue happens on the oldest tested release</b>
   368  		{{else if eq .Type $fixJob}}
   369  			<b>{{if .FixCandidate}}Fix candidate detection:{{else}}Fix bisection:{{end}}
   370  			the issue occurs on the latest tested release</b>
   371  		{{end}}
   372  		<b>({{link .LogLink "bisect log"}})</b><br>
   373  	{{end}}
   374  	{{if .CrashLogLink}}
   375  		Crash: {{link .CrashReportLink .CrashTitle}} ({{link .CrashLogLink "log"}})<br>
   376  		Repro: {{optlink .Crash.ReproCLink "C"}}
   377  		{{optlink .Crash.ReproSyzLink "syz"}}
   378  		{{optlink .Crash.KernelConfigLink ".config"}}<br>
   379  	{{end}}
   380  
   381  	{{if not .Reported}}[report pending]<br>{{end}}
   382  	{{optlink .RestartJobLink "🔄 retry this bisection"}}&nbsp;&nbsp;
   383  	{{optlink .InvalidateJobLink "❌ mark as invalid"}}
   384  {{end}}
   385  {{end}}
   386  
   387  {{/* List of fixing commits, invoked with *uiCrashTable */}}
   388  {{/* Show crashes */}}
   389  {{define "crash_list"}}
   390  {{if .}}
   391  <table class="list_table">
   392  	{{if .Caption}}<caption>{{.Caption}}:</caption>{{end}}
   393  		<thead>
   394  		<tr>
   395  			<th><a onclick="return sortTable(this, 'Time', textSort, true)" href="#">Time</a></th>
   396  			<th><a onclick="return sortTable(this, 'Kernel', textSort)" href="#">Kernel</a></th>
   397  			<th><a onclick="return sortTable(this, 'Commit', textSort)" href="#">Commit</a></th>
   398  			<th><a onclick="return sortTable(this, 'Syzkaller', textSort)" href="#">Syzkaller</a></th>
   399  			<th><a onclick="return sortTable(this, 'Config', textSort)" href="#">Config</a></th>
   400  			<th><a onclick="return sortTable(this, 'Log', textSort)" href="#">Log</a></th>
   401  			<th><a onclick="return sortTable(this, 'Report', reproSort)" href="#">Report</a></th>
   402  			<th><a onclick="return sortTable(this, 'Syz repro', reproSort)" href="#">Syz repro</a></th>
   403  			<th><a onclick="return sortTable(this, 'C repro', textSort)" href="#">C repro</a></th>
   404  			<th><a onclick="return sortTable(this, 'VM info', textSort)" href="#">VM info</a></th>
   405  			<th><a onclick="return sortTable(this, 'Assets', textSort)" href="#">Assets</a> (<a href="https://github.com/google/syzkaller/blob/master/docs/syzbot_assets.md">help?</a>)</th>
   406  			<th><a onclick="return sortTable(this, 'Manager', textSort)" href="#">Manager</a></th>
   407  			<th><a onclick="return sortTable(this, 'Title', textSort)" href="#">Title</a></th>
   408  		</tr>
   409  		</thead>
   410  		<tbody>
   411  		{{range $b := .Crashes}}
   412  		<tr>
   413  			<td class="time">{{formatTime $b.Time}}</td>
   414  			<td class="kernel" title="{{$b.KernelAlias}}">{{$b.KernelAlias}}</td>
   415  			<td class="tag" title="{{$b.KernelCommit}}
   416  	{{formatTime $b.KernelCommitDate}}">{{link $b.KernelCommitLink (formatTagHash $b.KernelCommit)}}</td>
   417  			<td class="tag">{{link $b.SyzkallerCommitLink (formatShortHash $b.SyzkallerCommit)}}</td>
   418  			<td class="config">{{if $b.KernelConfigLink}}<a href="{{$b.KernelConfigLink}}">.config</a>{{end}}</td>
   419  			<td class="repro">{{if $b.LogLink}}<a href="{{$b.LogLink}}">{{if $b.LogHasStrace}}strace{{else}}console{{end}} log</a>{{end}}</td>
   420  			<td class="repro">{{if $b.ReportLink}}<a href="{{$b.ReportLink}}">report</a>{{end}}</td>
   421  			<td class="repro{{if $b.ReproIsRevoked}} stale_repro{{end}}">{{if $b.ReproSyzLink}}<a href="{{$b.ReproSyzLink}}">syz</a>{{end}}</td>
   422  			<td class="repro{{if $b.ReproIsRevoked}} stale_repro{{end}}">{{if $b.ReproCLink}}<a href="{{$b.ReproCLink}}">C</a>{{end}}</td>
   423  			<td class="repro">{{if $b.MachineInfoLink}}<a href="{{$b.MachineInfoLink}}">info</a>{{end}}</td>
   424  			<td class="assets">{{range $i, $asset := .Assets}}
   425  				<span class="no-break">[<a href="{{$asset.DownloadURL}}">{{$asset.Title}}</a>]</span>
   426  			{{end}}</td>
   427  			<td class="manager">{{$b.Manager}}</td>
   428  			<td class="manager">{{$b.Title}}</td>
   429  		</tr>
   430  		{{end}}
   431  		</tbody>
   432  </table>
   433  <i>* <s>Struck through</s> repros no longer work on HEAD.</i>
   434  {{end}}
   435  {{end}}
   436  
   437  
   438  
   439  {{/* List of jobs, invoked with *uiJobList */}}
   440  {{define "job_list"}}
   441  {{if and $ $.Jobs}}
   442  	<table class="list_table">
   443  		<caption id="jobs"><a class="plain" href="#jobs">{{$.Title}}</a></caption>
   444  		<thead>
   445  		<tr>
   446  			{{if not $.PerBug}}<th>Bug</th>{{end}}
   447  			<th>Created</th>
   448  			<th>Duration</th>
   449  			<th>User</th>
   450  			<th>Patch</th>
   451  			<th>Repo</th>
   452  			{{if not $.PerBug}}<th>Manager</th>{{end}}
   453  			<th>Result</th>
   454  		</tr>
   455  		</thead>
   456  		<tbody>
   457  		{{range $job := $.Jobs}}
   458  			<tr>
   459  				{{if not $.PerBug}}<td class="title"><a href="{{$job.BugLink}}">{{$job.BugTitle}}</a></td>{{end}}
   460  				<td class="time">{{link $job.ExternalLink (formatTime $job.Created)}}</td>
   461  				<td class="time" title="started: {{formatTime $job.Started}}&#013;finished: {{formatTime $job.Finished}}">
   462  					{{formatDuration $job.Duration}}{{if gt $job.Attempts 1}} ({{$job.Attempts}}){{end}}
   463  				</td>
   464  				<td>
   465  					{{if eq $job.Type 0}}
   466  						{{if $job.User}}{{$job.User}}
   467  						{{- else if $job.TreeOrigin}}tree origin
   468  						{{- else}}retest repro{{end}}
   469  					{{else if eq $job.Type 1}}
   470  						bisect
   471  					{{else if eq $job.Type 2}}
   472  						{{if $job.FixCandidate}}fix candidate{{else}}bisect fix{{end}}
   473  					{{end}}
   474  				</td>
   475  				<td>{{optlink $job.PatchLink "patch"}}</td>
   476  				<td class="kernel" title="{{$job.KernelAlias}}">{{link $job.KernelCommitLink $job.KernelAlias}}</td>
   477  				{{if not $.PerBug}}<td title="{{$job.Namespace}}/{{$job.Reporting}}">{{$job.Manager}}</td>{{end}}
   478  				<td class="result">
   479  					{{if $job.ErrorLink}}
   480  						{{link $job.ErrorLink "error"}}
   481  					{{end}}
   482  					{{if $job.LogLink}}
   483  						{{link $job.LogLink "job log"}}
   484  						({{if $job.Commit}}1{{else}}{{len $job.Commits}}{{end}})
   485  					{{else if $job.CrashTitle}}
   486  						{{optlink $job.CrashReportLink "report"}}
   487  					{{else if formatTime $job.Finished}}
   488  						OK
   489  					{{else if formatTime $job.Started}}
   490  						running
   491  					{{else}}
   492  						pending
   493  					{{end}}
   494  					{{if $job.CrashLogLink}}
   495  						{{optlink $job.CrashLogLink "log"}}
   496  					{{end}}
   497  					{{ if $job.InvalidatedBy }}
   498  						</br>marked invalid by {{$job.InvalidatedBy}}
   499  					{{end}}
   500  					{{if and $.PerBug (or .InvalidateJobLink .RestartJobLink)}}<br/>{{optlink .RestartJobLink "🔄 retry this bisection"}}&nbsp;&nbsp;{{optlink .InvalidateJobLink "❌ mark as invalid"}}{{end}}
   501  				</td>
   502  			</tr>
   503  		{{end}}
   504  		</tbody>
   505  	</table>
   506  {{end}}
   507  {{end}}
   508  
   509  {{/* Checkbox input, invoked with *uiCheckbox */}}
   510  {{define "input-checkbox"}}
   511  	<div class="panel">
   512  		<h1>{{$.Caption}}</h1>
   513  		{{range .Values}}
   514  			<input type="checkbox" name="{{$.ID}}" {{if .Selected}}checked{{end}} value="{{.ID}}">{{if .Caption}}{{.Caption}}{{else}}{{.ID}}{{end}}</input><br>
   515  		{{end}}
   516  	</div>
   517  {{end}}
   518  
   519  {{/* Range slider input, invoked with *uiSlider */}}
   520  {{define "input-slider"}}
   521  	<div class="panel">
   522  		<label for="{{.ID}}">{{.Caption}}:</label>
   523  		<input type="range" name="{{.ID}}" min="{{.Min}}" max="{{.Max}}" value="{{.Val}}" oninput="document.getElementById('{{.ID}}-val').innerHTML = this.value">
   524  		<i id="{{.ID}}-val">{{.Val}}</i>
   525  	</div>
   526  {{end}}
   527  
   528  {{/* Multiple text fields */}}
   529  {{define "input-multi-text"}}
   530  	<div class="panel">
   531  		<h1>{{.Caption}}:</h1>
   532  		<div class="input-values">
   533  			{{$input := .}}
   534  			{{range .Vals}}
   535  			<span class="input-group">
   536  				<input type="text" name="{{$input.ID}}" value="{{.}}" /> <button onclick="deleteInputGroup(this)" type="button">x</button>
   537  			</span>
   538  			{{else}}
   539  			<span class="input-group">
   540  				<input type="text" name="{{$input.ID}}" value="" /> <button onclick="deleteInputGroup(this)" type="button">x</button>
   541  			</span>
   542  			{{end}}
   543  			<button onclick="addInputGroup(this)">Add one more</button>
   544  		</div>
   545  	</div>
   546  {{end}}
   547  
   548  {{/* List of discussions, invoked with []*uiBugDiscussion */}}
   549  {{define "discussion_list"}}
   550  {{if .}}
   551  <table class="list_table">
   552  	<thead>
   553  	<tr>
   554  		<th>Title</th>
   555  		<th>Replies (including bot)</th>
   556  		<th>Last reply</th>
   557  	</tr>
   558  	</thead>
   559  	<tbody>
   560  	{{range $item := .}}
   561  		<tr>
   562  			<td>{{link $item.Link $item.Subject}}</td>
   563  			<td class="stat">{{$item.External}} ({{$item.Total}})</td>
   564  			<td class="stat">{{formatTime $item.Last}}</td>
   565  		</tr>
   566  	{{end}}
   567  	</tbody>
   568  </table>
   569  {{end}}
   570  {{end}}
   571  
   572  {{/* List of test results, invoked with []*dashapi.JobInfo */}}
   573  {{define "test_results"}}
   574  {{if .}}
   575  <table class="list_table">
   576  	<thead>
   577  	<tr>
   578  		<th>Date</th>
   579  		<th>Name</th>
   580  		<th>Commit</th>
   581  		<th>Repro</th>
   582  		<th>Result</th>
   583  	</tr>
   584  	</thead>
   585  	<tbody>
   586  	{{range $item := .}}
   587  		<tr>
   588  			<td>{{formatDate $item.Finished}}</td>
   589  			<td>{{$item.KernelAlias}} {{if $item.OnMergeBase}}(merge base){{else}}(ToT){{end}}</td>
   590  			<td class="stat">{{link $item.KernelCommitLink (formatTagHash $item.KernelCommit)}}</td>
   591  			<td>
   592  				{{if $item.ReproCLink}}<a href="{{$item.ReproCLink}}">C</a>
   593  				{{else if $item.ReproSyzLink}}<a href="{{$item.ReproSyzLink}}">C</a>{{end}}
   594  			</td>
   595  			{{if ne $item.CrashTitle ""}}
   596  			<td class="status-crashed">
   597  				{{link $item.CrashReportLink "[report]"}} <i>{{$item.CrashTitle}}</i>
   598  			</td>
   599  			{{else if ne $item.ErrorLink ""}}
   600  			<td class="status-error">
   601  				Failed due to {{link $item.ErrorLink "an error"}}; will retry later
   602  			</td>
   603  			{{else}}
   604  			<td class="status-ok">Didn't crash</td>
   605                          {{end}}
   606  		</tr>
   607  	{{end}}
   608  	</tbody>
   609  </table>
   610  {{end}}
   611  {{end}}
   612  
   613  {{/* List of failed repro attempts, invoked with []*uiReproAttempt */}}
   614  {{define "repro_attempts"}}
   615  {{if .}}
   616  <table class="list_table">
   617  	<thead>
   618  	<tr>
   619  		<th>Time</th>
   620  		<th>Manager</th>
   621  		<th>Log</th>
   622  	</tr>
   623  	</thead>
   624  	<tbody>
   625  	{{range $item := .}}
   626  		<tr>
   627  			<td>{{formatTime $item.Time}}</td>
   628  			<td class="stat">{{$item.Manager}}</td>
   629  			<td class="stat">{{link $item.LogLink "repro log"}}</td>
   630  		</tr>
   631  	{{end}}
   632  	</tbody>
   633  </table>
   634  {{end}}
   635  {{end}}