Compare commits

..

No commits in common. "5fb3ca86b273de9cc71564fd86ce14b061453873" and "3f302c71801d6d8bca5baa57becb990aa2729b49" have entirely different histories.

12 changed files with 100 additions and 191 deletions

View file

@ -12,12 +12,6 @@ fn main() {
}; };
println!("cargo:rustc-env=GIT_COMMIT={version}"); println!("cargo:rustc-env=GIT_COMMIT={version}");
let version_short = if version.len() > 16 {
&version[..16]
} else {
&version
};
println!("cargo:rustc-env=GIT_COMMIT_SHORT={version_short}");
} }
fn try_get_commit() -> color_eyre::Result<String> { fn try_get_commit() -> color_eyre::Result<String> {

View file

@ -1,10 +0,0 @@
-- Add migration script here
ALTER TABLE "build_info"
ADD COLUMN "build_date" INTEGER NULL;
ALTER TABLE "build_info"
ADD COLUMN "build_duration_ms" INTEGER NULL;
ALTER TABLE "build_info"
ADD COLUMN "does_it_build_version" VARCHAR NULL;

View file

@ -1,3 +0,0 @@
-- Add migration script here
CREATE INDEX IF NOT EXISTS build_info_status ON build_info (status);

View file

@ -2,7 +2,7 @@ use std::{
fmt::{Debug, Display}, fmt::{Debug, Display},
num::NonZeroUsize, num::NonZeroUsize,
path::Path, path::Path,
time::{Duration, Instant, SystemTime}, time::Duration,
}; };
use color_eyre::{ use color_eyre::{
@ -52,13 +52,6 @@ impl Display for Toolchain {
} }
pub async fn background_builder(db: Db) -> Result<()> { pub async fn background_builder(db: Db) -> Result<()> {
if concurrent_jobs() == 0 {
info!("Suspending background thread since DOES_IT_BUILD_PARALLEL_JOBS=0");
loop {
tokio::time::sleep(Duration::from_secs(3600)).await;
}
}
loop { loop {
if let Err(err) = background_builder_inner(&db).await { if let Err(err) = background_builder_inner(&db).await {
error!("error in background builder: {err}"); error!("error in background builder: {err}");
@ -199,12 +192,21 @@ pub async fn build_every_target_for_toolchain(
.await .await
.wrap_err("failed to get targets")?; .wrap_err("failed to get targets")?;
let concurrent = std::env::var("DOES_IT_BUILD_PARALLEL_JOBS")
.map(|jobs| jobs.parse().unwrap())
.unwrap_or_else(|_| {
std::thread::available_parallelism()
.unwrap_or(NonZeroUsize::new(2).unwrap())
.get()
/ 2
});
let results = futures::stream::iter( let results = futures::stream::iter(
targets targets
.iter() .iter()
.map(|target| build_single_target(db, nightly, target, mode)), .map(|target| build_single_target(db, nightly, target, mode)),
) )
.buffer_unordered(concurrent_jobs()) .buffer_unordered(concurrent)
.collect::<Vec<Result<()>>>() .collect::<Vec<Result<()>>>()
.await; .await;
for result in results { for result in results {
@ -240,8 +242,6 @@ async fn build_single_target(db: &Db, nightly: &str, target: &str, mode: BuildMo
let tmpdir = tempfile::tempdir().wrap_err("creating temporary directory")?; let tmpdir = tempfile::tempdir().wrap_err("creating temporary directory")?;
let start_time = Instant::now();
let result = build_target( let result = build_target(
tmpdir.path(), tmpdir.path(),
&Toolchain::from_nightly(nightly), &Toolchain::from_nightly(nightly),
@ -258,16 +258,6 @@ async fn build_single_target(db: &Db, nightly: &str, target: &str, mode: BuildMo
stderr: result.stderr, stderr: result.stderr,
mode, mode,
rustflags: result.rustflags, rustflags: result.rustflags,
build_date: Some(
SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_millis()
.try_into()
.unwrap(),
),
does_it_build_version: Some(crate::VERSION_SHORT.into()),
build_duration_ms: Some(start_time.elapsed().as_millis().try_into().unwrap()),
}) })
.await?; .await?;
@ -352,14 +342,3 @@ async fn build_target(
rustflags, rustflags,
}) })
} }
fn concurrent_jobs() -> usize {
std::env::var("DOES_IT_BUILD_PARALLEL_JOBS")
.map(|jobs| jobs.parse().unwrap())
.unwrap_or_else(|_| {
std::thread::available_parallelism()
.unwrap_or(NonZeroUsize::new(2).unwrap())
.get()
/ 2
})
}

View file

@ -49,9 +49,6 @@ pub struct FullBuildInfo {
pub stderr: String, pub stderr: String,
pub mode: BuildMode, pub mode: BuildMode,
pub rustflags: Option<String>, pub rustflags: Option<String>,
pub build_date: Option<i64>,
pub does_it_build_version: Option<String>,
pub build_duration_ms: Option<i64>,
} }
#[derive(Debug, PartialEq, Clone, Copy, sqlx::Type, Serialize, Deserialize)] #[derive(Debug, PartialEq, Clone, Copy, sqlx::Type, Serialize, Deserialize)]
@ -85,17 +82,6 @@ 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)
@ -110,8 +96,7 @@ impl Db {
pub async fn insert(&self, info: FullBuildInfo) -> Result<()> { pub async fn insert(&self, info: FullBuildInfo) -> Result<()> {
sqlx::query( sqlx::query(
"INSERT INTO build_info (nightly, target, status, stderr, mode, rustflags, build_date, does_it_build_version, build_duration_ms) \ "INSERT INTO build_info (nightly, target, status, stderr, mode, rustflags) VALUES (?, ?, ?, ?, ?, ?);",
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);",
) )
.bind(info.nightly) .bind(info.nightly)
.bind(info.target) .bind(info.target)
@ -119,9 +104,6 @@ impl Db {
.bind(info.stderr) .bind(info.stderr)
.bind(info.mode) .bind(info.mode)
.bind(info.rustflags) .bind(info.rustflags)
.bind(info.build_date)
.bind(info.does_it_build_version)
.bind(info.build_duration_ms)
.execute(&self.conn) .execute(&self.conn)
.await .await
.wrap_err("inserting build info into database")?; .wrap_err("inserting build info into database")?;
@ -186,34 +168,6 @@ 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,
@ -221,7 +175,7 @@ impl Db {
mode: BuildMode, mode: BuildMode,
) -> Result<Option<FullBuildInfo>> { ) -> Result<Option<FullBuildInfo>> {
let result = sqlx::query_as::<_, FullBuildInfo>( let result = sqlx::query_as::<_, FullBuildInfo>(
"SELECT nightly, target, status, stderr, mode, rustflags, build_date, does_it_build_version, build_duration_ms FROM build_info "SELECT nightly, target, status, stderr, mode, rustflags FROM build_info
WHERE nightly = ? AND target = ? AND mode = ?", WHERE nightly = ? AND target = ? AND mode = ?",
) )
.bind(nightly) .bind(nightly)

View file

@ -8,7 +8,6 @@ use db::Db;
use tracing_subscriber::EnvFilter; use tracing_subscriber::EnvFilter;
const VERSION: &str = env!("GIT_COMMIT"); const VERSION: &str = env!("GIT_COMMIT");
const VERSION_SHORT: &str = env!("GIT_COMMIT_SHORT");
#[tokio::main] #[tokio::main]
async fn main() -> Result<()> { async fn main() -> Result<()> {

View file

@ -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, BuildStats, Db, Status}; use crate::db::{BuildInfo, BuildMode, Db, Status};
#[derive(Clone)] #[derive(Clone)]
pub struct AppState { pub struct AppState {
@ -25,7 +25,6 @@ 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);
@ -53,9 +52,6 @@ async fn web_build(State(state): State<AppState>, Query(query): Query<BuildQuery
rustflags: Option<String>, rustflags: Option<String>,
version: &'static str, version: &'static str,
status: Status, status: Status,
build_date: Option<String>,
build_duration_s: Option<f32>,
does_it_build_version: Option<String>,
} }
match state match state
@ -76,19 +72,6 @@ async fn web_build(State(state): State<AppState>, Query(query): Query<BuildQuery
rustflags: build.rustflags, rustflags: build.rustflags,
version: crate::VERSION, version: crate::VERSION,
status: build.status, status: build.status,
build_date: build.build_date.map(|build_date| {
time::OffsetDateTime::from_unix_timestamp_nanos(build_date as i128 * 1000000)
.map(|build_date| {
build_date
.format(&time::format_description::well_known::Rfc3339)
.unwrap()
})
.unwrap()
}),
build_duration_s: build
.build_duration_ms
.map(|build_duration_ms| (build_duration_ms as f32) / 1000.0),
does_it_build_version: build.does_it_build_version,
}; };
Html(page.render().unwrap()).into_response() Html(page.render().unwrap()).into_response()
} }
@ -274,37 +257,35 @@ 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;
async fn render(state: AppState) -> Result<Response> {
#[derive(askama::Template)] #[derive(askama::Template)]
#[template(path = "index.html")] #[template(path = "index.html")]
struct RootPage { struct RootPage {
targets: Vec<String>, targets: Vec<String>,
nightlies: Vec<String>, nightlies: Vec<String>,
version: &'static str, version: &'static str,
build_count: BuildStats,
} }
let targets = state.db.target_list().await?; match state.db.target_list().await {
let nightlies = state.db.nightly_list().await?; Ok(targets) => match state.db.nightly_list().await {
let build_count = state.db.build_count().await?; Ok(nightlies) => {
let page = RootPage { let page = RootPage {
targets, targets,
nightlies, nightlies,
version: crate::VERSION, version: crate::VERSION,
build_count,
}; };
Ok(Html(page.render().unwrap()).into_response()) Html(page.render().unwrap()).into_response()
} }
Err(err) => {
render(state) error!(?err, "Error loading nightly state");
.await
.unwrap_or_else(|err: color_eyre::eyre::Error| {
error!(?err, "Error loading data for root page");
StatusCode::INTERNAL_SERVER_ERROR.into_response() StatusCode::INTERNAL_SERVER_ERROR.into_response()
}) }
},
Err(err) => {
error!(?err, "Error loading target state");
StatusCode::INTERNAL_SERVER_ERROR.into_response()
}
}
} }
async fn index_css() -> impl IntoResponse { async fn index_css() -> impl IntoResponse {
@ -317,16 +298,6 @@ 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,

View file

@ -1,13 +0,0 @@
// 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));
});
// Do some fancy date formatting in your locale, so you can't blame me if the numbers look ass.
document.querySelectorAll(".date").forEach((elem) => {
console.log("run")
elem.textContent = new Intl.DateTimeFormat(undefined, {
dateStyle: "short",
timeStyle: "short",
}).format(new Date(elem.textContent));
});

View file

@ -5,7 +5,6 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Build {{nightly}} {{target}}</title> <title>Build {{nightly}} {{target}}</title>
<link rel="stylesheet" href="/index.css" /> <link rel="stylesheet" href="/index.css" />
<script type="module" defer src="index.js"></script>
<style> <style>
.build-indicator-big { .build-indicator-big {
padding: 10px; padding: 10px;
@ -22,12 +21,6 @@
<p> <p>
Using rustflags: <b><code>{{rustflags}}</code></b> Using rustflags: <b><code>{{rustflags}}</code></b>
</p> </p>
{% endif %} {% if let Some(build_date) = build_date %}
<p>Build date: <span class="date">{{build_date}}</span></p>
{% endif %} {% if let Some(build_duration_s) = build_duration_s %}
<p>Build duration: <span class="number">{{build_duration_s}}</span>s</p>
{% endif %} {% if let Some(does_it_build_version) = does_it_build_version %}
<p>Builder does-it-build commit: <span>{{does_it_build_version}}</span></p>
{% endif %} {% endif %}
<pre> <pre>
{{stderr}} {{stderr}}
@ -43,8 +36,20 @@
> >
</p> </p>
<footer class="footer"> <footer class="footer">
<span>does-it-build {{version}}</span>
<a href="https://github.com/Noratrieb/does-it-build"> <a href="https://github.com/Noratrieb/does-it-build">
does-it-build {{version}} <svg
viewBox="0 0 16 16"
width="32"
height="32"
aria-labelledby="github-logo-title"
>
<title id="github-logo-title">GitHub</title>
<path
fill="black"
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z"
></path>
</svg>
</a> </a>
</footer> </footer>
</body> </body>

View file

@ -5,24 +5,21 @@
<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" />
<script type="module" defer src="index.js"></script> <style></style>
</head> </head>
<body> <body>
<h1>Does it build?</h1> <h1>Does it build?</h1>
<p> <p>
This website builds the standard libary for every rustc target on every This website builds every rustc target on many nightlies to check which
nightly to check whether it builds or not. ones work and which ones do 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>
You can select a nightly or target from the list below and check its If that is not what you want, you can visit the
history. <a href="full-table">full table</a> to see
<strong>all</strong> information at once (which will really stress test
your browser).
</p> </p>
<h1>Nightlies</h1> <h1>Nightlies</h1>
@ -61,8 +58,20 @@
</section> </section>
<footer class="footer"> <footer class="footer">
<span>does-it-build {{version}}</span>
<a href="https://github.com/Noratrieb/does-it-build"> <a href="https://github.com/Noratrieb/does-it-build">
does-it-build {{version}} <svg
viewBox="0 0 16 16"
width="32"
height="32"
aria-labelledby="github-logo-title"
>
<title id="github-logo-title">GitHub</title>
<path
fill="black"
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z"
></path>
</svg>
</a> </a>
</footer> </footer>
</body> </body>

View file

@ -86,8 +86,20 @@
{% endfor %} {% endfor %}
</table> </table>
<footer class="footer"> <footer class="footer">
<span>does-it-build {{version}}</span>
<a href="https://github.com/Noratrieb/does-it-build"> <a href="https://github.com/Noratrieb/does-it-build">
does-it-build {{version}} <svg
viewBox="0 0 16 16"
width="32"
height="32"
aria-labelledby="github-logo-title"
>
<title id="github-logo-title">GitHub</title>
<path
fill="black"
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z"
></path>
</svg>
</a> </a>
</footer> </footer>
</body> </body>

View file

@ -67,8 +67,20 @@
{% endfor %} {% endfor %}
</table> </table>
<footer class="footer"> <footer class="footer">
<span>does-it-build {{version}}</span>
<a href="https://github.com/Noratrieb/does-it-build"> <a href="https://github.com/Noratrieb/does-it-build">
does-it-build {{version}} <svg
viewBox="0 0 16 16"
width="32"
height="32"
aria-labelledby="github-logo-title"
>
<title id="github-logo-title">GitHub</title>
<path
fill="black"
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z"
></path>
</svg>
</a> </a>
</footer> </footer>
</body> </body>