Remove old link and show number of builds

In the users locale of course. Without any annoying Accept-Language
parsing or anything like that, just with the beauty of JavaScript.
This commit is contained in:
nora 2025-07-04 22:06:40 +02:00
parent 3f302c7180
commit f6fac25c6f
4 changed files with 94 additions and 35 deletions

View file

@ -82,6 +82,17 @@ pub struct FinishedNightlyWithBroken {
pub broken_error: Option<String>,
}
pub struct BuildStats {
pub pass_count: u32,
pub error_count: u32,
}
impl BuildStats {
pub fn total(&self) -> u32 {
self.pass_count + self.error_count
}
}
impl Db {
pub async fn open(path: &str) -> Result<Self> {
let db_opts = SqliteConnectOptions::from_str(path)
@ -168,6 +179,34 @@ impl Db {
.map(|elems| elems.into_iter().map(|elem| elem.nightly).collect())
}
pub async fn build_count(&self) -> Result<BuildStats> {
#[derive(sqlx::FromRow)]
struct BuildStat {
build_count: u32,
status: Status,
}
let results = sqlx::query_as::<_, BuildStat>(
"SELECT COUNT(status) as build_count, status FROM build_info GROUP BY status",
)
.fetch_all(&self.conn)
.await
.wrap_err("getting list of all targets")?;
let count = |status| {
results
.iter()
.find(|row| row.status == status)
.map(|row| row.build_count)
.unwrap_or(0)
};
Ok(BuildStats {
pass_count: count(Status::Pass),
error_count: count(Status::Error),
})
}
pub async fn build_status_full(
&self,
nightly: &str,

View file

@ -11,7 +11,7 @@ use color_eyre::{eyre::Context, Result};
use serde::{Deserialize, Serialize};
use tracing::{error, info};
use crate::db::{BuildInfo, BuildMode, Db, Status};
use crate::db::{BuildInfo, BuildMode, BuildStats, Db, Status};
#[derive(Clone)]
pub struct AppState {
@ -25,6 +25,7 @@ pub async fn webserver(db: Db) -> Result<()> {
.route("/target", get(web_target))
.route("/nightly", get(web_nightly))
.route("/index.css", get(index_css))
.route("/index.js", get(index_js))
.with_state(AppState { db });
info!("Serving website on port 3000 (commit {})", crate::VERSION);
@ -257,35 +258,37 @@ async fn web_nightly(State(state): State<AppState>, Query(query): Query<NightlyQ
async fn web_root(State(state): State<AppState>) -> impl IntoResponse {
use askama::Template;
#[derive(askama::Template)]
#[template(path = "index.html")]
struct RootPage {
targets: Vec<String>,
nightlies: Vec<String>,
version: &'static str,
}
match state.db.target_list().await {
Ok(targets) => match state.db.nightly_list().await {
Ok(nightlies) => {
let page = RootPage {
targets,
nightlies,
version: crate::VERSION,
};
Html(page.render().unwrap()).into_response()
}
Err(err) => {
error!(?err, "Error loading nightly state");
StatusCode::INTERNAL_SERVER_ERROR.into_response()
}
},
Err(err) => {
error!(?err, "Error loading target state");
StatusCode::INTERNAL_SERVER_ERROR.into_response()
async fn render(state: AppState) -> Result<Response> {
#[derive(askama::Template)]
#[template(path = "index.html")]
struct RootPage {
targets: Vec<String>,
nightlies: Vec<String>,
version: &'static str,
build_count: BuildStats,
}
let targets = state.db.target_list().await?;
let nightlies = state.db.nightly_list().await?;
let build_count = state.db.build_count().await?;
let page = RootPage {
targets,
nightlies,
version: crate::VERSION,
build_count,
};
Ok(Html(page.render().unwrap()).into_response())
}
render(state)
.await
.unwrap_or_else(|err: color_eyre::eyre::Error| {
error!(?err, "Error loading data for root page");
StatusCode::INTERNAL_SERVER_ERROR.into_response()
})
}
async fn index_css() -> impl IntoResponse {
@ -298,6 +301,16 @@ async fn index_css() -> impl IntoResponse {
)
}
async fn index_js() -> impl IntoResponse {
(
[(
axum::http::header::CONTENT_TYPE,
axum::http::HeaderValue::from_static("application/javascript; charset=utf-8"),
)],
include_str!("../static/index.js"),
)
}
#[derive(Serialize, Deserialize)]
struct TriggerBuildBody {
nightly: String,

4
static/index.js Normal file
View file

@ -0,0 +1,4 @@
// Do some fancy number formatting in your locale, so you can't blame me if the numbers look ass.
document.querySelectorAll(".number").forEach((elem) => {
elem.textContent = new Intl.NumberFormat().format(Number(elem.textContent));
});

View file

@ -5,21 +5,24 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Does it build?</title>
<link rel="stylesheet" href="index.css" />
<style></style>
<script type="module" defer src="index.js"></script>
</head>
<body>
<h1>Does it build?</h1>
<p>
This website builds every rustc target on many nightlies to check which
ones work and which ones do not.
This website builds the standard libary for every rustc target on every
nightly to check whether it builds or not.
</p>
<p>
There are currently
<span class="number">{{build_count.total()}}</span> build results stored,
with <span class="number">{{build_count.pass_count}}</span> passing and
<span class="number">{{build_count.error_count}}</span> erroring.
</p>
<p>You can select a target from the list below and check its history.</p>
<p>
If that is not what you want, you can visit the
<a href="full-table">full table</a> to see
<strong>all</strong> information at once (which will really stress test
your browser).
You can select a nightly or target from the list below and check its
history.
</p>
<h1>Nightlies</h1>