Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • loqs/rebuilderd-website
  • iyanmv/rebuilderd-website
  • mgolebiowski/rebuilderd-website
  • xexaxo/rebuilderd-website
  • duthils/rebuilderd-website
  • aditya/rebuilderd-website
  • kpcyrd/rebuilderd-website
  • archlinux/rebuilderd-website
8 results
Show changes
Commits on Source (34)
# EditorConfig is awesome: http://EditorConfig.org
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
charset = utf-8
indent_style = tab
indent_size = 4
insert_final_newline = true
trim_trailing_whitespace = true
; Python: PEP8 defines 4 spaces for indentation
[*.py]
indent_style = space
indent_size = 4
; YAML format, 2 spaces
[*.yaml, *.yml]
indent_style = space
indent_size = 2
; HTML, CSS and JavaScript, 4 spaces
[*.{html,css,js}]
charset = utf-8
indent_size = 2
indent_style = space
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
Subproject commit fe41472481348017b99e31f205235cdcaa0d556f
Subproject commit 5d3ec1f7a122283fbd5aebb6c8a9c87f43b18ac4
[submodule ".external/archlinux-common-style"]
path = .external/archlinux-common-style
url = ../archlinux-common-style
url = https://gitlab.archlinux.org/archlinux/archlinux-common-style
localhost:8881 {
errors stderr
log stdout
http://localhost:8881
gzip
log
proxy /api https://reproducible.archlinux.org/ {
transparent
}
encode gzip
proxy / 127.0.0.1:9966 {
transparent
}
proxy /livereload 127.0.0.1:9966 {
websocket
transparent
}
}
reverse_proxy localhost:9966
reverse_proxy /api/* https://reproducible.archlinux.org
reverse_proxy /livereload localhost:9966
......@@ -33,7 +33,6 @@ js-watcher: vendor
dist: vendor
@mkdir -p "dist/${PACKAGE_NAME}-${VERSION}"
cp -avf public/index.html "dist/${PACKAGE_NAME}-${VERSION}/index.html"
# TODO: cache-invalidation with version string replaced in html file
svgcleaner public/${ARCHLOGO} "dist/${PACKAGE_NAME}-${VERSION}/archlogo-${VERSION}.svg"
cp -vf public/favicon.ico -t "dist/${PACKAGE_NAME}-${VERSION}/"
$(SASS) -t compressed src/style.scss "dist/${PACKAGE_NAME}-${VERSION}/bundle-${VERSION}.css"
......
......@@ -7,19 +7,19 @@
"private": true,
"dependencies": {},
"devDependencies": {
"@babel/core": "^7.12.8",
"@babel/core": "^7.12.10",
"@babel/plugin-proposal-object-rest-spread": "^7.10.1",
"@babel/plugin-transform-react-jsx": "^7.12.7",
"@babel/preset-env": "^7.12.7",
"@babel/preset-react": "^7.12.7",
"@babel/plugin-transform-react-jsx": "^7.12.11",
"@babel/preset-env": "^7.12.11",
"@babel/preset-react": "^7.12.10",
"babelify": "^10.0.0",
"budo": "^11.6.3",
"bulma": "0.9",
"prop-types": "^15.5.8",
"react": "^17.0.1",
"react": "^18.2.0",
"react-collapsible": "^2.8.1",
"react-dom": "^17.0.1",
"terser": "^5.5.0"
"react-dom": "^18.2.0",
"terser": "^5.5.1"
},
"browserslist": "> 0.25%, not dead"
}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
role="img"
viewBox="-3.29 29.96 14.840857 12.000001"
version="1.1"
id="svg4"
sodipodi:docname="in-toto.svg"
inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20, custom)"
width="14.840857"
height="12"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs8" />
<sodipodi:namedview
id="namedview6"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
showgrid="false"
inkscape:zoom="9.6242015"
inkscape:cx="25.404705"
inkscape:cy="14.702518"
inkscape:window-width="1916"
inkscape:window-height="1060"
inkscape:window-x="0"
inkscape:window-y="18"
inkscape:window-maximized="1"
inkscape:current-layer="svg4"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0" />
<path
d="m 11.405437,32.497306 c 0,0 -0.297326,-0.866189 -0.731522,-1.33095 -0.314258,-0.33638 -0.657577,-0.628783 -1.0630262,-0.830542 l 0.0043,-6.67e-4 c -0.01214,-0.0052 -0.02428,-0.01018 -0.03642,-0.01523 -0.03351,-0.01608 -0.06736,-0.0317 -0.101874,-0.04639 -1.131349,-0.481191 -2.232577,-0.411572 -3.28832,0.230139 a 2.8599687,2.8599687 0 0 0 -0.341432,0.248664 c -0.319852,0.266635 -1.839074,1.3446 -1.584916,1.874201 0.124121,0.258551 0.813788,0.893584 1.100126,0.892634 0.29289,-10e-4 1.473795,-1.091544 1.815452,-1.262144 0.698821,-0.34886 1.524004,-0.35334 2.005717,0.251119 0.498043,0.624951 0.418386,1.525341 -0.187393,2.031578 -0.827694,0.691756 -1.630056,1.415984 -2.49084,2.066138 -0.331225,0.250176 -0.659327,0.356276 -0.969076,0.353337 0.667567,-0.222733 0.616473,-1.513664 0.209407,-2.22336 -0.535035,-0.932826 -1.329962,-1.513103 -2.385504,-1.714666 -1.062228,-0.20284 -2.020517,0.04871 -2.858947,0.729792 -0.721415,0.585936 -1.474016,1.137567 -2.149673,1.775843 -0.426796,0.403129 -0.830473,0.83627 -1.103884,1.314123 -0.487606,0.85241 -0.703808,1.565703 -0.39223,2.58177 0,0 0.38128,0.93633 0.770326,1.330947 0.358218,0.36326 0.690998,0.694082 1.158245,0.892832 1.131344,0.481191 2.232588,0.411569 3.288316,-0.230139 a 2.8599974,2.8599974 0 0 0 0.341436,-0.248666 c 0.319852,-0.266636 1.839074,-1.344596 1.584911,-1.874199 -0.124123,-0.25855 -0.813788,-0.893586 -1.100126,-0.892637 -0.292885,0.001 -1.47379,1.091547 -1.815441,1.262147 -0.698822,0.348854 -1.523994,0.353338 -2.005712,-0.251125 -0.498053,-0.624949 -0.41838,-1.525342 0.187382,-2.031575 0.827699,-0.691761 1.630057,-1.415987 2.490843,-2.066144 0.417644,-0.315438 0.830307,-0.401909 1.207481,-0.329347 a 1.8863898,1.8863898 0 0 0 -0.309482,2.260997 c 0.534968,0.932826 1.287606,1.467845 2.343133,1.669441 l 0.0652,0.0107 c 0.998134,0.148732 1.901994,-0.110446 2.697791,-0.7569 0.721419,-0.585936 1.474027,-1.137567 2.149683,-1.775842 0.4267902,-0.403126 0.8304732,-0.83627 1.1038832,-1.314124 0.487604,-0.852404 0.703802,-1.565701 0.39222,-2.581767 z"
id="path2"
style="stroke-width:0.0421598" />
</svg>
......@@ -12,6 +12,11 @@
<div id="root"></div>
<footer class="footer">
<div class="content has-text-centered">
<noscript>
<h1 class="title">Please enable javascript to use this site</h1>
<p>You may also use the api with rebuildctl from the commandline.</p>
<br>
</noscript>
<p>
<strong>Arch Linux</strong> Reproducible Status by <a href="https://github.com/jelly">Jelle van der Waa</a>. The source code is licensed
<a href="http://opensource.org/licenses/mit-license.php">MIT</a> and available <a href="https://gitlab.archlinux.org/archlinux/rebuilderd-website">here</a>.
......
......@@ -14,7 +14,7 @@ tmux select-pane -t 1
tmux send-keys "make sass-watcher" C-m
tmux split-window -v
tmux select-pane -t 2
tmux send-keys "caddy" C-m
tmux send-keys "caddy run" C-m
# Set default window
tmux select-window -t $SESSION:+1
......
......@@ -11,15 +11,16 @@ class App extends React.Component {
super(props);
this.state = {
fetchFailed: false,
suites: []
suites: [],
dashboard: null,
};
}
render() {
const { fetchFailed, suites } = this.state;
const { fetchFailed, dashboard, suites } = this.state;
return (
<React.Fragment>
<Header fetchFailed={fetchFailed} suites={suites}/>
<Header fetchFailed={fetchFailed} dashboard={dashboard}/>
<Body fetchFailed={fetchFailed} suites={suites}/>
</React.Fragment>
);
......@@ -39,7 +40,24 @@ class App extends React.Component {
}
}
componentDidMount() {
loadDashboard() {
const url = '/api/v0/dashboard';
fetch(url).then((response) => {
if (!response.ok) {
this.setState({fetchFailed: true});
throw new Error(response.statusText);
}
return response.json();
}).then((data) => {
this.setState({dashboard: data});
}).catch((error) => {
console.error(error);
this.setState({fetchFailed: true});
});
}
loadPkgs() {
const url = '/api/v0/pkgs/list';
fetch(url).then((response) => {
......@@ -69,10 +87,17 @@ class App extends React.Component {
this.setState({suites: suiteList});
}).catch((error) => {
console.log(error);
console.error(error);
this.setState({fetchFailed: true});
});
}
componentDidMount() {
this.loadDashboard()
this.loadPkgs()
}
}
module.exports = {App};
// vim: ts=2 sw=2 et:
......@@ -11,6 +11,11 @@ class Body extends React.Component {
return (
<React.Fragment>
{!fetchFailed && !suites.length &&
<section className="section">
<p><b>Loading packages...</b></p>
</section>
}
{ fetchFailed &&
<section className="section">
<div className="tile box has-background-danger">
......
......@@ -6,38 +6,46 @@ import ArchLinuxNavbar from './navbar';
class Header extends React.Component {
calculateSuiteStats(data) {
let good = 0;
let bad = 0;
let unknown = 0;
let good = data['good'];
let bad = data['bad'];
let unknown = data['unknown'];
for (let pkg of data) {
switch (pkg.status) {
case 'GOOD':
good++;
break
case 'BAD':
bad++;
break
case 'UNKWN':
unknown++;
break
}
}
const percentage = (good / data.length * 100).toFixed(1);
const percentage = (good / (good + bad + unknown) * 100).toFixed(1);
return {good, bad, unknown, percentage};
}
// TODO: this is duplciated code from App.js
compareSuites(a, b) {
if (a.name == 'core') {
return -1;
} else if (a.name == 'core' && b.name != 'core') {
return -1;
} else if (a.name == 'extra' && b.name == 'core') {
return 1;
} else if (a.name == 'extra' && b.name != 'core') {
return -1;
} else {
return 1;
}
}
render() {
const {fetchFailed, suites } = this.props;
const {fetchFailed, dashboard, suites } = this.props;
const overall = {good: 0, unknown: 0, bad: 0};
const suitesStats = [];
for (let suite of suites) {
const {good, bad, unknown, percentage} = this.calculateSuiteStats(suite.pkgs);
suitesStats.push({name: suite.name, good, bad, unknown, percentage});
if (dashboard) {
for (const [key, value] of Object.entries(dashboard.suites)) {
const {good, bad, unknown, percentage} = this.calculateSuiteStats(value);
overall['good'] += good;
overall['bad'] += bad;
overall['unknown'] += unknown;
suitesStats.push({name: key, good, bad, unknown, percentage});
}
suitesStats.sort(this.compareSuites);
}
const {good, bad, unknown, percentage} = this.calculateSuiteStats(suites.flatMap(suite => suite.pkgs));
const {good, bad, unknown, percentage} = this.calculateSuiteStats(overall);
const overallStats = {name: 'overall', good, bad, unknown, percentage};
return (
......@@ -47,10 +55,13 @@ class Header extends React.Component {
<div id="status">
<h1 className="title">Reproducible status</h1>
<p>Welcome to the official experimental Arch Linux <a href="https://github.com/kpcyrd/rebuilderd">rebuilderd</a> instance, this page shows the results of verification builds of official Arch Linux packages in the repositories in an effort to be fully reproducible.</p>
<p>For more information read the <a href="https://reproducible-builds.org/">Reproducible Builds website</a> or join the <a href="ircs://chat.freenode.net/archlinux-reproducible">#archlinux-reproducible</a> IRC channel on <a href="https://freenode.net/">Freenode</a>.</p>
<p>For more information read the <a href="https://reproducible-builds.org/">Reproducible Builds website</a> or join the <a href="ircs://irc.libera.chat/archlinux-reproducible">#archlinux-reproducible</a> IRC channel on <a href="https://libera.chat/">Libera Chat</a>.</p>
<br/>
<ul className="repo-summary">
{!fetchFailed && suites.length > 0 &&
{!fetchFailed && !dashboard &&
<p><b>Loading stats...</b></p>
}
{!fetchFailed && dashboard &&
<li key="overall">Arch Linux is <span className="has-text-weight-bold">{ overallStats.percentage }%</span> reproducible with <span className="bad has-text-weight-bold">{ overallStats.bad } bad</span> <span className="unknown has-text-weight-bold">{ overallStats.unknown } unknown</span> and <span className="good has-text-weight-bold">{ overallStats.good } good</span> packages.</li>
}
{!fetchFailed && suitesStats.map(function(repo, index) {
......@@ -65,3 +76,5 @@ class Header extends React.Component {
}
module.exports = {Header};
// vim: ts=2 sw=2 et:
......@@ -4,28 +4,35 @@ const React = require('react');
import Collapsible from 'react-collapsible'
function StatusSection(props) {
const isOpen = props.open;
const isOpen = props.open || false;
const content = (
<ul>
{props.pkgs.map(function(pkg) {
let url=`https://www.archlinux.org/packages/${pkg.suite}/${pkg.architecture}/${pkg.name}`;
const url=`https://www.archlinux.org/packages/${pkg.suite}/${pkg.architecture}/${pkg.name}`;
let links='';
if (pkg.build_id) {
let build_log_url=`/api/v0/builds/${pkg.build_id}/log`;
let diffoscope_url=`/api/v0/builds/${pkg.build_id}/diffoscope`;
links=<span className="noselect"> <a href={build_log_url} title="build log"><img src="icons/note-16.svg" className="icon" /></a> <a href={diffoscope_url} title="diffoscope"><img src="icons/search-16.svg" className="icon" /></a></span>;
const build_log_url=`/api/v0/builds/${pkg.build_id}/log`;
const build_log_link=<a href={build_log_url} target="_blank noreferrer" title="build log"><img src="icons/note-16.svg" className="icon" /></a>;
let diffoscope_link='';
let attestation_link='';
if (pkg.has_diffoscope) {
const diffoscope_url=`/api/v0/builds/${pkg.build_id}/diffoscope`;
diffoscope_link=<a href={diffoscope_url} target="_blank noreferrer" title="diffoscope"><img src="icons/search-16.svg" className="icon" /></a>;
}
if (pkg.has_attestation) {
const attestation_url=`/api/v0/builds/${pkg.build_id}/attestation`;
attestation_link=<a href={attestation_url} target="_blank noreferrer" title="attestation"><img src="icons/in-toto.svg" className="icon" /></a>;
}
links=<span className="noselect"> {build_log_link} {diffoscope_link} {attestation_link}</span>;
}
return <li key={pkg.name}><p className="subtitle is-6"><a href={url}>{pkg.name} {pkg.version}</a>{links}</p></li>
return <li key={pkg.name}><p className="subtitle is-6"><a href={url} target="_blank noreferrer" >{pkg.name} {pkg.version}</a>{links}</p></li>
})}
</ul>
);
const label = `${props.label} (${props.pkgs.length})`;
return (
<div className={ props.label }>
{ isOpen
? <Collapsible trigger={label} lazyRender open>{ content }</Collapsible>
: <Collapsible trigger={label} lazyRender>{ content }</Collapsible>
}
<Collapsible trigger={label} lazyRender open={isOpen}>{ content }</Collapsible>
</div>
);
}
......
'use strict';
const React = require('react');
const ReactDOM = require('react-dom');
import { createRoot } from 'react-dom/client';
const { App } = require('./App');
ReactDOM.render(<App />, document.getElementById('root'));
const container = document.getElementById('root');
const root = createRoot(container);
root.render(<App tab="home" />);
This diff is collapsed.