mirror of
https://github.com/Noratrieb/does-it-build.git
synced 2026-01-14 18:35:01 +01:00
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:
parent
3f302c7180
commit
f6fac25c6f
4 changed files with 94 additions and 35 deletions
39
src/db.rs
39
src/db.rs
|
|
@ -82,6 +82,17 @@ pub struct FinishedNightlyWithBroken {
|
||||||
pub broken_error: Option<String>,
|
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 {
|
impl Db {
|
||||||
pub async fn open(path: &str) -> Result<Self> {
|
pub async fn open(path: &str) -> Result<Self> {
|
||||||
let db_opts = SqliteConnectOptions::from_str(path)
|
let db_opts = SqliteConnectOptions::from_str(path)
|
||||||
|
|
@ -168,6 +179,34 @@ impl Db {
|
||||||
.map(|elems| elems.into_iter().map(|elem| elem.nightly).collect())
|
.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(
|
pub async fn build_status_full(
|
||||||
&self,
|
&self,
|
||||||
nightly: &str,
|
nightly: &str,
|
||||||
|
|
|
||||||
67
src/web.rs
67
src/web.rs
|
|
@ -11,7 +11,7 @@ use color_eyre::{eyre::Context, Result};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tracing::{error, info};
|
use tracing::{error, info};
|
||||||
|
|
||||||
use crate::db::{BuildInfo, BuildMode, Db, Status};
|
use crate::db::{BuildInfo, BuildMode, BuildStats, Db, Status};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct AppState {
|
pub struct AppState {
|
||||||
|
|
@ -25,6 +25,7 @@ pub async fn webserver(db: Db) -> Result<()> {
|
||||||
.route("/target", get(web_target))
|
.route("/target", get(web_target))
|
||||||
.route("/nightly", get(web_nightly))
|
.route("/nightly", get(web_nightly))
|
||||||
.route("/index.css", get(index_css))
|
.route("/index.css", get(index_css))
|
||||||
|
.route("/index.js", get(index_js))
|
||||||
.with_state(AppState { db });
|
.with_state(AppState { db });
|
||||||
|
|
||||||
info!("Serving website on port 3000 (commit {})", crate::VERSION);
|
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 {
|
async fn web_root(State(state): State<AppState>) -> impl IntoResponse {
|
||||||
use askama::Template;
|
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 {
|
async fn render(state: AppState) -> Result<Response> {
|
||||||
Ok(targets) => match state.db.nightly_list().await {
|
#[derive(askama::Template)]
|
||||||
Ok(nightlies) => {
|
#[template(path = "index.html")]
|
||||||
let page = RootPage {
|
struct RootPage {
|
||||||
targets,
|
targets: Vec<String>,
|
||||||
nightlies,
|
nightlies: Vec<String>,
|
||||||
version: crate::VERSION,
|
version: &'static str,
|
||||||
};
|
build_count: BuildStats,
|
||||||
|
|
||||||
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()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
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)]
|
#[derive(Serialize, Deserialize)]
|
||||||
struct TriggerBuildBody {
|
struct TriggerBuildBody {
|
||||||
nightly: String,
|
nightly: String,
|
||||||
|
|
|
||||||
4
static/index.js
Normal file
4
static/index.js
Normal 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));
|
||||||
|
});
|
||||||
|
|
@ -5,21 +5,24 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Does it build?</title>
|
<title>Does it build?</title>
|
||||||
<link rel="stylesheet" href="index.css" />
|
<link rel="stylesheet" href="index.css" />
|
||||||
<style></style>
|
<script type="module" defer src="index.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>Does it build?</h1>
|
<h1>Does it build?</h1>
|
||||||
<p>
|
<p>
|
||||||
This website builds every rustc target on many nightlies to check which
|
This website builds the standard libary for every rustc target on every
|
||||||
ones work and which ones do not.
|
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>
|
||||||
|
|
||||||
<p>You can select a target from the list below and check its history.</p>
|
|
||||||
<p>
|
<p>
|
||||||
If that is not what you want, you can visit the
|
You can select a nightly or target from the list below and check its
|
||||||
<a href="full-table">full table</a> to see
|
history.
|
||||||
<strong>all</strong> information at once (which will really stress test
|
|
||||||
your browser).
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h1>Nightlies</h1>
|
<h1>Nightlies</h1>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue