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