|
1 | | -import {STATUS_DATA_URL} from "../urls"; |
2 | | - |
3 | | -import {getJson} from "../utils/requests"; |
4 | | - |
5 | | -interface Commit { |
6 | | - sha: string; |
7 | | - date: string; |
8 | | - type: "Try" | "Master"; |
9 | | -} |
10 | | - |
11 | | -interface BenchmarkStatus { |
12 | | - name: string; |
13 | | - error: string; |
14 | | -} |
15 | | - |
16 | | -interface Step { |
17 | | - step: string; |
18 | | - is_done: boolean; |
19 | | - expected_duration: number; |
20 | | - current_progress: number; |
21 | | -} |
22 | | - |
23 | | -/** |
24 | | - * The `any` types in the interface below were chosen because the types are quite complex |
25 | | - * on the Rust side (they are modeled with enums encoded in a way that is not so simple to model in |
26 | | - * TS). |
27 | | - */ |
28 | | -interface CurrentState { |
29 | | - artifact: any; |
30 | | - progress: Step[]; |
31 | | -} |
32 | | - |
33 | | -interface StatusResponse { |
34 | | - last_commit: Commit | null; |
35 | | - benchmarks: BenchmarkStatus[]; |
36 | | - missing: Array<[Commit, any]>; |
37 | | - current: CurrentState | null; |
38 | | - most_recent_end: number | null; |
39 | | -} |
40 | | - |
41 | | -function populate_data(data: StatusResponse) { |
42 | | - let state_div = document.querySelector("#benchmark-state"); |
43 | | - if (data.last_commit !== null) { |
44 | | - let element = document.createElement("p"); |
45 | | - element.innerHTML = `SHA: ${data.last_commit.sha}, date: ${data.last_commit.date}`; |
46 | | - state_div.appendChild(element); |
47 | | - } |
48 | | - for (let benchmark of data.benchmarks) { |
49 | | - let element = document.createElement("div"); |
50 | | - element.innerHTML = `<details open> |
51 | | - <summary>${benchmark.name} - error</summary> |
52 | | - <pre class="benchmark-error"></pre> |
53 | | - </details>`; |
54 | | - element.querySelector<HTMLElement>(".benchmark-error").innerText = |
55 | | - benchmark.error; |
56 | | - state_div.appendChild(element); |
57 | | - } |
58 | | - let missing_div = document.querySelector("#data-insert-js"); |
59 | | - if (data.current !== null) { |
60 | | - let table = document.createElement("table"); |
61 | | - let tr = document.createElement("tr"); |
62 | | - let th = document.createElement("th"); |
63 | | - th.innerText = "Step"; |
64 | | - tr.appendChild(th); |
65 | | - th = document.createElement("th"); |
66 | | - tr.appendChild(th); |
67 | | - th = document.createElement("th"); |
68 | | - th.innerText = "Took"; |
69 | | - tr.appendChild(th); |
70 | | - th = document.createElement("th"); |
71 | | - th.innerText = "Expected"; |
72 | | - tr.appendChild(th); |
73 | | - table.appendChild(tr); |
74 | | - |
75 | | - let left = 0; |
76 | | - for (let step of data.current.progress) { |
77 | | - let tr = document.createElement("tr"); |
78 | | - let td = document.createElement("td"); |
79 | | - td.innerText = step.step; |
80 | | - tr.appendChild(td); |
81 | | - td = document.createElement("td"); |
82 | | - let progress = document.createElement("progress"); |
83 | | - progress.setAttribute("max", step.expected_duration.toString()); |
84 | | - progress.setAttribute( |
85 | | - "value", |
86 | | - (step.is_done |
87 | | - ? step.expected_duration |
88 | | - : step.current_progress |
89 | | - ).toString() |
90 | | - ); |
91 | | - td.appendChild(progress); |
92 | | - tr.appendChild(td); |
93 | | - td = document.createElement("td"); |
94 | | - td.innerHTML = |
95 | | - step.current_progress == 0 |
96 | | - ? "" |
97 | | - : format_duration(step.current_progress); |
98 | | - td.style.textAlign = "right"; |
99 | | - tr.appendChild(td); |
100 | | - td = document.createElement("td"); |
101 | | - td.innerHTML = format_duration(step.expected_duration); |
102 | | - td.style.textAlign = "right"; |
103 | | - tr.appendChild(td); |
104 | | - if (!step.is_done) { |
105 | | - left += step.expected_duration - step.current_progress; |
106 | | - } |
107 | | - table.appendChild(tr); |
108 | | - } |
109 | | - let element = document.createElement("p"); |
110 | | - let artifact_desc = ""; |
111 | | - if (data.current.artifact.Commit) { |
112 | | - artifact_desc = commit_url(data.current.artifact.Commit); |
113 | | - } else { |
114 | | - artifact_desc = data.current.artifact.Tag; |
115 | | - } |
116 | | - element.innerHTML = `Currently benchmarking: ${artifact_desc}. |
117 | | - <br>Time left: ${format_duration(left)}`; |
118 | | - missing_div.appendChild(element); |
119 | | - missing_div.appendChild(table); |
120 | | - } else { |
121 | | - let element = document.createElement("p"); |
122 | | - if (data.most_recent_end) { |
123 | | - let end = new Date(data.most_recent_end * 1000); |
124 | | - element.innerHTML = `No current collection in progress. Last one |
125 | | - finished at ${end.toLocaleString()} local time, |
126 | | - ${format_duration( |
127 | | - Math.trunc((Date.now() - end.getTime()) / 1000) |
128 | | - )} ago.`; |
129 | | - } else { |
130 | | - element.innerHTML = "No current collection in progress."; |
131 | | - } |
132 | | - missing_div.appendChild(element); |
133 | | - } |
134 | | - { |
135 | | - let element = document.createElement("p"); |
136 | | - element.innerHTML = `Queue (${data.missing.length} total):<br> Times are local.`; |
137 | | - missing_div.appendChild(element); |
138 | | - } |
139 | | - let table = document.createElement("table"); |
140 | | - table.id = "missing-commits"; |
141 | | - { |
142 | | - let row = document.createElement("tr"); |
143 | | - row.innerHTML = `<th>Commit Date</th><th>SHA</th><th>Reason</th>`; |
144 | | - table.appendChild(row); |
145 | | - } |
146 | | - for (let [commit, reason] of data.missing) { |
147 | | - let row = document.createElement("tr"); |
148 | | - { |
149 | | - let date = new Date(commit.date); |
150 | | - let element = document.createElement("td"); |
151 | | - if (date.getUTCFullYear() == 2001) { |
152 | | - element.innerHTML = "try commit"; |
153 | | - element.style.textAlign = "center"; |
154 | | - } else { |
155 | | - element.innerHTML = new Date(commit.date).toLocaleString(); |
156 | | - } |
157 | | - row.appendChild(element); |
158 | | - } |
159 | | - { |
160 | | - let element = document.createElement("td"); |
161 | | - element.innerHTML = commit_url(commit); |
162 | | - row.appendChild(element); |
163 | | - } |
164 | | - { |
165 | | - let element = document.createElement("td"); |
166 | | - element.innerHTML = reason_to_string(reason); |
167 | | - row.appendChild(element); |
168 | | - } |
169 | | - table.appendChild(row); |
170 | | - } |
171 | | - missing_div.appendChild(table); |
172 | | -} |
173 | | - |
174 | | -function reason_to_string(reason) { |
175 | | - if (typeof reason == "string") { |
176 | | - return reason; |
177 | | - } else if (reason.InProgress) { |
178 | | - return `${reason_to_string(reason.InProgress)} - in progress`; |
179 | | - } else if (reason["Master"] != undefined && reason.Master.pr) { |
180 | | - return `<a href="https://github.com/rust-lang/rust/pull/${ |
181 | | - reason["Master"].pr |
182 | | - }"> |
183 | | - #${reason["Master"].pr}</a>${ |
184 | | - reason.Master.is_try_parent ? " - Try commit parent" : "" |
185 | | - }`; |
186 | | - } else if (reason["Master"] != undefined && reason.Master.pr == 0) { |
187 | | - return "Master"; |
188 | | - } else if (reason["Try"] != undefined && reason.Try.pr) { |
189 | | - return ` |
190 | | - Try for |
191 | | - <a href="https://github.com/rust-lang/rust/pull/${reason["Try"].pr}"> |
192 | | - #${reason["Try"].pr} |
193 | | - </a>`; |
194 | | - } else { |
195 | | - // Should never happen, but a good fallback |
196 | | - return JSON.stringify(reason); |
197 | | - } |
198 | | -} |
199 | | - |
200 | | -function commit_url(commit) { |
201 | | - return `<a href="https://github.com/rust-lang/rust/commit/${ |
202 | | - commit.sha |
203 | | - }">${commit.sha.substr(0, 13)}</a>`; |
204 | | -} |
205 | | - |
206 | | -function format_duration(seconds) { |
207 | | - let secs = seconds % 60; |
208 | | - let mins = Math.trunc(seconds / 60); |
209 | | - let hours = Math.trunc(mins / 60); |
210 | | - mins -= hours * 60; |
211 | | - |
212 | | - let s = ""; |
213 | | - if (hours > 0) { |
214 | | - s = `${hours}h${mins < 10 ? "0" + mins : mins}m${ |
215 | | - secs < 10 ? "0" + secs : secs |
216 | | - }s`; |
217 | | - } else { |
218 | | - s = `${mins < 10 ? " " + mins : mins}m${secs < 10 ? "0" + secs : secs}s`; |
219 | | - } |
220 | | - return s; |
221 | | -} |
222 | | - |
223 | | -async function make_data() { |
224 | | - const response = await getJson<StatusResponse>(STATUS_DATA_URL); |
225 | | - populate_data(response); |
226 | | -} |
227 | | - |
228 | | -make_data(); |
| 1 | +import Status from "./status/page.vue"; |
| 2 | +import {createApp} from "vue"; |
| 3 | +import WithSuspense from "../components/with-suspense.vue"; |
| 4 | + |
| 5 | +const app = createApp(WithSuspense, { |
| 6 | + component: Status, |
| 7 | +}); |
| 8 | +app.mount("#app"); |
0 commit comments