430 lines
17 KiB
HTML
430 lines
17 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en" data-bs-theme="dark">
|
|
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta content="width=device-width, initial-scale=1" name="viewport">
|
|
<title>ALHP Status</title>
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
|
|
<link crossorigin="anonymous" href="https://cdn.jsdelivr.net/npm/fork-awesome@1.2.0/css/fork-awesome.min.css" integrity="sha256-XoaMnoYC5TH6/+ihMEnospgm0J1PM/nioxbOUdnM8HY=" rel="stylesheet">
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/Scalesoft/s-pagination@3.0.1/dist/pagination.css" crossorigin="anonymous">
|
|
|
|
<style>
|
|
/* This style fixes the position of the pagination */
|
|
.pagination-container ul {
|
|
margin-top: 0 !important;
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body style="background-color: #111217">
|
|
<nav class="navbar navbar-expand-lg sticky-top navbar-light bg-primary">
|
|
<div class="container">
|
|
<div class="d-flex justify-content-start">
|
|
<span class="navbar-brand align-middle">ALHP Status</span>
|
|
<span class="navbar-text">
|
|
<a class="align-middle" href="https://somegit.dev/ALHP/ALHP.GO" target="_blank">
|
|
<i class="fa fa-gitea fs-4"></i>
|
|
</a>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
<div class="container">
|
|
<div class="pt-4 pb-4">
|
|
<h4>Buildserver Stats</h4>
|
|
<iframe allowtransparency="true" class="container-fluid rounded-1 overflow-hidden" height="420px" src="https://stats.itsh.dev/public-dashboards/0fb04abb0c5e4b7390cf26a98e6dead1"></iframe>
|
|
</div>
|
|
|
|
<h3>Packages</h3>
|
|
<div class="d-flex justify-space-between mt-4" style="height: 37px">
|
|
<div class="d-flex gap-3 w-50">
|
|
<input type="text" class="form-control" id="input-pkgbase" placeholder="Search Pkgbase">
|
|
|
|
<select class="form-select" id="select-repository" aria-label="Repository select">
|
|
<option value="any" selected>Repository (any)</option>
|
|
<option value="core-x86-64-v2">core-x86-64-v2</option>
|
|
<option value="extra-x86-64-v2">extra-x86-64-v2</option>
|
|
<option value="multilib-x86-64-v2">multilib-x86-64-v2</option>
|
|
<option value="core-x86-64-v3">core-x86-64-v3</option>
|
|
<option value="extra-x86-64-v3">extra-x86-64-v3</option>
|
|
<option value="multilib-x86-64-v3">multilib-x86-64-v3</option>
|
|
<option value="core-x86-64-v4">core-x86-64-v4</option>
|
|
<option value="extra-x86-64-v4">extra-x86-64-v4</option>
|
|
<option value="multilib-x86-64-v4">multilib-x86-64-v4</option>
|
|
</select>
|
|
|
|
<select class="form-select" id="select-status" aria-label="Status select">
|
|
<option value="any" selected>Status (any)</option>
|
|
<option value="latest">Latest</option>
|
|
<option value="build">Built</option>
|
|
<option value="failed">Failed</option>
|
|
<option value="skipped">Skipped</option>
|
|
<option value="delayed">Delayed</option>
|
|
<option value="building">Building</option>
|
|
<option value="signing">Signing</option>
|
|
<option value="unknown">Unknown</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div id="pagination" style="line-height: 27px; margin-left: auto"></div>
|
|
</div>
|
|
|
|
<table class="table mt-2" style="margin-bottom: 100px">
|
|
<thead>
|
|
<tr>
|
|
<th scope="col">Repository</th>
|
|
<th scope="col">Pkgbase</th>
|
|
<th scope="col">Status</th>
|
|
<th scope="col">Reason</th>
|
|
<th class="text-center" scope="col" title="link time optimization does not guarantee that package is actually built with LTO">
|
|
LTO
|
|
</th>
|
|
<th class="text-center" scope="col" title="Debug-symbols available via debuginfod">DS
|
|
</th>
|
|
<th scope="col">Archlinux Version</th>
|
|
<th scope="col">ALHP Version</th>
|
|
<th class="text-end" scope="col">Info</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="main-tbody"></tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<footer class="text-center text-lg-start fixed-bottom" style="background-color: #000000">
|
|
<div class="p-2 text-center ">
|
|
<span id="stats-latest"></span><span style="color: #084f46"> latest</span>
|
|
<span id="stats-queued"></span><span style="color: #5d2f03"> queued</span>
|
|
<span id="stats-skipped"></span><span style="color: #4c4c4c"> skipped</span>
|
|
<span id="stats-failed"></span><span style="color: #4f140f"> failed</span> ‖
|
|
<span class="fw-bold">LTO: </span> <span id="stats-lto"></span><span style="color: #084f46"> enabled</span>
|
|
<span id="stats-lto-disabled"></span><span style="color: #4f140f"> disabled</span>
|
|
<span id="stats-lto-unknown"></span><span style="color: #646464"> unknown</span>
|
|
</div>
|
|
</footer>
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
|
|
<script src="https://cdn.jsdelivr.net/gh/Scalesoft/s-pagination@3.0.1/dist/pagination.js"></script>
|
|
<script>
|
|
const url = new URL(window.location)
|
|
|
|
const pagination = new Pagination({
|
|
container: document.getElementById('pagination'),
|
|
pageClickCallback: function (pageNumber) {
|
|
searchPackages((pageNumber - 1) * 50)
|
|
}
|
|
})
|
|
|
|
const ref = {
|
|
totalItems: 0
|
|
}
|
|
const handler = {
|
|
get(target, prop, receiver) {
|
|
if (prop === 'totalItems') {
|
|
return target.totalItems
|
|
}
|
|
return Reflect.get(...arguments)
|
|
},
|
|
set(obj, prop, value) {
|
|
if (prop === 'totalItems') {
|
|
obj[prop] = value
|
|
}
|
|
|
|
pagination.make(value, 50)
|
|
return true
|
|
}
|
|
}
|
|
const pages = new Proxy(ref, handler)
|
|
|
|
const inputPkgbase = document.getElementById('input-pkgbase')
|
|
const selectRepo = document.getElementById('select-repository')
|
|
const selectStatus = document.getElementById('select-status')
|
|
|
|
function getStats() {
|
|
fetch('https://api.alhp.dev/stats')
|
|
.then(response => {
|
|
if (!response.ok) throw new Error(response.statusText)
|
|
return response.json()
|
|
}).then(stats => {
|
|
document.getElementById('stats-latest').innerText = stats.latest
|
|
document.getElementById('stats-queued').innerText = stats.queued
|
|
document.getElementById('stats-skipped').innerText = stats.skipped
|
|
document.getElementById('stats-failed').innerText = stats.failed
|
|
document.getElementById('stats-lto').innerText = stats.lto.enabled
|
|
document.getElementById('stats-lto-disabled').innerText = stats.lto.disabled
|
|
document.getElementById('stats-lto-unknown').innerText = stats.lto.unknown
|
|
}).catch(error => {
|
|
console.error(error)
|
|
}).finally(() => {})
|
|
}
|
|
|
|
function searchPackages(offset) {
|
|
const params = new URLSearchParams({
|
|
limit: 50,
|
|
offset
|
|
})
|
|
|
|
if (inputPkgbase.value) params.append('pkgbase', inputPkgbase.value.toLowerCase())
|
|
if (selectRepo.value !== 'any') params.append('repo', selectRepo.value)
|
|
if (selectStatus.value !== 'any') params.append('status', selectStatus.value)
|
|
|
|
fetch('https://api.alhp.dev/packages?' + params, {
|
|
method: 'GET',
|
|
}).then(response => {
|
|
if (response.ok) return response.json()
|
|
if (response.status === 404) {
|
|
const tableBody = document.getElementById('main-tbody')
|
|
const ntb = document.createElement('tbody')
|
|
ntb.id = 'main-tbody'
|
|
const ntr = document.createElement('tr')
|
|
const ntd = document.createElement('td')
|
|
ntd.innerText = 'No Packages found'
|
|
|
|
ntb.appendChild(ntr.appendChild(ntd))
|
|
tableBody.replaceWith(ntb)
|
|
|
|
pages.totalItems = 0
|
|
} else {
|
|
throw new Error(response.statusText)
|
|
}
|
|
}).then(packages => {
|
|
if (!packages) return
|
|
|
|
if (pages.totalItems !== packages.total) {
|
|
pages.totalItems = packages.total
|
|
}
|
|
|
|
const tableBody = document.getElementById('main-tbody')
|
|
const ntb = document.createElement('tbody')
|
|
ntb.id = 'main-tbody'
|
|
|
|
for (const pkg of packages.packages) {
|
|
const rowColor = getStatus(pkg.status)
|
|
|
|
const ntr = document.createElement('tr')
|
|
ntr.id = pkg.pkgbase + '-' + pkg.repo
|
|
|
|
// Create table cells
|
|
const Repository = document.createElement('td')
|
|
Repository.style.backgroundColor = rowColor
|
|
const repo = pkg.repo.split('-')
|
|
Repository.innerHTML = `<span class="fw-bold">${repo[0]}</span> <span style="width: 1.25rem; height: 1.25rem; border-radius: 5px; background-color: ${ getVersionColor(repo[repo.length - 1]) }; padding: 0 10px">${repo[repo.length - 1]}</span>`
|
|
ntr.appendChild(Repository)
|
|
|
|
const PkgBase = document.createElement('td')
|
|
PkgBase.style.backgroundColor = rowColor
|
|
PkgBase.innerText = pkg.pkgbase
|
|
ntr.appendChild(PkgBase)
|
|
|
|
const Status = document.createElement('td')
|
|
Status.style.backgroundColor = rowColor
|
|
Status.innerText = pkg.status.toLocaleUpperCase()
|
|
ntr.appendChild(Status)
|
|
|
|
const Reason = document.createElement('td')
|
|
Reason.style.backgroundColor = rowColor
|
|
Reason.innerText = pkg.skip_reason || ''
|
|
ntr.appendChild(Reason)
|
|
|
|
const LTO = document.createElement('td')
|
|
LTO.style.backgroundColor = rowColor
|
|
const ltoObj = getLto(pkg.lto)
|
|
LTO.innerHTML = `<i class="${ltoObj.class}" title="${ltoObj.title}"></i>`
|
|
ntr.appendChild(LTO)
|
|
|
|
const DS = document.createElement('td')
|
|
DS.style.backgroundColor = rowColor
|
|
const dsObj = getDs(pkg.debug_symbols)
|
|
DS.innerHTML = `<i class="${dsObj.class}" title="${dsObj.title}"></i>`
|
|
ntr.appendChild(DS)
|
|
|
|
const ArchLinuxVersion = document.createElement('td')
|
|
ArchLinuxVersion.style.backgroundColor = rowColor
|
|
ArchLinuxVersion.innerText = pkg.arch_version
|
|
ntr.appendChild(ArchLinuxVersion)
|
|
|
|
const AlhpVersion = document.createElement('td')
|
|
AlhpVersion.style.backgroundColor = rowColor
|
|
AlhpVersion.innerText = pkg.repo_version
|
|
ntr.appendChild(AlhpVersion)
|
|
|
|
const Info = document.createElement('td')
|
|
Info.style.backgroundColor = rowColor
|
|
const logFile = pkg.status === 'failed' ? '<a href="https://alhp.dev/logs/' + pkg.repo.slice(pkg.repo.indexOf('-') + 1) + '/' + pkg.pkgbase + '.log" class="text-decoration-none text-white-50" target="_blank"><i class="fa fa-file-text fa-lg"></i></a>' : ''
|
|
const aw = '<a href="https://archlinux.org/packages/?q=' + pkg.pkgbase + '" target="_blank" title="ArchWeb" class="text-decoration-none text-white-50 fw-bold">AW</a>'
|
|
let info = ''
|
|
if (pkg.build_date && pkg.peak_mem) {
|
|
info = '<i class="fa fa-info-circle fa-lg text-white-50" data-bs-html="true" data-bs-placement="bottom" data-bs-toggle="tooltip" title="' + `${pkg.build_date ? 'Built on ' + pkg.build_date + ' ' : ''}${pkg.peak_mem ? 'Peak-Memory: ' + pkg.peak_mem : ''}` + '"></i>'
|
|
}
|
|
Info.classList.add('text-end')
|
|
Info.innerHTML = `${logFile} ${aw} ${info}`
|
|
ntr.appendChild(Info)
|
|
|
|
// Append Table Row to Table Body
|
|
ntb.appendChild(ntr)
|
|
}
|
|
|
|
tableBody.replaceWith(ntb)
|
|
}).catch(error => {
|
|
console.error(error)
|
|
})
|
|
}
|
|
|
|
const getVersionColor = (version) => {
|
|
let color = 'grey'
|
|
switch (version) {
|
|
case 'v2':
|
|
color = '#3498db'
|
|
break
|
|
case 'v3':
|
|
color = '#f39c12'
|
|
break
|
|
case 'v4':
|
|
color = '#2ecc71'
|
|
break
|
|
}
|
|
return color
|
|
}
|
|
|
|
const getStatus = (status) => {
|
|
let color = ''
|
|
switch (status) {
|
|
case 'skipped':
|
|
color = '#373737'
|
|
break
|
|
case 'queued':
|
|
color = '#5d2f03'
|
|
break
|
|
case 'latest':
|
|
color = ''
|
|
break
|
|
case 'failed':
|
|
color = '#4f140f'
|
|
break
|
|
case 'signing':
|
|
color = '#093372'
|
|
break
|
|
case 'building':
|
|
color ='#084f46'
|
|
break
|
|
case 'unknown':
|
|
color ='#191919'
|
|
break
|
|
}
|
|
return color
|
|
}
|
|
|
|
const getLto = (lto) => {
|
|
let icon = {
|
|
title: '',
|
|
class: ''
|
|
}
|
|
switch (lto) {
|
|
case 'enabled':
|
|
icon = {
|
|
title: 'built with LTO',
|
|
class: 'fa fa-check fa-lg text-success'
|
|
}
|
|
break
|
|
case 'unknown':
|
|
icon = {
|
|
title: 'not built with LTO yet',
|
|
class: 'fa fa-hourglass-o fa-lg text-black-50'
|
|
}
|
|
break
|
|
case 'disabled':
|
|
icon = {
|
|
title: 'LTO explicitly disabled',
|
|
class: 'fa fa-times fa-lg text-danger'
|
|
}
|
|
break
|
|
case 'auto_disabled':
|
|
icon = {
|
|
title: 'LTO automatically disabled',
|
|
class: 'fa fa-times-circle-o fa-lg text-warning'
|
|
}
|
|
break
|
|
}
|
|
return icon
|
|
}
|
|
|
|
const getDs = (lto) => {
|
|
let icon = {
|
|
title: '',
|
|
class: ''
|
|
}
|
|
switch (lto) {
|
|
case 'available':
|
|
icon = {
|
|
title: 'Debug symbols available',
|
|
class: 'fa fa-check fa-lg text-success'
|
|
}
|
|
break
|
|
case 'unknown':
|
|
icon = {
|
|
title: 'Not built yet',
|
|
class: 'fa fa-hourglass-o fa-lg text-black-50'
|
|
}
|
|
break
|
|
case 'not_available':
|
|
icon = {
|
|
title: 'Not built with debug symbols',
|
|
class: 'fa fa-times fa-lg text-danger'
|
|
}
|
|
break
|
|
}
|
|
return icon
|
|
}
|
|
|
|
window.addEventListener('load', () => {
|
|
inputPkgbase.value = url.searchParams.has('pkgbase') ? url.searchParams.get('pkgbase').toLowerCase() : ''
|
|
selectRepo.value = url.searchParams.has('repo') ? url.searchParams.get('repo').toLowerCase() : 'any'
|
|
selectStatus.value = url.searchParams.has('status') ? url.searchParams.get('status').toLowerCase() : 'any'
|
|
|
|
getStats()
|
|
searchPackages(0)
|
|
})
|
|
|
|
let delayTimer = null
|
|
inputPkgbase.addEventListener('input', () => {
|
|
if (delayTimer) clearTimeout(delayTimer);
|
|
delayTimer = setTimeout(function() {
|
|
if (inputPkgbase.value) {
|
|
url.searchParams.set('pkgbase', inputPkgbase.value.toLowerCase())
|
|
} else {
|
|
url.searchParams.delete('pkgbase')
|
|
}
|
|
window.history.pushState(null, '', url.toString())
|
|
searchPackages(0)
|
|
}, 250);
|
|
});
|
|
|
|
selectRepo.addEventListener('change', () => {
|
|
if (selectRepo.value) {
|
|
if (selectRepo.value === 'any') {
|
|
url.searchParams.delete('repo')
|
|
} else {
|
|
url.searchParams.set('repo', selectRepo.value)
|
|
}
|
|
window.history.pushState(null, '', url.toString())
|
|
}
|
|
searchPackages(0)
|
|
})
|
|
|
|
selectStatus.addEventListener('change', () => {
|
|
if (selectStatus.value) {
|
|
if (selectStatus.value === 'any') {
|
|
url.searchParams.delete('status')
|
|
} else {
|
|
url.searchParams.set('status', selectStatus.value)
|
|
}
|
|
window.history.pushState(null, '', url.toString())
|
|
}
|
|
searchPackages(0)
|
|
})
|
|
</script>
|
|
</body>
|
|
|
|
</html>
|