mirror of
https://github.com/Noratrieb/does-it-build.git
synced 2026-01-14 18:35:01 +01:00
Add nightly overview pages
This commit is contained in:
parent
7f4c69e51f
commit
61d78680e0
9 changed files with 229 additions and 41 deletions
12
src/build.rs
12
src/build.rs
|
|
@ -57,7 +57,7 @@ async fn background_builder_inner(db: &Db, nightly_cache: &mut NightlyCache) ->
|
|||
match next {
|
||||
Some((nightly, mode)) => {
|
||||
info!(%nightly, %mode, "Building next nightly");
|
||||
let result = build_every_target_for_toolchain(&db, &nightly, mode)
|
||||
let result = build_every_target_for_toolchain(db, &nightly, mode)
|
||||
.await
|
||||
.wrap_err_with(|| format!("building targets for toolchain {nightly}"));
|
||||
if let Err(err) = result {
|
||||
|
|
@ -69,7 +69,7 @@ async fn background_builder_inner(db: &Db, nightly_cache: &mut NightlyCache) ->
|
|||
}
|
||||
None => {
|
||||
info!("No new nightly, waiting for an hour to try again");
|
||||
tokio::time::sleep(Duration::from_secs(1 * 60 * 60)).await;
|
||||
tokio::time::sleep(Duration::from_secs(60 * 60)).await;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
|
@ -191,7 +191,7 @@ pub async fn build_every_target_for_toolchain(
|
|||
let results = futures::stream::iter(
|
||||
targets
|
||||
.iter()
|
||||
.map(|target| build_single_target(&db, nightly, target, mode)),
|
||||
.map(|target| build_single_target(db, nightly, target, mode)),
|
||||
)
|
||||
.buffer_unordered(concurrent)
|
||||
.collect::<Vec<Result<()>>>()
|
||||
|
|
@ -266,7 +266,7 @@ async fn build_target(
|
|||
BuildMode::Core => {
|
||||
let init = Command::new("cargo")
|
||||
.args(["init", "--lib", "--name", "target-test"])
|
||||
.current_dir(&tmpdir)
|
||||
.current_dir(tmpdir)
|
||||
.output()
|
||||
.await
|
||||
.wrap_err("spawning cargo init")?;
|
||||
|
|
@ -282,7 +282,7 @@ async fn build_target(
|
|||
.arg(format!("+{toolchain}"))
|
||||
.args(["build", "-Zbuild-std=core", "--release"])
|
||||
.args(["--target", target])
|
||||
.current_dir(&tmpdir)
|
||||
.current_dir(tmpdir)
|
||||
.output()
|
||||
.await
|
||||
.wrap_err("spawning cargo build")?
|
||||
|
|
@ -291,7 +291,7 @@ async fn build_target(
|
|||
.arg(format!("+{toolchain}"))
|
||||
.args(["miri", "setup"])
|
||||
.args(["--target", target])
|
||||
.current_dir(&tmpdir)
|
||||
.current_dir(tmpdir)
|
||||
.env("MIRI_SYSROOT", tmpdir)
|
||||
.output()
|
||||
.await
|
||||
|
|
|
|||
29
src/db.rs
29
src/db.rs
|
|
@ -33,7 +33,7 @@ impl Display for BuildMode {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(sqlx::FromRow, Serialize, Deserialize)]
|
||||
#[derive(sqlx::FromRow, Serialize, Deserialize, Clone)]
|
||||
pub struct BuildInfo {
|
||||
pub nightly: String,
|
||||
pub target: String,
|
||||
|
|
@ -81,7 +81,7 @@ impl Db {
|
|||
|
||||
let conn = Pool::connect_with(db_opts)
|
||||
.await
|
||||
.wrap_err_with(|| format!("opening db from `{}`", path))?;
|
||||
.wrap_err_with(|| format!("opening db from `{path}`"))?;
|
||||
Ok(Self { conn })
|
||||
}
|
||||
|
||||
|
|
@ -117,6 +117,16 @@ impl Db {
|
|||
.wrap_err("getting history for single target")
|
||||
}
|
||||
|
||||
pub async fn history_for_nightly(&self, nightly: &str) -> Result<Vec<BuildInfo>> {
|
||||
sqlx::query_as::<_, BuildInfo>(
|
||||
"SELECT nightly, target, status, mode FROM build_info WHERE nightly = ?",
|
||||
)
|
||||
.bind(nightly)
|
||||
.fetch_all(&self.conn)
|
||||
.await
|
||||
.wrap_err("getting history for single nightly")
|
||||
}
|
||||
|
||||
pub async fn target_list(&self) -> Result<Vec<String>> {
|
||||
#[derive(sqlx::FromRow)]
|
||||
struct TargetName {
|
||||
|
|
@ -130,6 +140,21 @@ impl Db {
|
|||
.map(|elems| elems.into_iter().map(|elem| elem.target).collect())
|
||||
}
|
||||
|
||||
pub async fn nightly_list(&self) -> Result<Vec<String>> {
|
||||
#[derive(sqlx::FromRow)]
|
||||
struct NightlyName {
|
||||
nightly: String,
|
||||
}
|
||||
|
||||
sqlx::query_as::<_, NightlyName>(
|
||||
"SELECT DISTINCT nightly FROM build_info ORDER BY nightly DESC",
|
||||
)
|
||||
.fetch_all(&self.conn)
|
||||
.await
|
||||
.wrap_err("getting list of all targets")
|
||||
.map(|elems| elems.into_iter().map(|elem| elem.nightly).collect())
|
||||
}
|
||||
|
||||
pub async fn build_status_full(
|
||||
&self,
|
||||
nightly: &str,
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ impl Nightlies {
|
|||
.last()
|
||||
.ok_or_eyre("did not find any nightlies in manifests.txt")?;
|
||||
|
||||
for nightly in guess_more_recent_nightlies(&latest)? {
|
||||
for nightly in guess_more_recent_nightlies(latest)? {
|
||||
if nightly_exists(&nightly, cache)
|
||||
.await
|
||||
.wrap_err_with(|| format!("checking whether {nightly} exists"))?
|
||||
|
|
@ -54,7 +54,10 @@ impl Nightlies {
|
|||
|
||||
all.reverse();
|
||||
|
||||
debug!("Loaded {} nightlies from the manifest and manual additions", all.len());
|
||||
debug!(
|
||||
"Loaded {} nightlies from the manifest and manual additions",
|
||||
all.len()
|
||||
);
|
||||
Ok(Self { all })
|
||||
}
|
||||
|
||||
|
|
|
|||
105
src/web.rs
105
src/web.rs
|
|
@ -4,7 +4,7 @@ use axum::{
|
|||
extract::{Query, State},
|
||||
http::StatusCode,
|
||||
response::{Html, IntoResponse, Response},
|
||||
routing::{get, post},
|
||||
routing::get,
|
||||
Json, Router,
|
||||
};
|
||||
use color_eyre::{eyre::Context, Result};
|
||||
|
|
@ -23,11 +23,11 @@ pub async fn webserver(db: Db) -> Result<()> {
|
|||
.route("/", get(web_root))
|
||||
.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))
|
||||
.route("/trigger-build", post(trigger_build))
|
||||
.with_state(AppState { db });
|
||||
|
||||
info!("Serving website on port 3000 (commit {})", crate::VERSION);
|
||||
|
|
@ -144,24 +144,95 @@ async fn web_target(State(state): State<AppState>, Query(query): Query<TargetQue
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct NightlyQuery {
|
||||
nightly: String,
|
||||
}
|
||||
|
||||
async fn web_nightly(State(state): State<AppState>, Query(query): Query<NightlyQuery>) -> Response {
|
||||
use askama::Template;
|
||||
#[derive(askama::Template)]
|
||||
#[template(path = "nightly.html")]
|
||||
struct NightlyPage {
|
||||
nightly: String,
|
||||
version: &'static str,
|
||||
builds: Vec<(String, Option<BuildInfo>, Option<BuildInfo>)>,
|
||||
core_failures: usize,
|
||||
std_failures: usize,
|
||||
}
|
||||
|
||||
match state.db.history_for_nightly(&query.nightly).await {
|
||||
Ok(builds) => {
|
||||
let mut builds_grouped =
|
||||
HashMap::<String, (Option<BuildInfo>, Option<BuildInfo>)>::new();
|
||||
for build in &builds {
|
||||
let v = builds_grouped.entry(build.target.clone()).or_default();
|
||||
match build.mode {
|
||||
BuildMode::Core => v.0 = Some(build.clone()),
|
||||
BuildMode::MiriStd => v.1 = Some(build.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
let mut std_failures = 0;
|
||||
let mut core_failures = 0;
|
||||
for build in builds {
|
||||
if build.status == Status::Error {
|
||||
match build.mode {
|
||||
BuildMode::Core => core_failures += 1,
|
||||
BuildMode::MiriStd => std_failures += 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut builds = builds_grouped
|
||||
.into_iter()
|
||||
.map(|(k, (v1, v2))| (k, v1, v2))
|
||||
.collect::<Vec<_>>();
|
||||
builds.sort_by_cached_key(|build| build.0.clone());
|
||||
|
||||
let page = NightlyPage {
|
||||
nightly: query.nightly,
|
||||
version: crate::VERSION,
|
||||
builds,
|
||||
std_failures,
|
||||
core_failures,
|
||||
};
|
||||
|
||||
Html(page.render().unwrap()).into_response()
|
||||
}
|
||||
Err(err) => {
|
||||
error!(?err, "Error loading target state");
|
||||
StatusCode::INTERNAL_SERVER_ERROR.into_response()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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) => {
|
||||
let page = RootPage {
|
||||
targets,
|
||||
version: crate::VERSION,
|
||||
};
|
||||
Ok(targets) => match state.db.nightly_list().await {
|
||||
Ok(nightlies) => {
|
||||
let page = RootPage {
|
||||
targets,
|
||||
nightlies,
|
||||
version: crate::VERSION,
|
||||
};
|
||||
|
||||
Html(page.render().unwrap()).into_response()
|
||||
}
|
||||
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()
|
||||
|
|
@ -203,22 +274,6 @@ struct TriggerBuildBody {
|
|||
nightly: String,
|
||||
}
|
||||
|
||||
#[axum::debug_handler]
|
||||
async fn trigger_build(
|
||||
State(_state): State<AppState>,
|
||||
_body: Json<TriggerBuildBody>,
|
||||
) -> StatusCode {
|
||||
return StatusCode::BAD_REQUEST;
|
||||
// tokio::spawn(async move {
|
||||
// let result = build::build_every_target_for_toolchain(&state.db, &body.nightly).await;
|
||||
// if let Err(err) = result {
|
||||
// error!(?err, "Error while building");
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// StatusCode::ACCEPTED
|
||||
}
|
||||
|
||||
impl Status {
|
||||
fn to_emoji(&self) -> &'static str {
|
||||
match self {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue