status-page: add alerts for github issues (#93)
* status-page: add alerts for github issues * status-page: tweak css
Daiderd Jordan committed
Jan 9, 2020 at 00:02 UTC
32947059eebc33282b7dcfead2431a08b59943b7
3 files changed
+39
-4
delft/eris/status-page/index.html
+2
@@ -57,6 +57,8 @@
57
<h1>NixOS</h1>
58
</div>
59
60
+ <div id="alerts"></div>
61
+
62
<div class="hero12">
63
<h2>Nix Channel Status</h2>
64
<p>See <a href="http://howoldis.herokuapp.com/">HowOldIs</a> and the <a href="https://nixos.wiki/wiki/Nix_channels">NixOS Wiki</a> for information on how channel updates progress.</p>
delft/eris/status-page/status.css
+9
@@ -12,6 +12,15 @@
12
max-width: 15em;
13
}
14
15
+#alerts {
16
+ margin-top: 10px;
17
+}
18
+
19
+.issue-age {
20
+ display: inline-block;
21
+ min-width: 6em;
22
+}
23
+
24
.github {
25
max-width: 10em;
26
overflow: hidden;
delft/eris/status-page/status.js
+28
-4
@@ -8,6 +8,30 @@ function init() {
8
});
9
}
10
11
+async function fetchIssues(label) {
12
+ const response = await fetch(`https://api.github.com/repos/NixOS/nixpkgs/issues?labels=${label}`);
13
+ return await response.json();
14
+}
15
+
16
+fetchIssues("1.severity%3A%20channel%20blocker")
17
+ .then(data => data.map(issue => {
18
+ var el = document.createElement('div');
19
+ el.classList = "alert alert-warning";
20
+ el.innerHTML = '<span class="issue-age"></span> <a class="issue-link"></a>';
21
+ const since = moment(issue['created_at']).fromNow();
22
+ el.getElementsByClassName('issue-age')[0].innerText = since;
23
+ el.getElementsByClassName('issue-link')[0].href = issue['html_url'];
24
+ el.getElementsByClassName('issue-link')[0].innerText = issue['title'];
25
+ if (issue['labels'].find(label => label['name'] == 'infrastructure')) {
26
+ el.innerHTML += ' <span class="label label-important">Infrastructure</span>'
27
+ }
28
+ return el;
29
+ }))
30
+ .then(elems => {
31
+ var alerts = document.getElementById('alerts');
32
+ elems.forEach(el => alerts.appendChild(el));
33
+ });
34
+
35
function aggregateByChannel(result) {
36
return result.reduce((acc, {
37
channel,
@@ -18,7 +42,7 @@ function aggregateByChannel(result) {
42
}), {});
43
}
44
21
-async function fetchData(queryType, queryArgs = {}) {
45
+async function fetchMetrics(queryType, queryArgs = {}) {
46
const params = new URLSearchParams();
47
for (const [key, value] of Object.entries(queryArgs)) {
48
params.set(key, String(value));
@@ -32,7 +56,7 @@ async function fetchData(queryType, queryArgs = {}) {
56
return data.result;
57
}
58
35
-const revisionData = fetchData('query', {
59
+const revisionData = fetchMetrics('query', {
60
query: 'channel_revision'
61
})
62
.then(records => (
@@ -50,7 +74,7 @@ const revisionData = fetchData('query', {
74
.then(aggregateByChannel);
75
76
53
-const updateTimeData = fetchData('query', {
77
+const updateTimeData = fetchMetrics('query', {
78
query: 'channel_update_time'
79
})
80
.then(records => (
@@ -75,7 +99,7 @@ if (idealStart > earliestStart) {
99
start = earliestStart;
100
}
101
var end = moment.utc().format();
78
-const jobsetData = fetchData('query_range', {
102
+const jobsetData = fetchMetrics('query_range', {
103
query: 'hydra_job_failed',
104
start: start.format(),
105
end,