[Git][qa/jenkins.debian.net][master] rdn: add all-pull184 setup

Holger Levsen (@holger) gitlab at salsa.debian.org
Sat Sep 6 06:20:24 BST 2025



Holger Levsen pushed to branch master at Debian QA / jenkins.debian.net


Commits:
c1051880 by Holger Levsen at 2025-09-06T07:17:47+02:00
rdn: add all-pull184 setup

Signed-off-by: Holger Levsen <holger at layer-acht.org>

- - - - -


28 changed files:

- bin/djm-rebuildctlwatch
- bin/rebuilderd_graph.sh
- bin/rebuilderd_manual_scheduler.sh
- bin/rebuilderd_pkgsync.sh
- + hosts/ionos16-amd64/etc/rebuilderd-worker/rebuilderd-worker.conf
- hosts/osuosl5-amd64/etc/cron.d/rebuilderd
- hosts/osuosl5-amd64/etc/dehydrated/domains.txt
- hosts/osuosl5-amd64/etc/nginx/nginx.conf
- + hosts/osuosl5-amd64/etc/rebuilderd/rebuilderd-all-pull184.conf
- + hosts/osuosl5-amd64/etc/rebuilderd/rebuilderd-sync-all-pull184.conf
- + hosts/osuosl5-amd64/var/www/html/all-pull184/experimental.html
- + hosts/osuosl5-amd64/var/www/html/all-pull184/forky.html
- + hosts/osuosl5-amd64/var/www/html/all-pull184/index.html
- + hosts/osuosl5-amd64/var/www/html/all-pull184/trixie-backports.html
- + hosts/osuosl5-amd64/var/www/html/all-pull184/trixie-proposed-updates.html
- + hosts/osuosl5-amd64/var/www/html/all-pull184/trixie-security.html
- + hosts/osuosl5-amd64/var/www/html/all-pull184/trixie-updates.html
- + hosts/osuosl5-amd64/var/www/html/all-pull184/trixie.html
- + hosts/osuosl5-amd64/var/www/html/all-pull184/unstable.html
- hosts/osuosl5-amd64/var/www/html/amd64-pull184/experimental.html
- hosts/osuosl5-amd64/var/www/html/amd64-pull184/forky.html
- hosts/osuosl5-amd64/var/www/html/amd64-pull184/trixie-backports.html
- hosts/osuosl5-amd64/var/www/html/amd64-pull184/trixie-proposed-updates.html
- hosts/osuosl5-amd64/var/www/html/amd64-pull184/trixie-security.html
- hosts/osuosl5-amd64/var/www/html/amd64-pull184/trixie-updates.html
- hosts/osuosl5-amd64/var/www/html/amd64-pull184/trixie.html
- hosts/osuosl5-amd64/var/www/html/amd64-pull184/unstable.html
- update_jdn.sh


Changes:

=====================================
bin/djm-rebuildctlwatch
=====================================
@@ -21,6 +21,9 @@ set_globals_for_arch() {
 	REBUILDCTL=/usr/bin/rebuildctl
 	case $1 in
 		all)		PORT=8489 ;;
+		all-pull184)	PORT=8495
+				REBUILDCTL=/usr/local/usr/bin/rebuildctl
+				;;
 		amd64)		PORT=8484 ;;
 		amd64-pull184)	PORT=8494
 				REBUILDCTL=/usr/local/usr/bin/rebuildctl


=====================================
bin/rebuilderd_graph.sh
=====================================
@@ -74,7 +74,7 @@ update_png_api() {
 # main
 #
 case $ARCH in
-	amd64-pull184)	if [ -z "$2" ] ; then
+	*-pull184)	if [ -z "$2" ] ; then
 				echo "need a release too."
 				exit 1
 			fi


=====================================
bin/rebuilderd_manual_scheduler.sh
=====================================
@@ -11,13 +11,17 @@ REBUILDCTL=/usr/bin/rebuildctl
 #
 case $1 in
 	any)		shift
-			for arch in amd64 amd64-pull184 arm64 armel armhf i386 riscv64 ppc64el ; do
+			# needs $release for -pull184
+			for arch in amd64 arm64 armel armhf i386 riscv64 ppc64el ; do
 				echo "Scheduling on arch:any that is $arch now:"
 				$0 $arch $@
 			done
 			;;
 	all)		PORT=8489
 			;;
+	all-pull184)	PORT=8495
+			REBUILDCTL=/usr/local/usr/bin/rebuildctl
+			;;
 	amd64)		PORT=8484
 			;;
 	amd64-pull184)	PORT=8494


=====================================
bin/rebuilderd_pkgsync.sh
=====================================
@@ -15,6 +15,10 @@ PROFILES=main
 case $ARCH in
 	all)		PORT=8489
 			;;
+	all-pull184)	PORT=8495
+			REBUILDCTL=/usr/local/usr/bin/rebuildctl
+			PROFILES="main security"
+			;;
 	amd64)		PORT=8484
 			;;
 	amd64-pull184)	PORT=8494


=====================================
hosts/ionos16-amd64/etc/rebuilderd-worker/rebuilderd-worker.conf
=====================================
@@ -0,0 +1,27 @@
+## The rebuilderd to connect to
+endpoint = "https://reproduce.debian.net/all-pull184"
+## The server would either allowlist our key or require a signup secret
+signup_secret = "INSECURE"
+
+[build]
+#timeout = 86400 # 24 hours
+## Set a maximum build log limit in bytes (default: none).
+## When reaching this limit the log is truncated but the rebuilder backend is *not* terminated.
+max_bytes = 20971520 # 20 MiB ## 10 MiB is upstream default
+## By default build output is forwarded to stdout/stderr.
+## This can be disabled by settings this to true.
+#silent = true
+
+[diffoscope]
+## Generate and attach diffs with diffoscope when rebuilding
+enabled = true
+## Pass additional arguments to diffoscope. Use wisely, some options might not work well.
+#args = ["--max-container-depth", "2", "--fuzzy-threshold", "0"]
+## Set a timeout in seconds after which diffoscope is terminated (default: 3600)
+timeout = 600 # 10 minutes
+## Set a maximum diffoscope output limit in bytes (default: none).
+## When reaching this limit, diffoscope is terminated and the output is truncated.
+max_bytes = 10485760 # 10 MiB
+
+[backend."debian"]
+path = "/etc/rebuilderd-worker/rebuilder-debian.sh"


=====================================
hosts/osuosl5-amd64/etc/cron.d/rebuilderd
=====================================
@@ -1,5 +1,5 @@
 MAILTO=root
 42 */3 * * * rebuilderd for arch in all amd64 arm64 armel armhf i386 ppc64el riscv64 ; do mkdir -p /srv/rebuilderd/$arch/stats/ && /srv/jenkins/bin/rebuilderd_stats.py $arch /srv/rebuilderd/$arch/rebuilderd.db trixie --cache /srv/rebuilderd/$arch/stats/cache.pickle /srv/rebuilderd/$arch/stats/ ; done
-0 */3 * * * rebuilderd for arch in amd64-pull184 ; do for release in trixie trixie-proposed-updates trixie-updates trixie-security trixie-backports forky unstable experimental ; do mkdir -p /srv/rebuilderd/$arch/stats/$release && /srv/jenkins/bin/rebuilderd_stats.py $arch /srv/rebuilderd/$arch/rebuilderd.db $release --cache /srv/rebuilderd/$arch/stats/$release/cache.pickle /srv/rebuilderd/$arch/stats/$release ; /srv/jenkins/bin/rebuilderd_graph.sh $arch $release ; done ; done
+0 */3 * * * rebuilderd for arch in all-pull184 amd64-pull184 ; do for release in trixie trixie-proposed-updates trixie-updates trixie-security trixie-backports forky unstable experimental ; do mkdir -p /srv/rebuilderd/$arch/stats/$release && /srv/jenkins/bin/rebuilderd_stats.py $arch /srv/rebuilderd/$arch/rebuilderd.db $release --cache /srv/rebuilderd/$arch/stats/$release/cache.pickle /srv/rebuilderd/$arch/stats/$release ; /srv/jenkins/bin/rebuilderd_graph.sh $arch $release ; done ; done
 23 0,6,12,18 * * * rebuilderd for arch in all amd64 arm64 armel armhf i386 ppc64el riscv64 ; do /srv/jenkins/bin/rebuilderd_graph.sh $arch ; done
 


=====================================
hosts/osuosl5-amd64/etc/dehydrated/domains.txt
=====================================
@@ -1,4 +1,6 @@
 reproduce.debian.net
+all.reproduce.debian.net
+all-pull184.reproduce.debian.net
 amd64.reproduce.debian.net
 amd64-pull184.reproduce.debian.net
 i386.reproduce.debian.net
@@ -7,4 +9,3 @@ armhf.reproduce.debian.net
 armel.reproduce.debian.net
 riscv64.reproduce.debian.net
 ppc64el.reproduce.debian.net
-all.reproduce.debian.net


=====================================
hosts/osuosl5-amd64/etc/nginx/nginx.conf
=====================================
@@ -16,6 +16,7 @@ http {
         listen          80;
         listen          [::]:80;
         server_name     all.reproduce.debian.net;
+        server_name     all-pull184.reproduce.debian.net;
         server_name     reproduce.debian.net;
         server_name     amd64.reproduce.debian.net;
         server_name     amd64-pull184.reproduce.debian.net;
@@ -74,6 +75,20 @@ http {
             alias /srv/rebuilderd/all/stats/ ;
             disable_symlinks off;
         }
+        # all-pull184
+        location /all-pull184/api/ {
+            proxy_set_header    X-Real-IP          $remote_addr;
+            proxy_pass http://127.0.0.1:8495/api/;
+        }
+        location = /all-pull184/api/v1/builds {
+            client_max_body_size 200M;
+            proxy_set_header    X-Real-IP          $remote_addr;
+            proxy_pass http://127.0.0.1:8495/api/v1/builds;
+        }
+        location /all-pull184/stats/ {
+            alias /srv/rebuilderd/all-pull184/stats/ ;
+            disable_symlinks off;
+        }
         # amd64
         location /amd64/api/ {
             proxy_set_header    X-Real-IP          $remote_addr;
@@ -213,6 +228,31 @@ http {
         }
     }
 
+    server {
+        server_name     all-pull184.reproduce.debian.net;
+        ssi on;
+        root /var/www/html;
+        listen 443 ssl;
+        listen [::]:443 ssl;
+        ssl_certificate /var/lib/dehydrated/certs/all-pull184.reproduce.debian.net/fullchain.pem;
+        ssl_certificate_key /var/lib/dehydrated/certs/all-pull184.reproduce.debian.net/privkey.pem;
+        ssl_session_cache shared:le_nginx_SSL:10m;
+        ssl_session_timeout 1440m;
+        ssl_session_tickets off;
+        ssl_protocols TLSv1.2 TLSv1.3;
+        ssl_prefer_server_ciphers off;
+        ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-C
+        HACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
+        location /.well-known/acme-challenge/ {
+            alias /var/lib/dehydrated/acme-challenges/;
+            disable_symlinks off;
+            autoindex off;
+        }
+        location / {
+            return 301 https://reproduce.debian.net/all-pull184$request_uri;
+        }
+    }
+
     server {
         server_name     amd64.reproduce.debian.net;
         ssi on;


=====================================
hosts/osuosl5-amd64/etc/rebuilderd/rebuilderd-all-pull184.conf
=====================================
@@ -0,0 +1,40 @@
+## Configuration for http daemon
+[http]
+## The address to bind to. This is 127.0.0.1:8484 by default.
+bind_addr = "127.0.0.1:8495"
+## If you use a reverse proxy, use this header instead of the actual connecting ip.
+## Make sure the reverse proxy has filters in place to prevent spoofing issues.
+#real_ip_header = "X-Real-IP"
+## Set a default endpoint for rebuildctl. This is especially useful for the sync timer.
+#endpoint = "http://127.0.0.1:8484"
+
+## A random cookie for administration is generated at startup and written to /var/lib/rebuilderd/auth-cookie
+## You can set this to a fixed value here. Use `pwgen -1s 32` to generate one.
+## rebuildctl is searching for this cookie in ~/.config/rebuilderd.conf, /etc/rebuilderd.conf and
+## /var/lib/rebuilderd/auth-cookie in that order.
+#[auth]
+#cookie = "INSECURE"
+
+## The auth cookie above is only used for the default endpoint.
+## You can use different endpoints with `rebuildctl -H https://rebuilder.example.com status`,
+## In that case you need to configure a section below if you want to attach a cookie.
+#[endpoints."https://rebuilder.example.com"]
+#cookie = "INSECURE"
+
+## IMPORTANT: in production, make sure either `authorized_workers` or `signup_secret` is configured.
+[worker]
+## If we have a fixed set of workers we can allow-list the keys here.
+#authorized_workers = ["key1", "key2"]
+## If we want to spawn new workers dynamically we can configure a sign up secret below.
+## Use `pwgen -1s 32` to generate one.
+signup_secret = "INSECURE"
+
+#[schedule]
+## Configure the delay to automatically retry failed rebuilds in hours. The
+## default is 24h, this base is multiplied with the number of rebuilds, so the
+## first retry would happen after 24h, the second retry would happen 48h after the
+## first retry and the third retry would happen 72h after the second retry. There
+## is no upper limit of retries, if you can't afford frequent retries it's
+## recommended to set this to a high value like 168 (1 week) or higher.
+## Successful rebuilds are not retried.
+retry_delay_base = 124800  # 100 years


=====================================
hosts/osuosl5-amd64/etc/rebuilderd/rebuilderd-sync-all-pull184.conf
=====================================
@@ -0,0 +1,15 @@
+[profile."debian-main"]
+distro = "debian"
+components = [ "main", "non-free-firmware" ]
+architectures = ["all"]
+releases = ["trixie", "trixie-backports", "trixie-proposed-updates", "trixie-updates", "forky", "unstable", "experimental"]
+source = "http://deb.debian.org/debian"
+#excludes = ["tensorflow*"]
+
+[profile."debian-security"]
+distro = "debian"
+components = [ "main", "non-free-firmware" ]
+architectures = ["all"]
+releases = ["trixie-security"]
+source = "http://security.debian.org/"
+


=====================================
hosts/osuosl5-amd64/var/www/html/all-pull184/experimental.html
=====================================
@@ -0,0 +1,239 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8">
+        <title>
+		reproduce.debian.net/all-pull184 - experimental (arch:all)
+        </title>
+        <style>
+        body {
+            font-family: sans-serif;
+            font-size: 18pt;
+        }
+        h1 {
+            font-size: 24pt;
+        }
+        h3 {
+            font-size: 18pt;
+        }
+
+        #search-results {
+            margin: 18pt 0;
+        }
+
+        pre {
+            margin: 0;
+        }
+
+        img {
+            vertical-align: middle;
+            max-width: 1920;
+            width: 50%;
+        }
+
+        #search-results pre {
+            margin: 12pt 0;
+        }
+
+        .status {
+            font-weight: bold;
+        }
+
+        .good {
+            color: green;
+        }
+
+        .bad {
+            color: red;
+        }
+
+        .unknown {
+            color: #957fff;
+        }
+
+        footer {
+            font-size: 12pt;
+        }
+        </style>
+        <script>
+        document.addEventListener('DOMContentLoaded', function() {
+            // package search
+            function spanWith(text) {
+                let s = document.createElement('span');
+                s.textContent = text;
+                return s;
+            }
+
+            function linkTo(href, text) {
+                let a = document.createElement('a');
+                a.href = href;
+                a.textContent = text;
+                return a;
+            }
+
+            function searchPkgs(query) {
+                let div = document.getElementById('search-results');
+                let url = '/all-pull184/api/v1/packages/binary?' + new URLSearchParams({
+                    name: query,
+                    distro: 'debian',
+		    release: 'experimental',
+                });
+                fetch(url)
+                    .then(response => response.json())
+                    .then(data => {
+                        // clear children
+                        div.innerHTML = '';
+                        let result = data['records'];
+
+                        result.map(pkg => {
+                            let build_id = pkg.build_id;
+                            let r = document.createElement('pre');
+
+                            r.appendChild(spanWith('['));
+                            let status = pkg['status'];
+                            let statusSpan = spanWith(status);
+                            statusSpan.className += ' status';
+                            if (status == 'GOOD') {
+                                statusSpan.className += ' good';
+                            } else if (status == 'BAD') {
+                                statusSpan.className += ' bad';
+                            } else {
+                                statusSpan.className += ' unknown';
+                            }
+                            r.appendChild(statusSpan);
+                            r.appendChild(spanWith(`] ${pkg['name']} ${pkg['version']}\t\t`));
+
+                            if (build_id) {
+                                r.appendChild(spanWith(' ['));
+                                r.appendChild(linkTo(`/all-pull184/api/v1/builds/${build_id}/log`, 'log'));
+                                r.appendChild(spanWith(']'));
+                            }
+
+                            if (pkg.has_attestation) {
+                                r.appendChild(spanWith(' ['));
+                                r.appendChild(linkTo(`/all-pull184/api/v1/builds/${build_id}/attestation`, 'attestation'));
+                                r.appendChild(spanWith(']'));
+                            }
+
+                            if (pkg.has_diffoscope) {
+                                r.appendChild(spanWith(' ['));
+                                r.appendChild(linkTo(`/all-pull184/api/v1/builds/${build_id}/diffoscope`, 'diffoscope'));
+                                r.appendChild(spanWith(']'));
+                            }
+
+                            div.appendChild(r);
+                        });
+                    });
+            }
+
+            if (location.hash) {
+                searchPkgs(location.hash.substr(1));
+            }
+
+            document.getElementById('search').addEventListener('submit', function(e) {
+                e.preventDefault();
+                let query = document.getElementById('search-query').value;
+                location.href = `#${query}`;
+                searchPkgs(query);
+            });
+
+            // display stats
+            function updateStats(data) {
+                let div = document.getElementById('stats');
+                // clear children
+                div.innerHTML = '';
+                // add rows
+                data.map(row => {
+                    let r = document.createElement('pre');
+                    let key = row[0] + ': ';
+                    r.textContent = key.padEnd(25) + row[1];
+                    div.appendChild(r);
+                });
+            }
+
+            function fetchStats() {
+                fetch('/all-pull184/api/v1/dashboard?release=experimental')
+                    .then(response => response.json())
+                    .then(data => {
+                        let div = document.getElementById('stats');
+
+                        let good = data['rebuilds']['good'];
+                        let bad = data['rebuilds']['bad'];
+                        let fail = data['rebuilds']['fail'];
+                        let unknown = data['rebuilds']['unknown'];
+
+                        let running = data['jobs']['running'];
+                        let available = data['jobs']['available'];
+                        let pending = data['jobs']['pending'];
+
+                        updateStats([
+                            ['reproduced', (100 / (good + bad + fail) * good).toFixed(2) + '%'],
+                            ['good', good],
+                            ['bad', bad],
+                            ['fail', fail],
+                            ['unknown', unknown],
+                            ['build progress', (100 / (good + bad + fail + unknown) * (good + bad + fail)).toFixed(2) + '%'],
+                            ['jobs running', running],
+                            ['jobs available', available],
+                            ['jobs pending', pending],
+                        ]);
+                    });
+            }
+
+            setInterval(fetchStats, 60 * 1000);
+            fetchStats();
+        });
+        </script>
+    </head>
+    <body>
+        <h1>
+		<a href="https://reproduce.debian.net">reproduce</a>.debian.net/<a href="https://all-pull184.reproduce.debian.net">all-pull184</a>
+ </h1>
+	<h3>
+		running https://github.com/kpcyrd/rebuilderd/pull/184
+	</h3>
+        <a href="stats/experimental/rb.png"><img src="stats/experimental/rb.png" align="right"></a>
+        <h3>
+	experimental,
+	<a href="https://all-pull184.reproduce.debian.net/unstable.html">unstable</a>,
+	<a href="https://all-pull184.reproduce.debian.net/forky.html">forky</a>,
+	<a href="https://all-pull184.reproduce.debian.net/trixie.html">trixie</a>,
+	<a href="https://all-pull184.reproduce.debian.net/trixie-security.html">trixie-security</a>,
+	<a href="https://all-pull184.reproduce.debian.net/trixie-updates.html">trixie-updates</a>,
+	<a href="https://all-pull184.reproduce.debian.net/trixie-proposed-updates.html">trixie-proposed-updates</a>,
+	<a href="https://all-pull184.reproduce.debian.net/trixie-backports.html">trixie-backports</a>,
+        (arch:all, <a href="https://amd64-pull184.reproduce.debian.net/forky.html">(arch:amd64)</a>)
+        </h3>
+        <code>
+		experimental (arch:all) main+non-free-firmware
+        </code>
+
+        <div id="stats">Loading stats...</div>
+
+        <div>
+            <h3>Binary package search</h3>
+            <form id="search">
+                <input type="text" id="search-query" placeholder="2ping">
+                <input type="submit" value="Search">
+            </form>
+        </div>
+        <div id="search-results">
+        </div>
+
+	<footer>
+	    <br/>
+	    <a href="stats/experimental">Statistics about BAD packages</a> on all/experimental.
+	    <br/>
+	<hr/>
+            pew pew, <a href="https://github.com/kpcyrd/rebuilderd">rebuilderd</a> using <a href="https://tracker.debian.org/pkg/devscripts">debrebuild</a> to reproduce what Debian distributes via <code><a href="https://ftp.debian.org/debian/dists/">ftp.debian.org</a></code>. ♥️
+	<br/>
+	    <small>
+		<a href="https://reproduce.debian.net/">This setup</a> is in its infancy, even though by now everything is in trixie. Still, please don't consider any URLs as stable here, and more to the point, especially don't take any numbers here seriously, unless...!?!
+		<br/>Oh, and in case you are wondering why we are doing this, then hopefully the <a href="https://reproducible-builds.org">Reproducible Builds website</a> will explain why this is useful.
+		<!--#config timefmt="%Y-%m-%d" --><br/>Static content last modified: <!--#echo var="date_gmt" -->
+		</br>
+		contact: IRC preferred: #debian-reproducible on OFTC or mail to holger at d.o
+	    </small>
+        </footer>
+    </body>
+</html>


=====================================
hosts/osuosl5-amd64/var/www/html/all-pull184/forky.html
=====================================
@@ -0,0 +1,239 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8">
+        <title>
+		reproduce.debian.net/all-pull184 - forky (arch:all)
+        </title>
+        <style>
+        body {
+            font-family: sans-serif;
+            font-size: 18pt;
+        }
+        h1 {
+            font-size: 24pt;
+        }
+        h3 {
+            font-size: 18pt;
+        }
+
+        #search-results {
+            margin: 18pt 0;
+        }
+
+        pre {
+            margin: 0;
+        }
+
+        img {
+            vertical-align: middle;
+            max-width: 1920;
+            width: 50%;
+        }
+
+        #search-results pre {
+            margin: 12pt 0;
+        }
+
+        .status {
+            font-weight: bold;
+        }
+
+        .good {
+            color: green;
+        }
+
+        .bad {
+            color: red;
+        }
+
+        .unknown {
+            color: #957fff;
+        }
+
+        footer {
+            font-size: 12pt;
+        }
+        </style>
+        <script>
+        document.addEventListener('DOMContentLoaded', function() {
+            // package search
+            function spanWith(text) {
+                let s = document.createElement('span');
+                s.textContent = text;
+                return s;
+            }
+
+            function linkTo(href, text) {
+                let a = document.createElement('a');
+                a.href = href;
+                a.textContent = text;
+                return a;
+            }
+
+            function searchPkgs(query) {
+                let div = document.getElementById('search-results');
+                let url = '/all-pull184/api/v1/packages/binary?' + new URLSearchParams({
+                    name: query,
+                    distro: 'debian',
+                    release: 'forky',
+                });
+                fetch(url)
+                    .then(response => response.json())
+                    .then(data => {
+                        // clear children
+                        div.innerHTML = '';
+                        let result = data['records'];
+
+                        result.map(pkg => {
+                            let build_id = pkg.build_id;
+                            let r = document.createElement('pre');
+
+                            r.appendChild(spanWith('['));
+                            let status = pkg['status'];
+                            let statusSpan = spanWith(status);
+                            statusSpan.className += ' status';
+                            if (status == 'GOOD') {
+                                statusSpan.className += ' good';
+                            } else if (status == 'BAD') {
+                                statusSpan.className += ' bad';
+                            } else {
+                                statusSpan.className += ' unknown';
+                            }
+                            r.appendChild(statusSpan);
+                            r.appendChild(spanWith(`] ${pkg['name']} ${pkg['version']}\t\t`));
+
+                            if (build_id) {
+                                r.appendChild(spanWith(' ['));
+                                r.appendChild(linkTo(`/all-pull184/api/v1/builds/${build_id}/log`, 'log'));
+                                r.appendChild(spanWith(']'));
+                            }
+
+                            if (pkg.has_attestation) {
+                                r.appendChild(spanWith(' ['));
+                                r.appendChild(linkTo(`/all-pull184/api/v1/builds/${build_id}/attestation`, 'attestation'));
+                                r.appendChild(spanWith(']'));
+                            }
+
+                            if (pkg.has_diffoscope) {
+                                r.appendChild(spanWith(' ['));
+                                r.appendChild(linkTo(`/all-pull184/api/v1/builds/${build_id}/diffoscope`, 'diffoscope'));
+                                r.appendChild(spanWith(']'));
+                            }
+
+                            div.appendChild(r);
+                        });
+                    });
+            }
+
+            if (location.hash) {
+                searchPkgs(location.hash.substr(1));
+            }
+
+            document.getElementById('search').addEventListener('submit', function(e) {
+                e.preventDefault();
+                let query = document.getElementById('search-query').value;
+                location.href = `#${query}`;
+                searchPkgs(query);
+            });
+
+            // display stats
+            function updateStats(data) {
+                let div = document.getElementById('stats');
+                // clear children
+                div.innerHTML = '';
+                // add rows
+                data.map(row => {
+                    let r = document.createElement('pre');
+                    let key = row[0] + ': ';
+                    r.textContent = key.padEnd(25) + row[1];
+                    div.appendChild(r);
+                });
+            }
+
+            function fetchStats() {
+                fetch('/all-pull184/api/v1/dashboard?release=forky')
+                    .then(response => response.json())
+                    .then(data => {
+                        let div = document.getElementById('stats');
+
+                        let good = data['rebuilds']['good'];
+                        let bad = data['rebuilds']['bad'];
+                        let fail = data['rebuilds']['fail'];
+                        let unknown = data['rebuilds']['unknown'];
+
+                        let running = data['jobs']['running'];
+                        let available = data['jobs']['available'];
+                        let pending = data['jobs']['pending'];
+
+                        updateStats([
+                            ['reproduced', (100 / (good + bad + fail) * good).toFixed(2) + '%'],
+                            ['good', good],
+                            ['bad', bad],
+                            ['fail', fail],
+                            ['unknown', unknown],
+                            ['build progress', (100 / (good + bad + fail + unknown) * (good + bad + fail)).toFixed(2) + '%'],
+                            ['jobs running', running],
+                            ['jobs available', available],
+                            ['jobs pending', pending],
+                        ]);
+                    });
+            }
+
+            setInterval(fetchStats, 60 * 1000);
+            fetchStats();
+        });
+        </script>
+    </head>
+    <body>
+        <h1>
+		<a href="https://reproduce.debian.net">reproduce</a>.debian.net/<a href="https://all-pull184.reproduce.debian.net">all-pull184</a>
+ </h1>
+	<h3>
+		running https://github.com/kpcyrd/rebuilderd/pull/184
+	</h3>
+        <a href="stats/forky/rb.png"><img src="stats/forky/rb.png" align="right"></a>
+        <h3>
+	<a href="https://all-pull184.reproduce.debian.net/experimental.html">experimental</a>,
+	<a href="https://all-pull184.reproduce.debian.net/unstable.html">unstable</a>,
+	forky,
+	<a href="https://all-pull184.reproduce.debian.net/trixie.html">trixie</a>,
+	<a href="https://all-pull184.reproduce.debian.net/trixie-security.html">trixie-security</a>,
+	<a href="https://all-pull184.reproduce.debian.net/trixie-updates.html">trixie-updates</a>,
+	<a href="https://all-pull184.reproduce.debian.net/trixie-proposed-updates.html">trixie-proposed-updates</a>,
+	<a href="https://all-pull184.reproduce.debian.net/trixie-backports.html">trixie-backports</a>,
+        (arch:all, <a href="https://amd64-pull184.reproduce.debian.net/forky.html">(arch:amd64)</a>)
+        </h3>
+        <code>
+		forky (arch:all) main+non-free-firmware
+        </code>
+
+        <div id="stats">Loading stats...</div>
+
+        <div>
+            <h3>Binary package search</h3>
+            <form id="search">
+                <input type="text" id="search-query" placeholder="2ping">
+                <input type="submit" value="Search">
+            </form>
+        </div>
+        <div id="search-results">
+        </div>
+
+	<footer>
+	    <br/>
+	    <a href="stats/forky">Statistics about BAD packages</a> on all/forky.
+	    <br/>
+	<hr/>
+            pew pew, <a href="https://github.com/kpcyrd/rebuilderd">rebuilderd</a> using <a href="https://tracker.debian.org/pkg/devscripts">debrebuild</a> to reproduce what Debian distributes via <code><a href="https://ftp.debian.org/debian/dists/">ftp.debian.org</a></code>. ♥️
+	<br/>
+	    <small>
+		<a href="https://reproduce.debian.net/">This setup</a> is in its infancy, even though by now everything is in trixie. Still, please don't consider any URLs as stable here, and more to the point, especially don't take any numbers here seriously, unless...!?!
+		<br/>Oh, and in case you are wondering why we are doing this, then hopefully the <a href="https://reproducible-builds.org">Reproducible Builds website</a> will explain why this is useful.
+		<!--#config timefmt="%Y-%m-%d" --><br/>Static content last modified: <!--#echo var="date_gmt" -->
+		</br>
+		contact: IRC preferred: #debian-reproducible on OFTC or mail to holger at d.o
+	    </small>
+        </footer>
+    </body>
+</html>


=====================================
hosts/osuosl5-amd64/var/www/html/all-pull184/index.html
=====================================
@@ -0,0 +1,239 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8">
+        <title>
+		reproduce.debian.net/all-pull184 - forky (arch:all)
+        </title>
+        <style>
+        body {
+            font-family: sans-serif;
+            font-size: 18pt;
+        }
+        h1 {
+            font-size: 24pt;
+        }
+        h3 {
+            font-size: 18pt;
+        }
+
+        #search-results {
+            margin: 18pt 0;
+        }
+
+        pre {
+            margin: 0;
+        }
+
+        img {
+            vertical-align: middle;
+            max-width: 1920;
+            width: 50%;
+        }
+
+        #search-results pre {
+            margin: 12pt 0;
+        }
+
+        .status {
+            font-weight: bold;
+        }
+
+        .good {
+            color: green;
+        }
+
+        .bad {
+            color: red;
+        }
+
+        .unknown {
+            color: #957fff;
+        }
+
+        footer {
+            font-size: 12pt;
+        }
+        </style>
+        <script>
+        document.addEventListener('DOMContentLoaded', function() {
+            // package search
+            function spanWith(text) {
+                let s = document.createElement('span');
+                s.textContent = text;
+                return s;
+            }
+
+            function linkTo(href, text) {
+                let a = document.createElement('a');
+                a.href = href;
+                a.textContent = text;
+                return a;
+            }
+
+            function searchPkgs(query) {
+                let div = document.getElementById('search-results');
+                let url = '/all-pull184/api/v1/packages/binary?' + new URLSearchParams({
+                    name: query,
+                    distro: 'debian',
+                    release: 'forky',
+                });
+                fetch(url)
+                    .then(response => response.json())
+                    .then(data => {
+                        // clear children
+                        div.innerHTML = '';
+                        let result = data['records'];
+
+                        result.map(pkg => {
+                            let build_id = pkg.build_id;
+                            let r = document.createElement('pre');
+
+                            r.appendChild(spanWith('['));
+                            let status = pkg['status'];
+                            let statusSpan = spanWith(status);
+                            statusSpan.className += ' status';
+                            if (status == 'GOOD') {
+                                statusSpan.className += ' good';
+                            } else if (status == 'BAD') {
+                                statusSpan.className += ' bad';
+                            } else {
+                                statusSpan.className += ' unknown';
+                            }
+                            r.appendChild(statusSpan);
+                            r.appendChild(spanWith(`] ${pkg['name']} ${pkg['version']}\t\t`));
+
+                            if (build_id) {
+                                r.appendChild(spanWith(' ['));
+                                r.appendChild(linkTo(`/all-pull184/api/v1/builds/${build_id}/log`, 'log'));
+                                r.appendChild(spanWith(']'));
+                            }
+
+                            if (pkg.has_attestation) {
+                                r.appendChild(spanWith(' ['));
+                                r.appendChild(linkTo(`/all-pull184/api/v1/builds/${build_id}/attestation`, 'attestation'));
+                                r.appendChild(spanWith(']'));
+                            }
+
+                            if (pkg.has_diffoscope) {
+                                r.appendChild(spanWith(' ['));
+                                r.appendChild(linkTo(`/all-pull184/api/v1/builds/${build_id}/diffoscope`, 'diffoscope'));
+                                r.appendChild(spanWith(']'));
+                            }
+
+                            div.appendChild(r);
+                        });
+                    });
+            }
+
+            if (location.hash) {
+                searchPkgs(location.hash.substr(1));
+            }
+
+            document.getElementById('search').addEventListener('submit', function(e) {
+                e.preventDefault();
+                let query = document.getElementById('search-query').value;
+                location.href = `#${query}`;
+                searchPkgs(query);
+            });
+
+            // display stats
+            function updateStats(data) {
+                let div = document.getElementById('stats');
+                // clear children
+                div.innerHTML = '';
+                // add rows
+                data.map(row => {
+                    let r = document.createElement('pre');
+                    let key = row[0] + ': ';
+                    r.textContent = key.padEnd(25) + row[1];
+                    div.appendChild(r);
+                });
+            }
+
+            function fetchStats() {
+                fetch('/all-pull184/api/v1/dashboard?release=forky')
+                    .then(response => response.json())
+                    .then(data => {
+                        let div = document.getElementById('stats');
+
+                        let good = data['rebuilds']['good'];
+                        let bad = data['rebuilds']['bad'];
+                        let fail = data['rebuilds']['fail'];
+                        let unknown = data['rebuilds']['unknown'];
+
+                        let running = data['jobs']['running'];
+                        let available = data['jobs']['available'];
+                        let pending = data['jobs']['pending'];
+
+                        updateStats([
+                            ['reproduced', (100 / (good + bad + fail) * good).toFixed(2) + '%'],
+                            ['good', good],
+                            ['bad', bad],
+                            ['fail', fail],
+                            ['unknown', unknown],
+                            ['build progress', (100 / (good + bad + fail + unknown) * (good + bad + fail)).toFixed(2) + '%'],
+                            ['jobs running', running],
+                            ['jobs available', available],
+                            ['jobs pending', pending],
+                        ]);
+                    });
+            }
+
+            setInterval(fetchStats, 60 * 1000);
+            fetchStats();
+        });
+        </script>
+    </head>
+    <body>
+        <h1>
+		<a href="https://reproduce.debian.net">reproduce</a>.debian.net/<a href="https://all-pull184.reproduce.debian.net">all-pull184</a>
+ </h1>
+	<h3>
+		running https://github.com/kpcyrd/rebuilderd/pull/184
+	</h3>
+        <a href="stats/forky/rb.png"><img src="stats/forky/rb.png" align="right"></a>
+        <h3>
+	<a href="https://all-pull184.reproduce.debian.net/experimental.html">experimental</a>,
+	<a href="https://all-pull184.reproduce.debian.net/unstable.html">unstable</a>,
+	forky,
+	<a href="https://all-pull184.reproduce.debian.net/trixie.html">trixie</a>,
+	<a href="https://all-pull184.reproduce.debian.net/trixie-security.html">trixie-security</a>,
+	<a href="https://all-pull184.reproduce.debian.net/trixie-updates.html">trixie-updates</a>,
+	<a href="https://all-pull184.reproduce.debian.net/trixie-proposed-updates.html">trixie-proposed-updates</a>,
+	<a href="https://all-pull184.reproduce.debian.net/trixie-backports.html">trixie-backports</a>,
+        (arch:all, <a href="https://amd64-pull184.reproduce.debian.net/forky.html">arch:amd64</a>)
+        </h3>
+        <code>
+		forky (arch:all) main+non-free-firmware
+        </code>
+
+        <div id="stats">Loading stats...</div>
+
+        <div>
+            <h3>Binary package search</h3>
+            <form id="search">
+                <input type="text" id="search-query" placeholder="2ping">
+                <input type="submit" value="Search">
+            </form>
+        </div>
+        <div id="search-results">
+        </div>
+
+	<footer>
+	    <br/>
+	    <a href="stats/forky">Statistics about BAD packages</a> on all/forky.
+	    <br/>
+	<hr/>
+            pew pew, <a href="https://github.com/kpcyrd/rebuilderd">rebuilderd</a> using <a href="https://tracker.debian.org/pkg/devscripts">debrebuild</a> to reproduce what Debian distributes via <code><a href="https://ftp.debian.org/debian/dists/">ftp.debian.org</a></code>. ♥️
+	<br/>
+	    <small>
+		<a href="https://reproduce.debian.net/">This setup</a> is in its infancy, even though by now everything is in trixie. Still, please don't consider any URLs as stable here, and more to the point, especially don't take any numbers here seriously, unless...!?!
+		<br/>Oh, and in case you are wondering why we are doing this, then hopefully the <a href="https://reproducible-builds.org">Reproducible Builds website</a> will explain why this is useful.
+		<!--#config timefmt="%Y-%m-%d" --><br/>Static content last modified: <!--#echo var="date_gmt" -->
+		</br>
+		contact: IRC preferred: #debian-reproducible on OFTC or mail to holger at d.o
+	    </small>
+        </footer>
+    </body>
+</html>


=====================================
hosts/osuosl5-amd64/var/www/html/all-pull184/trixie-backports.html
=====================================
@@ -0,0 +1,239 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8">
+        <title>
+		reproduce.debian.net/all-pull184 - trixie-backports (arch:all)
+        </title>
+        <style>
+        body {
+            font-family: sans-serif;
+            font-size: 18pt;
+        }
+        h1 {
+            font-size: 24pt;
+        }
+        h3 {
+            font-size: 18pt;
+        }
+
+        #search-results {
+            margin: 18pt 0;
+        }
+
+        pre {
+            margin: 0;
+        }
+
+        img {
+            vertical-align: middle;
+            max-width: 1920;
+            width: 50%;
+        }
+
+        #search-results pre {
+            margin: 12pt 0;
+        }
+
+        .status {
+            font-weight: bold;
+        }
+
+        .good {
+            color: green;
+        }
+
+        .bad {
+            color: red;
+        }
+
+        .unknown {
+            color: #957fff;
+        }
+
+        footer {
+            font-size: 12pt;
+        }
+        </style>
+        <script>
+        document.addEventListener('DOMContentLoaded', function() {
+            // package search
+            function spanWith(text) {
+                let s = document.createElement('span');
+                s.textContent = text;
+                return s;
+            }
+
+            function linkTo(href, text) {
+                let a = document.createElement('a');
+                a.href = href;
+                a.textContent = text;
+                return a;
+            }
+
+            function searchPkgs(query) {
+                let div = document.getElementById('search-results');
+                let url = '/all-pull184/api/v1/packages/binary?' + new URLSearchParams({
+                    name: query,
+                    distro: 'debian',
+		    release: 'trixie-backports',
+                });
+                fetch(url)
+                    .then(response => response.json())
+                    .then(data => {
+                        // clear children
+                        div.innerHTML = '';
+                        let result = data['records'];
+
+                        result.map(pkg => {
+                            let build_id = pkg.build_id;
+                            let r = document.createElement('pre');
+
+                            r.appendChild(spanWith('['));
+                            let status = pkg['status'];
+                            let statusSpan = spanWith(status);
+                            statusSpan.className += ' status';
+                            if (status == 'GOOD') {
+                                statusSpan.className += ' good';
+                            } else if (status == 'BAD') {
+                                statusSpan.className += ' bad';
+                            } else {
+                                statusSpan.className += ' unknown';
+                            }
+                            r.appendChild(statusSpan);
+                            r.appendChild(spanWith(`] ${pkg['name']} ${pkg['version']}\t\t`));
+
+                            if (build_id) {
+                                r.appendChild(spanWith(' ['));
+                                r.appendChild(linkTo(`/all-pull184/api/v1/builds/${build_id}/log`, 'log'));
+                                r.appendChild(spanWith(']'));
+                            }
+
+                            if (pkg.has_attestation) {
+                                r.appendChild(spanWith(' ['));
+                                r.appendChild(linkTo(`/all-pull184/api/v1/builds/${build_id}/attestation`, 'attestation'));
+                                r.appendChild(spanWith(']'));
+                            }
+
+                            if (pkg.has_diffoscope) {
+                                r.appendChild(spanWith(' ['));
+                                r.appendChild(linkTo(`/all-pull184/api/v1/builds/${build_id}/diffoscope`, 'diffoscope'));
+                                r.appendChild(spanWith(']'));
+                            }
+
+                            div.appendChild(r);
+                        });
+                    });
+            }
+
+            if (location.hash) {
+                searchPkgs(location.hash.substr(1));
+            }
+
+            document.getElementById('search').addEventListener('submit', function(e) {
+                e.preventDefault();
+                let query = document.getElementById('search-query').value;
+                location.href = `#${query}`;
+                searchPkgs(query);
+            });
+
+            // display stats
+            function updateStats(data) {
+                let div = document.getElementById('stats');
+                // clear children
+                div.innerHTML = '';
+                // add rows
+                data.map(row => {
+                    let r = document.createElement('pre');
+                    let key = row[0] + ': ';
+                    r.textContent = key.padEnd(25) + row[1];
+                    div.appendChild(r);
+                });
+            }
+
+            function fetchStats() {
+                fetch('/all-pull184/api/v1/dashboard?release=trixie-backports')
+                    .then(response => response.json())
+                    .then(data => {
+                        let div = document.getElementById('stats');
+
+                        let good = data['rebuilds']['good'];
+                        let bad = data['rebuilds']['bad'];
+                        let fail = data['rebuilds']['fail'];
+                        let unknown = data['rebuilds']['unknown'];
+
+                        let running = data['jobs']['running'];
+                        let available = data['jobs']['available'];
+                        let pending = data['jobs']['pending'];
+
+                        updateStats([
+                            ['reproduced', (100 / (good + bad + fail) * good).toFixed(2) + '%'],
+                            ['good', good],
+                            ['bad', bad],
+                            ['fail', fail],
+                            ['unknown', unknown],
+                            ['build progress', (100 / (good + bad + fail + unknown) * (good + bad + fail)).toFixed(2) + '%'],
+                            ['jobs running', running],
+                            ['jobs available', available],
+                            ['jobs pending', pending],
+                        ]);
+                    });
+            }
+
+            setInterval(fetchStats, 60 * 1000);
+            fetchStats();
+        });
+        </script>
+    </head>
+    <body>
+        <h1>
+		<a href="https://reproduce.debian.net">reproduce</a>.debian.net/<a href="https://all-pull184.reproduce.debian.net">all-pull184</a>
+ </h1>
+	<h3>
+		running https://github.com/kpcyrd/rebuilderd/pull/184
+	</h3>
+        <a href="stats/trixie-backports/rb.png"><img src="stats/trixie-backports/rb.png" align="right"></a>
+        <h3>
+	<a href="https://all-pull184.reproduce.debian.net/experimental.html">experimental</a>,
+	<a href="https://all-pull184.reproduce.debian.net/unstable.html">unstable</a>,
+	<a href="https://all-pull184.reproduce.debian.net/forky.html">forky</a>,
+	<a href="https://all-pull184.reproduce.debian.net/trixie.html">trixie</a>,
+	<a href="https://all-pull184.reproduce.debian.net/trixie-security.html">trixie-security</a>,
+	<a href="https://all-pull184.reproduce.debian.net/trixie-updates.html">trixie-updates</a>,
+	<a href="https://all-pull184.reproduce.debian.net/trixie-proposed-updates.html">trixie-proposed-updates</a>,
+	trixie-backports,
+        (arch:all, <a href="https://amd64-pull184.reproduce.debian.net/forky.html">arch:amd64</a>)
+        </h3>
+        <code>
+		trixie-backports (arch:all) main+non-free-firmware
+        </code>
+
+        <div id="stats">Loading stats...</div>
+
+        <div>
+            <h3>Binary package search</h3>
+            <form id="search">
+                <input type="text" id="search-query" placeholder="2ping">
+                <input type="submit" value="Search">
+            </form>
+        </div>
+        <div id="search-results">
+        </div>
+
+	<footer>
+	    <br/>
+	    <a href="stats/trixie-backports">Statistics about BAD packages</a> on all/trixie-backports.
+	    <br/>
+	<hr/>
+            pew pew, <a href="https://github.com/kpcyrd/rebuilderd">rebuilderd</a> using <a href="https://tracker.debian.org/pkg/devscripts">debrebuild</a> to reproduce what Debian distributes via <code><a href="https://ftp.debian.org/debian/dists/">ftp.debian.org</a></code>. ♥️
+	<br/>
+	    <small>
+		<a href="https://reproduce.debian.net/">This setup</a> is in its infancy, even though by now everything is in trixie. Still, please don't consider any URLs as stable here, and more to the point, especially don't take any numbers here seriously, unless...!?!
+		<br/>Oh, and in case you are wondering why we are doing this, then hopefully the <a href="https://reproducible-builds.org">Reproducible Builds website</a> will explain why this is useful.
+		<!--#config timefmt="%Y-%m-%d" --><br/>Static content last modified: <!--#echo var="date_gmt" -->
+		</br>
+		contact: IRC preferred: #debian-reproducible on OFTC or mail to holger at d.o
+	    </small>
+        </footer>
+    </body>
+</html>


=====================================
hosts/osuosl5-amd64/var/www/html/all-pull184/trixie-proposed-updates.html
=====================================
@@ -0,0 +1,239 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8">
+        <title>
+		reproduce.debian.net/all-pull184 - trixie-proposed-updates (arch:all)
+        </title>
+        <style>
+        body {
+            font-family: sans-serif;
+            font-size: 18pt;
+        }
+        h1 {
+            font-size: 24pt;
+        }
+        h3 {
+            font-size: 18pt;
+        }
+
+        #search-results {
+            margin: 18pt 0;
+        }
+
+        pre {
+            margin: 0;
+        }
+
+        img {
+            vertical-align: middle;
+            max-width: 1920;
+            width: 50%;
+        }
+
+        #search-results pre {
+            margin: 12pt 0;
+        }
+
+        .status {
+            font-weight: bold;
+        }
+
+        .good {
+            color: green;
+        }
+
+        .bad {
+            color: red;
+        }
+
+        .unknown {
+            color: #957fff;
+        }
+
+        footer {
+            font-size: 12pt;
+        }
+        </style>
+        <script>
+        document.addEventListener('DOMContentLoaded', function() {
+            // package search
+            function spanWith(text) {
+                let s = document.createElement('span');
+                s.textContent = text;
+                return s;
+            }
+
+            function linkTo(href, text) {
+                let a = document.createElement('a');
+                a.href = href;
+                a.textContent = text;
+                return a;
+            }
+
+            function searchPkgs(query) {
+                let div = document.getElementById('search-results');
+                let url = '/all-pull184/api/v1/packages/binary?' + new URLSearchParams({
+                    name: query,
+                    distro: 'debian',
+		    release: 'trixie-proposed-updates',
+                });
+                fetch(url)
+                    .then(response => response.json())
+                    .then(data => {
+                        // clear children
+                        div.innerHTML = '';
+                        let result = data['records'];
+
+                        result.map(pkg => {
+                            let build_id = pkg.build_id;
+                            let r = document.createElement('pre');
+
+                            r.appendChild(spanWith('['));
+                            let status = pkg['status'];
+                            let statusSpan = spanWith(status);
+                            statusSpan.className += ' status';
+                            if (status == 'GOOD') {
+                                statusSpan.className += ' good';
+                            } else if (status == 'BAD') {
+                                statusSpan.className += ' bad';
+                            } else {
+                                statusSpan.className += ' unknown';
+                            }
+                            r.appendChild(statusSpan);
+                            r.appendChild(spanWith(`] ${pkg['name']} ${pkg['version']}\t\t`));
+
+                            if (build_id) {
+                                r.appendChild(spanWith(' ['));
+                                r.appendChild(linkTo(`/all-pull184/api/v1/builds/${build_id}/log`, 'log'));
+                                r.appendChild(spanWith(']'));
+                            }
+
+                            if (pkg.has_attestation) {
+                                r.appendChild(spanWith(' ['));
+                                r.appendChild(linkTo(`/all-pull184/api/v1/builds/${build_id}/attestation`, 'attestation'));
+                                r.appendChild(spanWith(']'));
+                            }
+
+                            if (pkg.has_diffoscope) {
+                                r.appendChild(spanWith(' ['));
+                                r.appendChild(linkTo(`/all-pull184/api/v1/builds/${build_id}/diffoscope`, 'diffoscope'));
+                                r.appendChild(spanWith(']'));
+                            }
+
+                            div.appendChild(r);
+                        });
+                    });
+            }
+
+            if (location.hash) {
+                searchPkgs(location.hash.substr(1));
+            }
+
+            document.getElementById('search').addEventListener('submit', function(e) {
+                e.preventDefault();
+                let query = document.getElementById('search-query').value;
+                location.href = `#${query}`;
+                searchPkgs(query);
+            });
+
+            // display stats
+            function updateStats(data) {
+                let div = document.getElementById('stats');
+                // clear children
+                div.innerHTML = '';
+                // add rows
+                data.map(row => {
+                    let r = document.createElement('pre');
+                    let key = row[0] + ': ';
+                    r.textContent = key.padEnd(25) + row[1];
+                    div.appendChild(r);
+                });
+            }
+
+            function fetchStats() {
+                fetch('/all-pull184/api/v1/dashboard?release=trixie-proposed-updates')
+                    .then(response => response.json())
+                    .then(data => {
+                        let div = document.getElementById('stats');
+
+                        let good = data['rebuilds']['good'];
+                        let bad = data['rebuilds']['bad'];
+                        let fail = data['rebuilds']['fail'];
+                        let unknown = data['rebuilds']['unknown'];
+
+                        let running = data['jobs']['running'];
+                        let available = data['jobs']['available'];
+                        let pending = data['jobs']['pending'];
+
+                        updateStats([
+                            ['reproduced', (100 / (good + bad + fail) * good).toFixed(2) + '%'],
+                            ['good', good],
+                            ['bad', bad],
+                            ['fail', fail],
+                            ['unknown', unknown],
+                            ['build progress', (100 / (good + bad + fail + unknown) * (good + bad + fail)).toFixed(2) + '%'],
+                            ['jobs running', running],
+                            ['jobs available', available],
+                            ['jobs pending', pending],
+                        ]);
+                    });
+            }
+
+            setInterval(fetchStats, 60 * 1000);
+            fetchStats();
+        });
+        </script>
+    </head>
+    <body>
+        <h1>
+		<a href="https://reproduce.debian.net">reproduce</a>.debian.net/<a href="https://all-pull184.reproduce.debian.net">all-pull184</a>
+ </h1>
+	<h3>
+		running https://github.com/kpcyrd/rebuilderd/pull/184
+	</h3>
+        <a href="stats/trixie-proposed-updates/rb.png"><img src="stats/trixie-proposed-updates/rb.png" align="right"></a>
+        <h3>
+	<a href="https://all-pull184.reproduce.debian.net/experimental.html">experimental</a>,
+	<a href="https://all-pull184.reproduce.debian.net/unstable.html">unstable</a>,
+	<a href="https://all-pull184.reproduce.debian.net/forky.html">forky</a>,
+	<a href="https://all-pull184.reproduce.debian.net/trixie.html">trixie</a>,
+	<a href="https://all-pull184.reproduce.debian.net/trixie-security.html">trixie-security</a>,
+	<a href="https://all-pull184.reproduce.debian.net/trixie-updates.html">trixie-updates</a>,
+	trixie-proposed-updates,
+	<a href="https://all-pull184.reproduce.debian.net/trixie-backports.html">trixie-backports</a>,
+        (arch:all, <a href="https://amd64-pull184.reproduce.debian.net/forky.html">arch:amd64</a>)
+        </h3>
+        <code>
+		trixie-proposed-updates (arch:all) main+non-free-firmware
+        </code>
+
+        <div id="stats">Loading stats...</div>
+
+        <div>
+            <h3>Binary package search</h3>
+            <form id="search">
+                <input type="text" id="search-query" placeholder="2ping">
+                <input type="submit" value="Search">
+            </form>
+        </div>
+        <div id="search-results">
+        </div>
+
+	<footer>
+	    <br/>
+	    <a href="stats/trixie-proposed-updates">Statistics about BAD packages</a> on all/trixie-proposed-updates.
+	    <br/>
+	<hr/>
+            pew pew, <a href="https://github.com/kpcyrd/rebuilderd">rebuilderd</a> using <a href="https://tracker.debian.org/pkg/devscripts">debrebuild</a> to reproduce what Debian distributes via <code><a href="https://ftp.debian.org/debian/dists/">ftp.debian.org</a></code>. ♥️
+	<br/>
+	    <small>
+		<a href="https://reproduce.debian.net/">This setup</a> is in its infancy, even though by now everything is in trixie. Still, please don't consider any URLs as stable here, and more to the point, especially don't take any numbers here seriously, unless...!?!
+		<br/>Oh, and in case you are wondering why we are doing this, then hopefully the <a href="https://reproducible-builds.org">Reproducible Builds website</a> will explain why this is useful.
+		<!--#config timefmt="%Y-%m-%d" --><br/>Static content last modified: <!--#echo var="date_gmt" -->
+		</br>
+		contact: IRC preferred: #debian-reproducible on OFTC or mail to holger at d.o
+	    </small>
+        </footer>
+    </body>
+</html>


=====================================
hosts/osuosl5-amd64/var/www/html/all-pull184/trixie-security.html
=====================================
@@ -0,0 +1,239 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8">
+        <title>
+		reproduce.debian.net/all-pull184 - trixie-security (arch:all)
+        </title>
+        <style>
+        body {
+            font-family: sans-serif;
+            font-size: 18pt;
+        }
+        h1 {
+            font-size: 24pt;
+        }
+        h3 {
+            font-size: 18pt;
+        }
+
+        #search-results {
+            margin: 18pt 0;
+        }
+
+        pre {
+            margin: 0;
+        }
+
+        img {
+            vertical-align: middle;
+            max-width: 1920;
+            width: 50%;
+        }
+
+        #search-results pre {
+            margin: 12pt 0;
+        }
+
+        .status {
+            font-weight: bold;
+        }
+
+        .good {
+            color: green;
+        }
+
+        .bad {
+            color: red;
+        }
+
+        .unknown {
+            color: #957fff;
+        }
+
+        footer {
+            font-size: 12pt;
+        }
+        </style>
+        <script>
+        document.addEventListener('DOMContentLoaded', function() {
+            // package search
+            function spanWith(text) {
+                let s = document.createElement('span');
+                s.textContent = text;
+                return s;
+            }
+
+            function linkTo(href, text) {
+                let a = document.createElement('a');
+                a.href = href;
+                a.textContent = text;
+                return a;
+            }
+
+            function searchPkgs(query) {
+                let div = document.getElementById('search-results');
+                let url = '/all-pull184/api/v1/packages/binary?' + new URLSearchParams({
+                    name: query,
+                    distro: 'debian',
+		    release: 'trixie-security',
+                });
+                fetch(url)
+                    .then(response => response.json())
+                    .then(data => {
+                        // clear children
+                        div.innerHTML = '';
+                        let result = data['records'];
+
+                        result.map(pkg => {
+                            let build_id = pkg.build_id;
+                            let r = document.createElement('pre');
+
+                            r.appendChild(spanWith('['));
+                            let status = pkg['status'];
+                            let statusSpan = spanWith(status);
+                            statusSpan.className += ' status';
+                            if (status == 'GOOD') {
+                                statusSpan.className += ' good';
+                            } else if (status == 'BAD') {
+                                statusSpan.className += ' bad';
+                            } else {
+                                statusSpan.className += ' unknown';
+                            }
+                            r.appendChild(statusSpan);
+                            r.appendChild(spanWith(`] ${pkg['name']} ${pkg['version']}\t\t`));
+
+                            if (build_id) {
+                                r.appendChild(spanWith(' ['));
+                                r.appendChild(linkTo(`/all-pull184/api/v1/builds/${build_id}/log`, 'log'));
+                                r.appendChild(spanWith(']'));
+                            }
+
+                            if (pkg.has_attestation) {
+                                r.appendChild(spanWith(' ['));
+                                r.appendChild(linkTo(`/all-pull184/api/v1/builds/${build_id}/attestation`, 'attestation'));
+                                r.appendChild(spanWith(']'));
+                            }
+
+                            if (pkg.has_diffoscope) {
+                                r.appendChild(spanWith(' ['));
+                                r.appendChild(linkTo(`/all-pull184/api/v1/builds/${build_id}/diffoscope`, 'diffoscope'));
+                                r.appendChild(spanWith(']'));
+                            }
+
+                            div.appendChild(r);
+                        });
+                    });
+            }
+
+            if (location.hash) {
+                searchPkgs(location.hash.substr(1));
+            }
+
+            document.getElementById('search').addEventListener('submit', function(e) {
+                e.preventDefault();
+                let query = document.getElementById('search-query').value;
+                location.href = `#${query}`;
+                searchPkgs(query);
+            });
+
+            // display stats
+            function updateStats(data) {
+                let div = document.getElementById('stats');
+                // clear children
+                div.innerHTML = '';
+                // add rows
+                data.map(row => {
+                    let r = document.createElement('pre');
+                    let key = row[0] + ': ';
+                    r.textContent = key.padEnd(25) + row[1];
+                    div.appendChild(r);
+                });
+            }
+
+            function fetchStats() {
+                fetch('/all-pull184/api/v1/dashboard?release=trixie-security')
+                    .then(response => response.json())
+                    .then(data => {
+                        let div = document.getElementById('stats');
+
+                        let good = data['rebuilds']['good'];
+                        let bad = data['rebuilds']['bad'];
+                        let fail = data['rebuilds']['fail'];
+                        let unknown = data['rebuilds']['unknown'];
+
+                        let running = data['jobs']['running'];
+                        let available = data['jobs']['available'];
+                        let pending = data['jobs']['pending'];
+
+                        updateStats([
+                            ['reproduced', (100 / (good + bad + fail) * good).toFixed(2) + '%'],
+                            ['good', good],
+                            ['bad', bad],
+                            ['fail', fail],
+                            ['unknown', unknown],
+                            ['build progress', (100 / (good + bad + fail + unknown) * (good + bad + fail)).toFixed(2) + '%'],
+                            ['jobs running', running],
+                            ['jobs available', available],
+                            ['jobs pending', pending],
+                        ]);
+                    });
+            }
+
+            setInterval(fetchStats, 60 * 1000);
+            fetchStats();
+        });
+        </script>
+    </head>
+    <body>
+        <h1>
+		<a href="https://reproduce.debian.net">reproduce</a>.debian.net/<a href="https://all-pull184.reproduce.debian.net">all-pull184</a>
+ </h1>
+	<h3>
+		running https://github.com/kpcyrd/rebuilderd/pull/184
+	</h3>
+        <a href="stats/trixie-security/rb.png"><img src="stats/trixie-security/rb.png" align="right"></a>
+        <h3>
+	<a href="https://all-pull184.reproduce.debian.net/experimental.html">experimental</a>,
+	<a href="https://all-pull184.reproduce.debian.net/unstable.html">unstable</a>,
+	<a href="https://all-pull184.reproduce.debian.net/forky.html">forky</a>,
+	<a href="https://all-pull184.reproduce.debian.net/trixie.html">trixie</a>,
+	trixie-security,
+	<a href="https://all-pull184.reproduce.debian.net/trixie-updates.html">trixie-updates</a>,
+	<a href="https://all-pull184.reproduce.debian.net/trixie-proposed-updates.html">trixie-proposed-updates</a>,
+	<a href="https://all-pull184.reproduce.debian.net/trixie-backports.html">trixie-backports</a>,
+        (arch:all, <a href="https://amd64-pull184.reproduce.debian.net/forky.html">arch:amd64</a>)
+        </h3>
+        <code>
+		trixie-security (arch:all) main+non-free-firmware
+        </code>
+
+        <div id="stats">Loading stats...</div>
+
+        <div>
+            <h3>Binary package search</h3>
+            <form id="search">
+                <input type="text" id="search-query" placeholder="2ping">
+                <input type="submit" value="Search">
+            </form>
+        </div>
+        <div id="search-results">
+        </div>
+
+	<footer>
+	    <br/>
+	    <a href="stats/trixie-security">Statistics about BAD packages</a> on all/trixie-security.
+	    <br/>
+	<hr/>
+            pew pew, <a href="https://github.com/kpcyrd/rebuilderd">rebuilderd</a> using <a href="https://tracker.debian.org/pkg/devscripts">debrebuild</a> to reproduce what Debian distributes via <code><a href="https://ftp.debian.org/debian/dists/">ftp.debian.org</a></code>. ♥️
+	<br/>
+	    <small>
+		<a href="https://reproduce.debian.net/">This setup</a> is in its infancy, even though by now everything is in trixie. Still, please don't consider any URLs as stable here, and more to the point, especially don't take any numbers here seriously, unless...!?!
+		<br/>Oh, and in case you are wondering why we are doing this, then hopefully the <a href="https://reproducible-builds.org">Reproducible Builds website</a> will explain why this is useful.
+		<!--#config timefmt="%Y-%m-%d" --><br/>Static content last modified: <!--#echo var="date_gmt" -->
+		</br>
+		contact: IRC preferred: #debian-reproducible on OFTC or mail to holger at d.o
+	    </small>
+        </footer>
+    </body>
+</html>


=====================================
hosts/osuosl5-amd64/var/www/html/all-pull184/trixie-updates.html
=====================================
@@ -0,0 +1,239 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8">
+        <title>
+		reproduce.debian.net/all-pull184 - trixie-updates (arch:all)
+        </title>
+        <style>
+        body {
+            font-family: sans-serif;
+            font-size: 18pt;
+        }
+        h1 {
+            font-size: 24pt;
+        }
+        h3 {
+            font-size: 18pt;
+        }
+
+        #search-results {
+            margin: 18pt 0;
+        }
+
+        pre {
+            margin: 0;
+        }
+
+        img {
+            vertical-align: middle;
+            max-width: 1920;
+            width: 50%;
+        }
+
+        #search-results pre {
+            margin: 12pt 0;
+        }
+
+        .status {
+            font-weight: bold;
+        }
+
+        .good {
+            color: green;
+        }
+
+        .bad {
+            color: red;
+        }
+
+        .unknown {
+            color: #957fff;
+        }
+
+        footer {
+            font-size: 12pt;
+        }
+        </style>
+        <script>
+        document.addEventListener('DOMContentLoaded', function() {
+            // package search
+            function spanWith(text) {
+                let s = document.createElement('span');
+                s.textContent = text;
+                return s;
+            }
+
+            function linkTo(href, text) {
+                let a = document.createElement('a');
+                a.href = href;
+                a.textContent = text;
+                return a;
+            }
+
+            function searchPkgs(query) {
+                let div = document.getElementById('search-results');
+                let url = '/all-pull184/api/v1/packages/binary?' + new URLSearchParams({
+                    name: query,
+                    distro: 'debian',
+		    release: 'trixie-updates',
+                });
+                fetch(url)
+                    .then(response => response.json())
+                    .then(data => {
+                        // clear children
+                        div.innerHTML = '';
+                        let result = data['records'];
+
+                        result.map(pkg => {
+                            let build_id = pkg.build_id;
+                            let r = document.createElement('pre');
+
+                            r.appendChild(spanWith('['));
+                            let status = pkg['status'];
+                            let statusSpan = spanWith(status);
+                            statusSpan.className += ' status';
+                            if (status == 'GOOD') {
+                                statusSpan.className += ' good';
+                            } else if (status == 'BAD') {
+                                statusSpan.className += ' bad';
+                            } else {
+                                statusSpan.className += ' unknown';
+                            }
+                            r.appendChild(statusSpan);
+                            r.appendChild(spanWith(`] ${pkg['name']} ${pkg['version']}\t\t`));
+
+                            if (build_id) {
+                                r.appendChild(spanWith(' ['));
+                                r.appendChild(linkTo(`/all-pull184/api/v1/builds/${build_id}/log`, 'log'));
+                                r.appendChild(spanWith(']'));
+                            }
+
+                            if (pkg.has_attestation) {
+                                r.appendChild(spanWith(' ['));
+                                r.appendChild(linkTo(`/all-pull184/api/v1/builds/${build_id}/attestation`, 'attestation'));
+                                r.appendChild(spanWith(']'));
+                            }
+
+                            if (pkg.has_diffoscope) {
+                                r.appendChild(spanWith(' ['));
+                                r.appendChild(linkTo(`/all-pull184/api/v1/builds/${build_id}/diffoscope`, 'diffoscope'));
+                                r.appendChild(spanWith(']'));
+                            }
+
+                            div.appendChild(r);
+                        });
+                    });
+            }
+
+            if (location.hash) {
+                searchPkgs(location.hash.substr(1));
+            }
+
+            document.getElementById('search').addEventListener('submit', function(e) {
+                e.preventDefault();
+                let query = document.getElementById('search-query').value;
+                location.href = `#${query}`;
+                searchPkgs(query);
+            });
+
+            // display stats
+            function updateStats(data) {
+                let div = document.getElementById('stats');
+                // clear children
+                div.innerHTML = '';
+                // add rows
+                data.map(row => {
+                    let r = document.createElement('pre');
+                    let key = row[0] + ': ';
+                    r.textContent = key.padEnd(25) + row[1];
+                    div.appendChild(r);
+                });
+            }
+
+            function fetchStats() {
+                fetch('/all-pull184/api/v1/dashboard?release=trixie-updates')
+                    .then(response => response.json())
+                    .then(data => {
+                        let div = document.getElementById('stats');
+
+                        let good = data['rebuilds']['good'];
+                        let bad = data['rebuilds']['bad'];
+                        let fail = data['rebuilds']['fail'];
+                        let unknown = data['rebuilds']['unknown'];
+
+                        let running = data['jobs']['running'];
+                        let available = data['jobs']['available'];
+                        let pending = data['jobs']['pending'];
+
+                        updateStats([
+                            ['reproduced', (100 / (good + bad + fail) * good).toFixed(2) + '%'],
+                            ['good', good],
+                            ['bad', bad],
+                            ['fail', fail],
+                            ['unknown', unknown],
+                            ['build progress', (100 / (good + bad + fail + unknown) * (good + bad + fail)).toFixed(2) + '%'],
+                            ['jobs running', running],
+                            ['jobs available', available],
+                            ['jobs pending', pending],
+                        ]);
+                    });
+            }
+
+            setInterval(fetchStats, 60 * 1000);
+            fetchStats();
+        });
+        </script>
+    </head>
+    <body>
+        <h1>
+		<a href="https://reproduce.debian.net">reproduce</a>.debian.net/<a href="https://all-pull184.reproduce.debian.net">all-pull184</a>
+ </h1>
+	<h3>
+		running https://github.com/kpcyrd/rebuilderd/pull/184
+	</h3>
+        <a href="stats/trixie-updates/rb.png"><img src="stats/trixie-updates/rb.png" align="right"></a>
+        <h3>
+	<a href="https://all-pull184.reproduce.debian.net/experimental.html">experimental</a>,
+	<a href="https://all-pull184.reproduce.debian.net/unstable.html">unstable</a>,
+	<a href="https://all-pull184.reproduce.debian.net/forky.html">forky</a>,
+	<a href="https://all-pull184.reproduce.debian.net/trixie.html">trixie</a>,
+	<a href="https://all-pull184.reproduce.debian.net/trixie-security.html">trixie-security</a>,
+	trixie-updates,
+	<a href="https://all-pull184.reproduce.debian.net/trixie-proposed-updates.html">trixie-proposed-updates</a>,
+	<a href="https://all-pull184.reproduce.debian.net/trixie-backports.html">trixie-backports</a>,
+        (arch:all, <a href="https://amd64-pull184.reproduce.debian.net/forky.html">arch:amd64</a>)
+        </h3>
+        <code>
+		trixie-updates (arch:all) main+non-free-firmware
+        </code>
+
+        <div id="stats">Loading stats...</div>
+
+        <div>
+            <h3>Binary package search</h3>
+            <form id="search">
+                <input type="text" id="search-query" placeholder="2ping">
+                <input type="submit" value="Search">
+            </form>
+        </div>
+        <div id="search-results">
+        </div>
+
+	<footer>
+	    <br/>
+	    <a href="stats/trixie-updates">Statistics about BAD packages</a> on all/trixie-updates.
+	    <br/>
+	<hr/>
+            pew pew, <a href="https://github.com/kpcyrd/rebuilderd">rebuilderd</a> using <a href="https://tracker.debian.org/pkg/devscripts">debrebuild</a> to reproduce what Debian distributes via <code><a href="https://ftp.debian.org/debian/dists/">ftp.debian.org</a></code>. ♥️
+	<br/>
+	    <small>
+		<a href="https://reproduce.debian.net/">This setup</a> is in its infancy, even though by now everything is in trixie. Still, please don't consider any URLs as stable here, and more to the point, especially don't take any numbers here seriously, unless...!?!
+		<br/>Oh, and in case you are wondering why we are doing this, then hopefully the <a href="https://reproducible-builds.org">Reproducible Builds website</a> will explain why this is useful.
+		<!--#config timefmt="%Y-%m-%d" --><br/>Static content last modified: <!--#echo var="date_gmt" -->
+		</br>
+		contact: IRC preferred: #debian-reproducible on OFTC or mail to holger at d.o
+	    </small>
+        </footer>
+    </body>
+</html>


=====================================
hosts/osuosl5-amd64/var/www/html/all-pull184/trixie.html
=====================================
@@ -0,0 +1,239 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8">
+        <title>
+		reproduce.debian.net/all-pull184 - trixie (arch:all)
+        </title>
+        <style>
+        body {
+            font-family: sans-serif;
+            font-size: 18pt;
+        }
+        h1 {
+            font-size: 24pt;
+        }
+        h3 {
+            font-size: 18pt;
+        }
+
+        #search-results {
+            margin: 18pt 0;
+        }
+
+        pre {
+            margin: 0;
+        }
+
+        img {
+            vertical-align: middle;
+            max-width: 1920;
+            width: 50%;
+        }
+
+        #search-results pre {
+            margin: 12pt 0;
+        }
+
+        .status {
+            font-weight: bold;
+        }
+
+        .good {
+            color: green;
+        }
+
+        .bad {
+            color: red;
+        }
+
+        .unknown {
+            color: #957fff;
+        }
+
+        footer {
+            font-size: 12pt;
+        }
+        </style>
+        <script>
+        document.addEventListener('DOMContentLoaded', function() {
+            // package search
+            function spanWith(text) {
+                let s = document.createElement('span');
+                s.textContent = text;
+                return s;
+            }
+
+            function linkTo(href, text) {
+                let a = document.createElement('a');
+                a.href = href;
+                a.textContent = text;
+                return a;
+            }
+
+            function searchPkgs(query) {
+                let div = document.getElementById('search-results');
+                let url = '/all-pull184/api/v1/packages/binary?' + new URLSearchParams({
+                    name: query,
+                    distro: 'debian',
+		    release: 'trixie',
+                });
+                fetch(url)
+                    .then(response => response.json())
+                    .then(data => {
+                        // clear children
+                        div.innerHTML = '';
+                        let result = data['records'];
+
+                        result.map(pkg => {
+                            let build_id = pkg.build_id;
+                            let r = document.createElement('pre');
+
+                            r.appendChild(spanWith('['));
+                            let status = pkg['status'];
+                            let statusSpan = spanWith(status);
+                            statusSpan.className += ' status';
+                            if (status == 'GOOD') {
+                                statusSpan.className += ' good';
+                            } else if (status == 'BAD') {
+                                statusSpan.className += ' bad';
+                            } else {
+                                statusSpan.className += ' unknown';
+                            }
+                            r.appendChild(statusSpan);
+                            r.appendChild(spanWith(`] ${pkg['name']} ${pkg['version']}\t\t`));
+
+                            if (build_id) {
+                                r.appendChild(spanWith(' ['));
+                                r.appendChild(linkTo(`/all-pull184/api/v1/builds/${build_id}/log`, 'log'));
+                                r.appendChild(spanWith(']'));
+                            }
+
+                            if (pkg.has_attestation) {
+                                r.appendChild(spanWith(' ['));
+                                r.appendChild(linkTo(`/all-pull184/api/v1/builds/${build_id}/attestation`, 'attestation'));
+                                r.appendChild(spanWith(']'));
+                            }
+
+                            if (pkg.has_diffoscope) {
+                                r.appendChild(spanWith(' ['));
+                                r.appendChild(linkTo(`/all-pull184/api/v1/builds/${build_id}/diffoscope`, 'diffoscope'));
+                                r.appendChild(spanWith(']'));
+                            }
+
+                            div.appendChild(r);
+                        });
+                    });
+            }
+
+            if (location.hash) {
+                searchPkgs(location.hash.substr(1));
+            }
+
+            document.getElementById('search').addEventListener('submit', function(e) {
+                e.preventDefault();
+                let query = document.getElementById('search-query').value;
+                location.href = `#${query}`;
+                searchPkgs(query);
+            });
+
+            // display stats
+            function updateStats(data) {
+                let div = document.getElementById('stats');
+                // clear children
+                div.innerHTML = '';
+                // add rows
+                data.map(row => {
+                    let r = document.createElement('pre');
+                    let key = row[0] + ': ';
+                    r.textContent = key.padEnd(25) + row[1];
+                    div.appendChild(r);
+                });
+            }
+
+            function fetchStats() {
+                fetch('/all-pull184/api/v1/dashboard?release=trixie')
+                    .then(response => response.json())
+                    .then(data => {
+                        let div = document.getElementById('stats');
+
+                        let good = data['rebuilds']['good'];
+                        let bad = data['rebuilds']['bad'];
+                        let fail = data['rebuilds']['fail'];
+                        let unknown = data['rebuilds']['unknown'];
+
+                        let running = data['jobs']['running'];
+                        let available = data['jobs']['available'];
+                        let pending = data['jobs']['pending'];
+
+                        updateStats([
+                            ['reproduced', (100 / (good + bad + fail) * good).toFixed(2) + '%'],
+                            ['good', good],
+                            ['bad', bad],
+                            ['fail', fail],
+                            ['unknown', unknown],
+                            ['build progress', (100 / (good + bad + fail + unknown) * (good + bad + fail)).toFixed(2) + '%'],
+                            ['jobs running', running],
+                            ['jobs available', available],
+                            ['jobs pending', pending],
+                        ]);
+                    });
+            }
+
+            setInterval(fetchStats, 60 * 1000);
+            fetchStats();
+        });
+        </script>
+    </head>
+    <body>
+        <h1>
+		<a href="https://reproduce.debian.net">reproduce</a>.debian.net/<a href="https://all-pull184.reproduce.debian.net">all-pull184</a>
+ </h1>
+	<h3>
+		running https://github.com/kpcyrd/rebuilderd/pull/184
+	</h3>
+        <a href="stats/trixie/rb.png"><img src="stats/trixie/rb.png" align="right"></a>
+        <h3>
+	<a href="https://all-pull184.reproduce.debian.net/experimental.html">experimental</a>,
+	<a href="https://all-pull184.reproduce.debian.net/unstable.html">unstable</a>,
+	<a href="https://all-pull184.reproduce.debian.net/forky.html">forky</a>,
+	trixie,
+	<a href="https://all-pull184.reproduce.debian.net/trixie-security.html">trixie-security</a>,
+	<a href="https://all-pull184.reproduce.debian.net/trixie-updates.html">trixie-updates</a>,
+	<a href="https://all-pull184.reproduce.debian.net/trixie-proposed-updates.html">trixie-proposed-updates</a>,
+	<a href="https://all-pull184.reproduce.debian.net/trixie-backports.html">trixie-backports</a>,
+        (arch:all, <a href="https://amd64-pull184.reproduce.debian.net/forky.html">arch:amd64</a>)
+        </h3>
+        <code>
+		trixie (arch:all) main+non-free-firmware
+        </code>
+
+        <div id="stats">Loading stats...</div>
+
+        <div>
+            <h3>Binary package search</h3>
+            <form id="search">
+                <input type="text" id="search-query" placeholder="2ping">
+                <input type="submit" value="Search">
+            </form>
+        </div>
+        <div id="search-results">
+        </div>
+
+	<footer>
+	    <br/>
+	    <a href="stats/trixie">Statistics about BAD packages</a> on all/trixie.
+	    <br/>
+	<hr/>
+            pew pew, <a href="https://github.com/kpcyrd/rebuilderd">rebuilderd</a> using <a href="https://tracker.debian.org/pkg/devscripts">debrebuild</a> to reproduce what Debian distributes via <code><a href="https://ftp.debian.org/debian/dists/">ftp.debian.org</a></code>. ♥️
+	<br/>
+	    <small>
+		<a href="https://reproduce.debian.net/">This setup</a> is in its infancy, even though by now everything is in trixie. Still, please don't consider any URLs as stable here, and more to the point, especially don't take any numbers here seriously, unless...!?!
+		<br/>Oh, and in case you are wondering why we are doing this, then hopefully the <a href="https://reproducible-builds.org">Reproducible Builds website</a> will explain why this is useful.
+		<!--#config timefmt="%Y-%m-%d" --><br/>Static content last modified: <!--#echo var="date_gmt" -->
+		</br>
+		contact: IRC preferred: #debian-reproducible on OFTC or mail to holger at d.o
+	    </small>
+        </footer>
+    </body>
+</html>


=====================================
hosts/osuosl5-amd64/var/www/html/all-pull184/unstable.html
=====================================
@@ -0,0 +1,239 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8">
+        <title>
+		reproduce.debian.net/all-pull184 - unstable (arch:all)
+        </title>
+        <style>
+        body {
+            font-family: sans-serif;
+            font-size: 18pt;
+        }
+        h1 {
+            font-size: 24pt;
+        }
+        h3 {
+            font-size: 18pt;
+        }
+
+        #search-results {
+            margin: 18pt 0;
+        }
+
+        pre {
+            margin: 0;
+        }
+
+        img {
+            vertical-align: middle;
+            max-width: 1920;
+            width: 50%;
+        }
+
+        #search-results pre {
+            margin: 12pt 0;
+        }
+
+        .status {
+            font-weight: bold;
+        }
+
+        .good {
+            color: green;
+        }
+
+        .bad {
+            color: red;
+        }
+
+        .unknown {
+            color: #957fff;
+        }
+
+        footer {
+            font-size: 12pt;
+        }
+        </style>
+        <script>
+        document.addEventListener('DOMContentLoaded', function() {
+            // package search
+            function spanWith(text) {
+                let s = document.createElement('span');
+                s.textContent = text;
+                return s;
+            }
+
+            function linkTo(href, text) {
+                let a = document.createElement('a');
+                a.href = href;
+                a.textContent = text;
+                return a;
+            }
+
+            function searchPkgs(query) {
+                let div = document.getElementById('search-results');
+                let url = '/all-pull184/api/v1/packages/binary?' + new URLSearchParams({
+                    name: query,
+                    distro: 'debian',
+		    release: 'unstable',
+                });
+                fetch(url)
+                    .then(response => response.json())
+                    .then(data => {
+                        // clear children
+                        div.innerHTML = '';
+                        let result = data['records'];
+
+                        result.map(pkg => {
+                            let build_id = pkg.build_id;
+                            let r = document.createElement('pre');
+
+                            r.appendChild(spanWith('['));
+                            let status = pkg['status'];
+                            let statusSpan = spanWith(status);
+                            statusSpan.className += ' status';
+                            if (status == 'GOOD') {
+                                statusSpan.className += ' good';
+                            } else if (status == 'BAD') {
+                                statusSpan.className += ' bad';
+                            } else {
+                                statusSpan.className += ' unknown';
+                            }
+                            r.appendChild(statusSpan);
+                            r.appendChild(spanWith(`] ${pkg['name']} ${pkg['version']}\t\t`));
+
+                            if (build_id) {
+                                r.appendChild(spanWith(' ['));
+                                r.appendChild(linkTo(`/all-pull184/api/v1/builds/${build_id}/log`, 'log'));
+                                r.appendChild(spanWith(']'));
+                            }
+
+                            if (pkg.has_attestation) {
+                                r.appendChild(spanWith(' ['));
+                                r.appendChild(linkTo(`/all-pull184/api/v1/builds/${build_id}/attestation`, 'attestation'));
+                                r.appendChild(spanWith(']'));
+                            }
+
+                            if (pkg.has_diffoscope) {
+                                r.appendChild(spanWith(' ['));
+                                r.appendChild(linkTo(`/all-pull184/api/v1/builds/${build_id}/diffoscope`, 'diffoscope'));
+                                r.appendChild(spanWith(']'));
+                            }
+
+                            div.appendChild(r);
+                        });
+                    });
+            }
+
+            if (location.hash) {
+                searchPkgs(location.hash.substr(1));
+            }
+
+            document.getElementById('search').addEventListener('submit', function(e) {
+                e.preventDefault();
+                let query = document.getElementById('search-query').value;
+                location.href = `#${query}`;
+                searchPkgs(query);
+            });
+
+            // display stats
+            function updateStats(data) {
+                let div = document.getElementById('stats');
+                // clear children
+                div.innerHTML = '';
+                // add rows
+                data.map(row => {
+                    let r = document.createElement('pre');
+                    let key = row[0] + ': ';
+                    r.textContent = key.padEnd(25) + row[1];
+                    div.appendChild(r);
+                });
+            }
+
+            function fetchStats() {
+                fetch('/all-pull184/api/v1/dashboard?release=unstable')
+                    .then(response => response.json())
+                    .then(data => {
+                        let div = document.getElementById('stats');
+
+                        let good = data['rebuilds']['good'];
+                        let bad = data['rebuilds']['bad'];
+                        let fail = data['rebuilds']['fail'];
+                        let unknown = data['rebuilds']['unknown'];
+
+                        let running = data['jobs']['running'];
+                        let available = data['jobs']['available'];
+                        let pending = data['jobs']['pending'];
+
+                        updateStats([
+                            ['reproduced', (100 / (good + bad + fail) * good).toFixed(2) + '%'],
+                            ['good', good],
+                            ['bad', bad],
+                            ['fail', fail],
+                            ['unknown', unknown],
+                            ['build progress', (100 / (good + bad + fail + unknown) * (good + bad + fail)).toFixed(2) + '%'],
+                            ['jobs running', running],
+                            ['jobs available', available],
+                            ['jobs pending', pending],
+                        ]);
+                    });
+            }
+
+            setInterval(fetchStats, 60 * 1000);
+            fetchStats();
+        });
+        </script>
+    </head>
+    <body>
+        <h1>
+		<a href="https://reproduce.debian.net">reproduce</a>.debian.net/<a href="https://all-pull184.reproduce.debian.net">all-pull184</a>
+ </h1>
+	<h3>
+		running https://github.com/kpcyrd/rebuilderd/pull/184
+	</h3>
+        <a href="stats/unstable/rb.png"><img src="stats/unstable/rb.png" align="right"></a>
+        <h3>
+	<a href="https://all-pull184.reproduce.debian.net/experimental.html">experimental</a>,
+	unstable,
+	<a href="https://all-pull184.reproduce.debian.net/forky.html">forky</a>,
+	<a href="https://all-pull184.reproduce.debian.net/trixie.html">trixie</a>,
+	<a href="https://all-pull184.reproduce.debian.net/trixie-security.html">trixie-security</a>,
+	<a href="https://all-pull184.reproduce.debian.net/trixie-updates.html">trixie-updates</a>,
+	<a href="https://all-pull184.reproduce.debian.net/trixie-proposed-updates.html">trixie-proposed-updates</a>,
+	<a href="https://all-pull184.reproduce.debian.net/trixie-backports.html">trixie-backports</a>,
+        (arch:all, <a href="https://amd64-pull184.reproduce.debian.net/forky.html">arch:amd64</a>)
+        </h3>
+        <code>
+		unstable (arch:all) main+non-free-firmware
+        </code>
+
+        <div id="stats">Loading stats...</div>
+
+        <div>
+            <h3>Binary package search</h3>
+            <form id="search">
+                <input type="text" id="search-query" placeholder="2ping">
+                <input type="submit" value="Search">
+            </form>
+        </div>
+        <div id="search-results">
+        </div>
+
+	<footer>
+	    <br/>
+	    <a href="stats/unstable">Statistics about BAD packages</a> on all/unstable.
+	    <br/>
+	<hr/>
+            pew pew, <a href="https://github.com/kpcyrd/rebuilderd">rebuilderd</a> using <a href="https://tracker.debian.org/pkg/devscripts">debrebuild</a> to reproduce what Debian distributes via <code><a href="https://ftp.debian.org/debian/dists/">ftp.debian.org</a></code>. ♥️
+	<br/>
+	    <small>
+		<a href="https://reproduce.debian.net/">This setup</a> is in its infancy, even though by now everything is in trixie. Still, please don't consider any URLs as stable here, and more to the point, especially don't take any numbers here seriously, unless...!?!
+		<br/>Oh, and in case you are wondering why we are doing this, then hopefully the <a href="https://reproducible-builds.org">Reproducible Builds website</a> will explain why this is useful.
+		<!--#config timefmt="%Y-%m-%d" --><br/>Static content last modified: <!--#echo var="date_gmt" -->
+		</br>
+		contact: IRC preferred: #debian-reproducible on OFTC or mail to holger at d.o
+	    </small>
+        </footer>
+    </body>
+</html>


=====================================
hosts/osuosl5-amd64/var/www/html/amd64-pull184/experimental.html
=====================================
@@ -202,7 +202,7 @@
 	<a href="https://amd64-pull184.reproduce.debian.net/trixie-updates.html">trixie-updates</a>,
 	<a href="https://amd64-pull184.reproduce.debian.net/trixie-proposed-updates.html">trixie-proposed-updates</a>,
 	<a href="https://amd64-pull184.reproduce.debian.net/trixie-backports.html">trixie-backports</a>,
-	(arch:amd64)
+        (arch:amd64, <a href="https://all-pull184.reproduce.debian.net/forky.html">arch:all</a>)
         </h3>
         <code>
 		experimental (arch:amd64) main+non-free-firmware


=====================================
hosts/osuosl5-amd64/var/www/html/amd64-pull184/forky.html
=====================================
@@ -202,7 +202,7 @@
 	<a href="https://amd64-pull184.reproduce.debian.net/trixie-updates.html">trixie-updates</a>,
 	<a href="https://amd64-pull184.reproduce.debian.net/trixie-proposed-updates.html">trixie-proposed-updates</a>,
 	<a href="https://amd64-pull184.reproduce.debian.net/trixie-backports.html">trixie-backports</a>,
-	(arch:amd64)
+        (arch:amd64, <a href="https://all-pull184.reproduce.debian.net/forky.html">arch:all</a>)
         </h3>
         <code>
 		forky (arch:amd64) main+non-free-firmware


=====================================
hosts/osuosl5-amd64/var/www/html/amd64-pull184/trixie-backports.html
=====================================
@@ -202,7 +202,7 @@
 	<a href="https://amd64-pull184.reproduce.debian.net/trixie-updates.html">trixie-updates</a>,
 	<a href="https://amd64-pull184.reproduce.debian.net/trixie-proposed-updates.html">trixie-proposed-updates</a>,
 	trixie-backports,
-	(arch:amd64)
+        (arch:amd64, <a href="https://all-pull184.reproduce.debian.net/forky.html">arch:all</a>)
         </h3>
         <code>
 		trixie-backports (arch:amd64) main+non-free-firmware


=====================================
hosts/osuosl5-amd64/var/www/html/amd64-pull184/trixie-proposed-updates.html
=====================================
@@ -202,7 +202,7 @@
 	<a href="https://amd64-pull184.reproduce.debian.net/trixie-updates.html">trixie-updates</a>,
 	trixie-proposed-updates,
 	<a href="https://amd64-pull184.reproduce.debian.net/trixie-backports.html">trixie-backports</a>,
-	(arch:amd64)
+        (arch:amd64, <a href="https://all-pull184.reproduce.debian.net/forky.html">arch:all</a>)
         </h3>
         <code>
 		trixie-proposed-updates (arch:amd64) main+non-free-firmware


=====================================
hosts/osuosl5-amd64/var/www/html/amd64-pull184/trixie-security.html
=====================================
@@ -202,7 +202,7 @@
 	<a href="https://amd64-pull184.reproduce.debian.net/trixie-updates.html">trixie-updates</a>,
 	<a href="https://amd64-pull184.reproduce.debian.net/trixie-proposed-updates.html">trixie-proposed-updates</a>,
 	<a href="https://amd64-pull184.reproduce.debian.net/trixie-backports.html">trixie-backports</a>,
-	(arch:amd64)
+        (arch:amd64, <a href="https://all-pull184.reproduce.debian.net/forky.html">arch:all</a>)
         </h3>
         <code>
 		trixie-security (arch:amd64) main+non-free-firmware


=====================================
hosts/osuosl5-amd64/var/www/html/amd64-pull184/trixie-updates.html
=====================================
@@ -202,7 +202,7 @@
 	trixie-updates,
 	<a href="https://amd64-pull184.reproduce.debian.net/trixie-proposed-updates.html">trixie-proposed-updates</a>,
 	<a href="https://amd64-pull184.reproduce.debian.net/trixie-backports.html">trixie-backports</a>,
-	(arch:amd64)
+        (arch:amd64, <a href="https://all-pull184.reproduce.debian.net/forky.html">arch:all</a>)
         </h3>
         <code>
 		trixie-updates (arch:amd64) main+non-free-firmware


=====================================
hosts/osuosl5-amd64/var/www/html/amd64-pull184/trixie.html
=====================================
@@ -202,7 +202,7 @@
 	<a href="https://amd64-pull184.reproduce.debian.net/trixie-updates.html">trixie-updates</a>,
 	<a href="https://amd64-pull184.reproduce.debian.net/trixie-proposed-updates.html">trixie-proposed-updates</a>,
 	<a href="https://amd64-pull184.reproduce.debian.net/trixie-backports.html">trixie-backports</a>,
-	(arch:amd64)
+        (arch:amd64, <a href="https://all-pull184.reproduce.debian.net/forky.html">arch:all</a>)
         </h3>
         <code>
 		trixie (arch:amd64) main+non-free-firmware


=====================================
hosts/osuosl5-amd64/var/www/html/amd64-pull184/unstable.html
=====================================
@@ -202,7 +202,7 @@
 	<a href="https://amd64-pull184.reproduce.debian.net/trixie-updates.html">trixie-updates</a>,
 	<a href="https://amd64-pull184.reproduce.debian.net/trixie-proposed-updates.html">trixie-proposed-updates</a>,
 	<a href="https://amd64-pull184.reproduce.debian.net/trixie-backports.html">trixie-backports</a>,
-	(arch:amd64)
+        (arch:amd64, <a href="https://all-pull184.reproduce.debian.net/forky.html">arch:all</a>)
         </h3>
         <code>
 		unstable (arch:amd64) main+non-free-firmware


=====================================
update_jdn.sh
=====================================
@@ -726,7 +726,7 @@ if [ "$HOSTNAME" = "jenkins" ] || [ "$HOSTNAME" = "ionos7-amd64" ] || [ "$HOSTNA
 fi
 # set secrets for rebuilderd and rebuilderd-workers
 case $HOSTNAME in
-	osuosl5*)		for a in all amd64 amd64-pull184 arm64 armel armhf i386 ppc64el riscv64 ; do
+	osuosl5*)		for a in all all-pull184 amd64 amd64-pull184 arm64 armel armhf i386 ppc64el riscv64 ; do
 					SIGNUPSECRET="$(sudo cat /etc/rebuilderd/rebuilderd-${a}.secret)"
 					f=rebuilderd-${a}.conf
 					if [ -f /etc/rebuilderd/$f ] ; then
@@ -1001,9 +1001,9 @@ case $HOSTNAME in
 	*ppc64el)				deploy_rebuilderd_services worker 1
 						;;
 	osuosl5*)				
-						deploy_rebuilderd_services rebuilderd	"all amd64 amd64-pull184 arm64 armel armhf i386 ppc64el riscv64"
-						deploy_rebuilderd_services pkgsync	"all amd64 amd64-pull184 arm64 armel armhf i386 ppc64el riscv64"
-						deploy_rebuilderd_services db-backup	"all amd64 amd64-pull184 arm64 armel armhf i386 ppc64el riscv64"
+						deploy_rebuilderd_services rebuilderd	"all all-pull184 amd64 amd64-pull184 arm64 armel armhf i386 ppc64el riscv64"
+						deploy_rebuilderd_services pkgsync	"all all-pull184 amd64 amd64-pull184 arm64 armel armhf i386 ppc64el riscv64"
+						deploy_rebuilderd_services db-backup	"all all-pull184 amd64 amd64-pull184 arm64 armel armhf i386 ppc64el riscv64"
 						sudo systemctl enable --now rebuilderd-db-backup-compress.timer
 						;;
 	*) 					;;



View it on GitLab: https://salsa.debian.org/qa/jenkins.debian.net/-/commit/c1051880334d597cebd895628222d458ed26e497

-- 
View it on GitLab: https://salsa.debian.org/qa/jenkins.debian.net/-/commit/c1051880334d597cebd895628222d458ed26e497
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/qa-jenkins-scm/attachments/20250906/db6717f7/attachment-0001.htm>


More information about the Qa-jenkins-scm mailing list