docker-ci/ci/template.html

702 lines
17 KiB
HTML
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>CI Results {{ image }}:{{ meta_tag }}</title>
<meta name="description" content="CI: {{ 'PASS ✅' if report_status=='PASS' else 'FAIL ❌' }}">
<meta name="author" content="linuxserver.io">
<meta name="theme-color" content="#da3b8a">
<!-- Google / Search Engine Tags -->
<meta itemprop="name" content="CI Results for {{ image }}:{{ meta_tag }}">
<meta itemprop="description" content="CI: {{ 'PASS ✅' if report_status=='PASS' else 'FAIL ❌' }}">
<meta itemprop="image" content="https://{{ bucket }}/{{ image }}/{{ meta_tag }}/logo.jpg">
<!-- Open Graph / Facebook -->
<meta property="og:type" content="website">
<meta property="og:site_name" content="{{ bucket }}">
<meta property="og:url" content="https://{{ bucket }}/">
<meta property="og:title" content="CI Results for {{ image }}:{{ meta_tag }}">
<meta property="og:description" content="CI: {{ 'PASS ✅' if report_status=='PASS' else 'FAIL ❌' }}">
<meta property="og:image" content="https://{{ bucket }}/{{ image }}/{{ meta_tag }}/logo.jpg">
<!-- Twitter -->
<meta property="twitter:card" content="summary_large_image">
<meta property="twitter:url" content="https://{{ bucket }}/">
<meta property="twitter:title" content="CI Results for {{ image }}:{{ meta_tag }}">
<meta property="twitter:description" content="CI: {{ 'PASS ✅' if report_status=='PASS' else 'FAIL ❌' }}">
<meta property="twitter:image" content="https://{{ bucket }}/{{ image }}/{{ meta_tag }}/logo.jpg">
<!-- Favicon-->
<link rel="icon" type="image/x-icon" href="favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://fonts.googleapis.com/css?family=Lato:400,700&display=swap" rel="stylesheet">
<script defer src="https://use.fontawesome.com/releases/v5.15.4/js/all.js"
integrity="sha384-rOA1PnstxnOBLzCLMcre8ybwbTmemjzdNlILg8O7z1lUkLXozs4DHonlDtnE7fpc"
crossorigin="anonymous"></script>
<style>
@media (prefers-color-scheme: dark) {
body {
background: linear-gradient(to right, rgba(34, 34, 34, 1), rgba(34, 34, 34, 1));
color: #96a2b4;
}
h1 {
color: #dce2ec;
}
h1 span {
color: rgba(218, 59, 138);
}
a {
color: rgba(218, 59, 138);
}
a:hover {
color: rgb(188, 52, 120);
}
section {
background: rgba(44, 44, 44);
border: solid 1px rgb(255 255 255 / 10%);
}
.section-header {
background: rgba(44, 44, 44);
border-bottom: 1px solid rgba(255, 255, 255, 0.1)
}
.section-header-h2 {
color: #96a2b4;
}
section h3 {
color: rgba(218, 59, 138);
}
.summary {
color: rgba(218, 59, 138);
}
.summary:hover {
color: rgb(188, 52, 120);
}
.styled-table {
border: solid 1px rgb(255 255 255 / 10%);
}
.styled-table thead tr {
background-color: #1f1f1f;
}
.styled-table tbody tr {
border-bottom: 1px solid rgba(221, 221, 221, 0.1);
}
.styled-table tbody tr:nth-of-type(even) {
background-color: rgba(255, 255, 255, 0.1);
}
.summary-container {
background: #1f1f1f;
}
summary:hover {
color: #dce2ec;
}
pre {
background: #1f1f1f;
}
.build {
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
border-top: 1px solid rgba(255, 255, 255, 0.1);
background: rgba(0, 0, 0, 0.25);
}
.build-header {
color:rgba(218, 59, 138);
}
.runtime {
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
background: rgba(0, 0, 0, 0.25);
}
strong {
color: rgba(218, 59, 138);
}
.warning-note {
color: #96a2b4;
}
.log-debug {color:lightgray}
.log-info {color:lightskyblue}
.log-warning {color:darkorange}
.log-error {color:red;font-weight: bolder;}
.log-success{color:limegreen;font-weight: bolder;}
}
@media (prefers-color-scheme: light) {
body {
background: #e8e8e8;
color: #738694;
}
.warning-note {
color: #738694;
}
h1 {
color: #738694;
}
h1 span {
color: #9bb0bf;
}
a {
color: #738694;
}
a:hover {
color: #9bb0bf;
}
section {
background: #efefef;
border: solid 1px rgb(0 0 0 / 15%);
}
.section-header {
background: #738694;
}
.section-header-h2 {
color: #FFFFFF;
}
.styled-table thead tr {
background-color: #738694;
}
.styled-table tbody tr {
border-bottom: 1px solid #dddddd;
}
.styled-table tbody tr:nth-of-type(even) {
background-color: #f3f3f3;
}
.section-header-status .report-status-pass {
color: #00c29a;
}
.summary-container {
background: #e8e8e8;
}
summary:hover {
color: #4b5d6a;
}
pre {
background: #e8e8e8;
}
.build {
border-bottom: 1px solid #dcdcdc;
background: #f5f5f5;
}
.runtime {
border-bottom: 1px solid #dcdcdc;
background: #f5f5f5;
}
.build-header {
color:#738694;
}
.log-debug {color:#9bb0bf}
.log-info {color:#60707c}
.log-warning {color:darkorange}
.log-error {color:red;font-weight: bolder;}
.log-success{color:#009879;font-weight: bolder;}
}
body,
html {
padding: 0;
margin: 0;
}
body {
font-family: 'Lato', sans-serif;
font-weight: 400;
font-size: 16px;
}
body * {
box-sizing: border-box;
}
#logohttpsrawgithubusercontentcomlinuxserverdockertemplatesmasterlinuxserverioimglinuxserver_mediumpng {
display: none;
}
a {
text-decoration: none;
}
a[target="_blank"]::after {
content: " \2197";
font-size: 80%;
margin-left: 4px;
vertical-align: middle;
}
#app {
display: flex;
flex-direction: column;
align-items: center;
padding: 15px;
}
#results {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
}
h1 {
font-size: 30px;
letter-spacing: 3px;
text-transform: uppercase;
font-weight: 400;
}
#results h1 {
font-size: 18px;
margin: 0 10px 25px;
word-break: break-all;
}
#results table {
margin: auto;
width: 100%;
}
.styled-table th,
.styled-table td {
word-wrap: break-word;
}
table {
table-layout: fixed;
}
th {
text-align: left
}
section {
display: flex;
width: 100%;
flex-direction: column;
margin: 10px;
min-width: 320px;
max-width: 50vw;
padding: 0 0 30px 0;
flex: 1 1 0;
border-radius: 10px;
}
section>* {
padding: 0 30px;
}
.section-header {
border-radius: 10px 10px 0 0;
overflow-wrap: break-word;
}
.section-header-h2 {
font-size: 17px;
padding: 15px 30px;
margin: 0;
text-align: center;
flex-wrap: wrap;
}
.section-header-status {
font-size: 17px;
padding-top: .5rem;
margin: 0;
text-align: center;
flex-wrap: wrap;
}
em {
color: #32a7c1;
}
/* No image */
section h2+h3 {
border-bottom: 1px solid #dcdcdc;
padding-bottom: 20px;
background: #f5f5f5;
margin: 0;
font-size: 12px;
word-break: break-all;
}
/* Has an image */
section h2+p+h3 {
border-bottom: 1px solid #dcdcdc;
padding: 20px 30px;
background: #f5f5f5;
margin: 0;
font-size: 12px;
word-break: break-all;
}
section h2+p {
margin: 0;
}
section p:empty {
display: none;
}
section h3 {
font-size: 16px;
padding: 0 30px;
}
.summary {
font-weight: bold;
margin-block-start: 1em;
margin-inline-start: 0px;
margin-inline-end: 0px;
}
section img {
width: calc(100% + 60px);
height: auto;
margin-left: -30px;
margin-right: -30px;
padding: 0;
display: block;
}
.debug-section {
max-width: 100%;
}
main {
display: flex;
justify-content: center;
align-items: stretch;
flex-wrap: wrap;
max-width: 100%;
}
@media only screen and (min-width: 500px) {
h1 {
font-size: 50px;
letter-spacing: 5px;
}
#results h1 {
font-size: 25px;
}
}
@media only screen and (max-width: 500px) {
/*Mobile*/
section h3,
section details,
.warning-notice,
.table-container {
padding: 0 5px;
}
.table-container {
padding-top: 10px;
}
}
.table-container {
padding-top: 1rem;
}
.styled-table {
border-collapse: collapse;
margin: 25px 0;
font-size: 0.9em;
font-family: sans-serif;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.15);
}
.styled-table thead tr {
color: #ffffff;
text-align: left;
}
.styled-table th,
.styled-table td {
padding: 12px 15px;
}
.styled-table tbody tr.active-row {
font-weight: bold;
color: #738694;
}
.fa-check-circle {
color: rgb(0, 152, 121);
margin-left: 5px;
}
.fa-exclamation-circle {
color: #f44336;
margin-left: 5px;
}
.fa-exclamation-triangle {
color: darkorange;
}
.summary-container {
min-height: 100px;
height: 300px;
margin-top: 0.5em;
overflow: auto;
resize: vertical;
}
summary {
cursor: pointer;
}
#logs {
overflow: auto;
}
pre {
padding: 10px;
}
.build-section {
text-align: center;
font-weight: bold;
padding: .3rem;
font-size: 14px;
}
.build-info-section {
padding: 10px 30px;
margin: 0;
font-size: 12px;
}
.build-info {
padding-right: .3rem;
padding-left: .3rem;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.build-summary {
display: flex;
}
.tag-image {
text-align: center;
}
.report-status-pass {
color: rgb(0, 152, 121)
}
.report-status-fail {
color: #f44336;
}
.warning-notice {
display: inline-flex;
}
.warning-note {
padding-left: .5rem;
padding-top: 0.5em;
font-weight: normal;
}
div.warning-notice > p {
margin-bottom: 0;
}
.warning-summary {
padding-right:5px;
padding-bottom:0;
margin-block-start: 1em;
color: darkorange;
font-weight: bold;
}
.warning-summary:hover {
color: #ff8c00db;
}
</style>
</head>
<body>
<div id="app">
<header>
<h1>Linux<span>Server</span>.io</h1>
</header>
<div id="results">
<h1 style="margin-bottom: 0; text-align: center;">Test Results</h1>
<h2 style="margin-bottom: 0; text-align: center;"><strong>{{ image }}</strong></span></h2>
<h3 style="margin-top:0; margin-bottom: 0; text-align: center;"><strong>{{ meta_tag }}</strong></span></h2>
<h2 style="margin-bottom: 0">Cumulative: <span class="report-status-{{ report_status.lower() }}">{{ report_status }}</span></h2>
<span>Total Runtime: {{ total_runtime }}</span>
<main>
{% for tag in report_containers %}
<section>
<div class="section-header">
{% if report_containers[tag]["test_success"] %}
<h3 class="section-header-status"><span class="report-status-pass">{{ report_containers[tag]["platform"] }} PASS</span></h3>
{% else %}
<h3 class="section-header-status"><span class="report-status-fail">{{ report_containers[tag]["platform"] }} FAIL</span></h3>
{% endif %}
<h2 class="section-header-h2">
{% if report_status.lower() == "pass" %}
<a target="_blank" href="{{ report_containers[tag]['build_url'] }}">{{ image }}</a>
{% else %}
{{ image }}:{{ tag }}
{% endif %}
</h2> </div>
<div class="runtime build-section">Runtime: {{ report_containers[tag]["runtime"] }}</div>
{% if screenshot %}
<a href="{{ tag }}.png">
<img src="{{ tag }}.png" alt="{{ tag }}" width="600" height="auto" onerror="this.onerror=null; this.src='404.jpg'; this.parentElement.setAttribute('href','#')">
</a>
{% else %}
<div class="tag-image">
<span>WEB_SCREENSHOT ENV Disabled</span><i class="fas fa-file-image"></i>
</div>
{% endif %}
<div class="build-section">Build Information</div>
<div class="build-info-section build">
{% for key, value in report_containers[tag]["build_info"].items() %}
<div class="build-summary">
<span class="build-header">{{ key|capitalize }}:</span> <span class="build-info">{{ value }}</span>
</div>
{% endfor %}
</div>
<summary class="summary">
<a href="{{ tag }}.log.html" target="_blank">View Container Logs</a>
</summary>
<details>
<summary>Expand</summary>
<div class="summary-container">
<pre><code>{{ report_containers[tag]["logs"] }}</code></pre>
</div>
</details>
<summary class="summary">
<a href="{{ tag }}.sbom.html" target="_blank">View SBOM output</a>
</summary>
<details>
<summary>Expand</summary>
<div class="summary-container">
<pre><code>{{ report_containers[tag]["sysinfo"] }}</code></pre>
</div>
</details>
{% if report_containers[tag]["browser_logs"] %}
<summary class="summary">
<a href="{{ tag }}.browser.html" target="_blank">View Browser Console Logs</a>
</summary>
<details>
<summary>Expand</summary>
<div class="summary-container">
<pre><code>{{ report_containers[tag]["browser_logs"] }}</code></pre>
</div>
</details>
{% endif %}
{% if report_containers[tag]["has_warnings"]%}
<details open>
<summary class="warning-summary">Warnings</summary>
{% for warning in report_containers[tag]["warnings"] %}
{% if report_containers[tag]["warnings"][warning] %}
<div class="warning-notice">
<code class="warning-note"><i class="fa fa-exclamation-triangle" aria-hidden="true"></i> {{ report_containers[tag]["warnings"][warning] }}</code>
</div>
{% endif %}
{% endfor %}
</details>
{% endif %}
<div class="table-container">
<table class="styled-table">
<thead>
<tr class="active-row">
<th>Test</th>
<th>Result</th>
<th>Message</th>
<th>Runtime</th>
</tr>
</thead>
<tbody>
{% for test in report_containers[tag]["test_results"] %}
<tr>
<td>{{ test }}</td>
{% if report_containers[tag]["test_results"][test]['status'] == 'PASS' %}
<td class="result-cell">{{ report_containers[tag]["test_results"][test]['status'] }} <i class="fas fa-check-circle"></i></td>
{% else %}
<td class="result-cell">{{ report_containers[tag]["test_results"][test]['status'] }} <i class="fas fa-exclamation-circle"></i></td>
{% endif %}
<td>{{ report_containers[tag]["test_results"][test]["message"] }}</td>
<td>{{ report_containers[tag]["test_results"][test]["runtime"] }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</section>
{% endfor %}
</main>
</div>
<section class="debug-section">
<summary class="summary">
<a href="python.log.html" target="_blank">View Python Logs</a>
</summary>
<details>
<summary>Expand</summary>
<pre id="logs"></pre>
</details>
</section>
</div>
<script type="text/javascript" charset="utf-8">
fetch("ci.log")
.then(response => response.text())
.then(logs => {
pylogs = logs.replace(/\[38;20m/gi,"<span class='log-debug'>"
).replace(/\[33;20m/gi,"<span class='log-warning'>"
).replace(/\[31;20m/gi,"<span class='log-error'>"
).replace(/\[36;20m/gi,"<span class='log-info'>"
).replace(/\[32;20m/gi,"<span class='log-success'>"
).replace(/\[0m/gi,"</span>")
document.getElementById("logs").innerHTML = pylogs
})
</script>
</body>
</html>