1/** 2 * Copyright (c) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you 5 * may not use this file except in compliance with the License. You may 6 * obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 13 * implied. See the License for the specific language governing 14 * permissions and limitations under the License. 15 */ 16 17'use strict'; 18 19const REPO_URL = 'https://android.googlesource.com/platform/external/perfetto/'; 20const GERRIT_REVIEW_URL = 'https://android-review.googlesource.com/c/platform/external/perfetto'; 21const CHANGES_URL = '/changes/?q=project:platform/external/perfetto+-age:7days+-is:abandoned&o=DETAILED_ACCOUNTS'; 22const REPO = 'catapult-project/perfetto'; 23 24let botIndex = {}; 25 26// Builds a map of bot name -> column index, e.g.: 27// {'linux-clang-x86_64-relese' -> 1, 'android-clang-arm-debug' -> 2}. 28function GetColumnIndexes() { 29 const cols = document.getElementById('cls_header').children; 30 for (let i = 0; i < cols.length; i++) { 31 const id = cols[i].id; 32 if (id) 33 botIndex[id] = i + 4 /* 4 = subject...updated columns */; 34 } 35} 36 37function GetTravisStatusForJob(jobId, div) { 38 fetch('https://api.travis-ci.org/jobs/' + jobId) 39 .then(response => { 40 if (response.status != 200) 41 throw 'Unable to make request to Travis'; 42 return response.json(); 43 }) 44 .then(resp => { 45 let jobName = resp.config.env.split(' ')[0]; 46 if (jobName.startsWith('CFG=')) 47 jobName = jobName.substring(4); 48 if (!(jobName in botIndex)) 49 return; 50 let link = document.createElement('a'); 51 link.href = 'https://travis-ci.org/' + REPO + '/jobs/' + jobId; 52 link.title = resp.state + ' [' + jobName + ']'; 53 let jobState = resp.state; 54 if (resp.state == 'finished' && resp.result !== 0) 55 jobState = 'errored'; 56 link.classList.add(jobState); 57 if (jobState == 'finished') 58 link.innerHTML = '<i class="material-icons">check_circle</i>'; 59 else if (jobState == 'created') 60 link.innerHTML = '<i class="material-icons">autorenew</i>'; 61 else if (jobState == 'errored' || jobState == 'cancelled') 62 link.innerHTML = '<i class="material-icons">bug_report</i>'; 63 else 64 link.innerHTML = '<i class="material-icons">hourglass_full</i>'; 65 let td = div.children[botIndex[jobName]]; 66 td.innerHTML = ''; 67 td.appendChild(link); 68 }); 69} 70 71function GetTravisStatusForBranch(branch, div) { 72 fetch('https://api.travis-ci.org/repos/' + REPO + '/branches/' + branch) 73 .then(response => { 74 if (response.status != 200) 75 throw 'Unable to make request to Travis'; 76 return response.json() 77 }) 78 .then(resp => { 79 for (const jobId of resp.branch.job_ids) 80 GetTravisStatusForJob(jobId, div); 81 }); 82} 83 84function CreateRowForBranch(branch, href, subject, status, author, updated) { 85 let table = document.getElementById('cls'); 86 let tr = document.createElement('tr'); 87 tr.classList.add(status); 88 89 let link = document.createElement('a'); 90 link.href = href; 91 link.innerText = subject; 92 let td = document.createElement('td'); 93 td.appendChild(link); 94 tr.appendChild(td); 95 96 td = document.createElement('td'); 97 td.innerText = status; 98 tr.appendChild(td); 99 100 td = document.createElement('td'); 101 td.innerText = author; 102 tr.appendChild(td); 103 104 td = document.createElement('td'); 105 td.innerText = updated; 106 tr.appendChild(td); 107 108 for (let _ in botIndex) { 109 td = document.createElement('td'); 110 td.classList.add('job'); 111 tr.appendChild(td); 112 } 113 table.appendChild(tr); 114 GetTravisStatusForBranch(branch, tr); 115} 116 117function LoadGerritCLs() { 118 fetch(CHANGES_URL) 119 .then(response => { 120 if (response.status != 200) 121 throw 'Unable to make request to Travis'; 122 return response.text(); 123 }) 124 .then(text => { 125 let json; 126 if (text.startsWith(')]}\'')) 127 json = text.substring(4); 128 else 129 json = text; 130 let resp = JSON.parse(json); 131 for (const cl of resp) { 132 const branch = 'changes/' + cl._number; 133 const href = GERRIT_REVIEW_URL + '/+/' + cl._number;; 134 const lastUpdate = new Date(cl.updated + ' UTC'); 135 const lastUpdateMins = Math.ceil((Date.now() - lastUpdate) / 60000); 136 let lastUpdateText = ''; 137 if (lastUpdateMins < 60) 138 lastUpdateText = lastUpdateMins + ' mins ago'; 139 else if (lastUpdateMins < 60 * 24) 140 lastUpdateText = Math.ceil(lastUpdateMins / 60) + ' hours ago'; 141 else 142 lastUpdateText = lastUpdate.toLocaleDateString(); 143 CreateRowForBranch(branch, href, cl.subject, cl.status, 144 cl.owner.email.replace('@google.com', '@'), lastUpdateText); 145 } 146 }); 147} 148 149// Register the service worker to cache job requests. 150if ('serviceWorker' in navigator) { 151 navigator.serviceWorker.register('/service_worker.js', { scope: '/' }); 152} 153 154// Fetch the CLs and the corresponding status for the Travis jobs. 155GetColumnIndexes(); 156CreateRowForBranch('master', REPO_URL, '*** master branch ***', 'MASTER', '', ''); 157LoadGerritCLs(); 158