diff --git a/migrations/20250703173258_index.sql b/migrations/20250703173258_index.sql new file mode 100644 index 0000000..ee4693a --- /dev/null +++ b/migrations/20250703173258_index.sql @@ -0,0 +1,5 @@ +-- Add migration script here + +CREATE INDEX IF NOT EXISTS build_info_nightly ON build_info (nightly); + +CREATE INDEX IF NOT EXISTS build_info_target ON build_info (target); diff --git a/src/db.rs b/src/db.rs index 3bc06f5..719eeb3 100644 --- a/src/db.rs +++ b/src/db.rs @@ -100,13 +100,6 @@ impl Db { Ok(()) } - pub async fn full_mega_monster(&self) -> Result> { - sqlx::query_as::<_, BuildInfo>("SELECT nightly, target, status, mode FROM build_info") - .fetch_all(&self.conn) - .await - .wrap_err("getting build status from DB") - } - pub async fn history_for_target(&self, target: &str) -> Result> { sqlx::query_as::<_, BuildInfo>( "SELECT nightly, target, status, mode FROM build_info WHERE target = ?", diff --git a/src/web.rs b/src/web.rs index ff8db9b..d0911d5 100644 --- a/src/web.rs +++ b/src/web.rs @@ -5,7 +5,7 @@ use axum::{ http::StatusCode, response::{Html, IntoResponse, Response}, routing::get, - Json, Router, + Router, }; use color_eyre::{eyre::Context, Result}; use serde::{Deserialize, Serialize}; @@ -24,10 +24,7 @@ pub async fn webserver(db: Db) -> Result<()> { .route("/build", get(web_build)) .route("/target", get(web_target)) .route("/nightly", get(web_nightly)) - .route("/full-table", get(web_full_table)) .route("/index.css", get(index_css)) - .route("/index.js", get(index_js)) - .route("/full-mega-monster", get(full_mega_monster)) .with_state(AppState { db }); info!("Serving website on port 3000 (commit {})", crate::VERSION); @@ -240,9 +237,6 @@ async fn web_root(State(state): State) -> impl IntoResponse { } } -async fn web_full_table() -> impl IntoResponse { - Html(include_str!("../static/full-table.html").replace("{{version}}", crate::VERSION)) -} async fn index_css() -> impl IntoResponse { ( [( @@ -252,22 +246,6 @@ async fn index_css() -> impl IntoResponse { include_str!("../static/index.css"), ) } -async fn index_js() -> impl IntoResponse { - ( - [( - axum::http::header::CONTENT_TYPE, - axum::http::HeaderValue::from_static("text/javascript"), - )], - include_str!("../static/index.js"), - ) -} - -async fn full_mega_monster(State(state): State) -> impl IntoResponse { - state.db.full_mega_monster().await.map(Json).map_err(|err| { - error!(?err, "Error loading target state"); - StatusCode::INTERNAL_SERVER_ERROR - }) -} #[derive(Serialize, Deserialize)] struct TriggerBuildBody { diff --git a/static/full-table.html b/static/full-table.html deleted file mode 100644 index 4f4b052..0000000 --- a/static/full-table.html +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - Does it build? - - - -

Does it build?

-

This website builds every rustc target on many nightlies to check which ones work and which ones do not.

- - -

Core Build

-

Builds every target with: -

cargo build --release -Zbuild-std=core

-

This checks that codegen/linking of core works, but does not check whether std builds.

- - - - - - - - - -
loading...
- - -

Std Check Build

-

Builds every target with: -

cargo miri setup

-

This checks that std builds (on targets that have it) but does not check whether codegen/linking works.

- - - - - - - - - -
loading...
- - - - - diff --git a/static/index.js b/static/index.js deleted file mode 100644 index 11e26cb..0000000 --- a/static/index.js +++ /dev/null @@ -1,159 +0,0 @@ -class Table { - constructor(data, tableElemId, filterElemId, filterFailedElemId) { - this.data = data; - this.elem = document.getElementById(tableElemId); - - document.getElementById(filterElemId)?.addEventListener("input", (e) => { - this.filter.search = e.target.value; - this.render(); - }); - document - .getElementById(filterFailedElemId) - ?.addEventListener("input", (e) => { - this.filter.filterFailed = e.target.checked; - this.render(); - }); - - this.filter = { - search: "", - filterFailed: false, - }; - } - - update(data) { - this.data = data; - } - - render() { - const allTargets = new Set(); - const allNightlies = new Set(); - - // The infos grouped by target. - const targetInfos = new Map(); - - // Targets that have, at some point, errored - const targetsWithErrors = new Set(); - - // Whether a nightly is completely broken. - // These are still filtered out when filter failed is selected. - const isNightlyBroken = new Map(); - - // The first pass over the data, to find nightlies that are broken. - for (const info of this.data) { - if (!isNightlyBroken.has(info.nightly)) { - // Assume that a nightly is broken until proven otherwise. - isNightlyBroken.set(info.nightly, true); - } - if (info.status == "pass") { - // This nightly has built something, so it's clearly not broken :). - isNightlyBroken.set(info.nightly, false); - } - } - - // Second pass over the data, group by nightly and prepare data for filter. - for (const info of this.data) { - allNightlies.add(info.nightly); - - if (!info.target.includes(this.filter.search)) { - continue; - } - - if (info.status === "error" && !isNightlyBroken.get(info.nightly)) { - targetsWithErrors.add(info.target); - } - - allTargets.add(info.target); - if (!targetInfos.has(info.target)) { - targetInfos.set(info.target, new Map()); - } - targetInfos.get(info.target).set(info.nightly, info); - } - - const nightlies = Array.from(allNightlies); - nightlies.sort(); - nightlies.reverse(); - const targets = Array.from(allTargets); - targets.sort(); - - const header = document.createElement("tr"); - const headerTarget = document.createElement("th"); - headerTarget.innerText = "target"; - header.appendChild(headerTarget); - nightlies.forEach((target) => { - const elem = document.createElement("th"); - elem.classList.add("target-header"); - elem.innerText = target; - header.appendChild(elem); - }); - - const rows = targets.flatMap((target) => { - if (this.filter.filterFailed && !targetsWithErrors.has(target)) { - return []; - } - - const tr = document.createElement("tr"); - - const targetCol = document.createElement("td"); - targetCol.innerText = target; - targetCol.classList.add("target-name-col"); - tr.appendChild(targetCol); - - const info = targetInfos.get(target) ?? new Map(); - - for (const nightly of nightlies) { - const td = document.createElement("td"); - const targetInfo = info.get(nightly); - - if (targetInfo) { - const a = document.createElement("a"); - a.classList.add("build-info-a"); - a.href = `build?nightly=${encodeURIComponent( - nightly - )}&target=${encodeURIComponent(target)}&mode=${encodeURIComponent( - targetInfo.mode - )}`; - a.innerText = targetInfo.status == "pass" ? "✅" : "❌"; - td.appendChild(a); - td.classList.add("build-cell"); - td.classList.add(targetInfo.status); - } else { - td.innerText = ""; - td.classList.add("missing"); - } - tr.appendChild(td); - } - - return [tr]; - }); - this.elem.replaceChildren(header, ...rows); - } -} - -const coreTable = new Table( - [], - "target-state", - "target-filter", - "target-filter-failed" -); -const miriTable = new Table( - [], - "target-state-miri", - "target-filter-miri", - "target-filter-failed-miri" -); - -function fetchTargets() { - fetch("full-mega-monster") - .then((body) => body.json()) - .then((body) => { - const core = body.filter((info) => info.mode === "core"); - const miri = body.filter((info) => info.mode === "miri-std"); - coreTable.update(core); - miriTable.update(miri); - coreTable.render(); - miriTable.render(); - }); -} - -// Initial fetch -fetchTargets(); diff --git a/templates/index.html b/templates/index.html index 07b6f21..421a894 100644 --- a/templates/index.html +++ b/templates/index.html @@ -23,7 +23,13 @@

Nightlies

-
    +
      + {% for nightly in nightlies.iter().take(5) %} +
    • + {{ nightly }} +
    • + {% endfor %} +

    To view a list of all nightlies, check the list at the end. @@ -68,6 +74,5 @@ -