From 98b86112a120b3f5355a9e4452965f990d6a0ced Mon Sep 17 00:00:00 2001 From: Denis Cornehl Date: Mon, 24 Jun 2024 11:35:40 +0200 Subject: [PATCH] show in-progress builds on build queue page --- ...a8ab868b6d0cc20143b176522c0791a7023c.json} | 4 +- ...42ad45269ad7aab9e9c08fdaa9cb218dbc752.json | 26 ++++++++ ...616e0171b05f09b71795af14270961fa8bd0.json} | 4 +- .../20240624085737_build-status-idx.down.sql | 1 + .../20240624085737_build-status-idx.up.sql | 1 + src/web/builds.rs | 46 +++++++------- src/web/crate_details.rs | 38 +++++------- src/web/mod.rs | 2 +- src/web/releases.rs | 30 +++++++-- templates/crate/builds.html | 9 ++- templates/releases/build_queue.html | 62 +++++++++++++------ templates/style/style.scss | 8 ++- 12 files changed, 152 insertions(+), 79 deletions(-) rename .sqlx/{query-1dae7bb925d677bb997ec28130f7de41c195510e87fa643a4cae57864552962c.json => query-162c05df1f44bb48d087b6e6e4b3a8ab868b6d0cc20143b176522c0791a7023c.json} (90%) create mode 100644 .sqlx/query-3cb4dcb5778c77148aeb8dfc7f942ad45269ad7aab9e9c08fdaa9cb218dbc752.json rename .sqlx/{query-e579486925d3d1927232675b2a03d5f8dd826d7136cdbba1331faf6e64c1f5eb.json => query-771731efe02694173d758c04a4ec616e0171b05f09b71795af14270961fa8bd0.json} (89%) create mode 100644 migrations/20240624085737_build-status-idx.down.sql create mode 100644 migrations/20240624085737_build-status-idx.up.sql diff --git a/.sqlx/query-1dae7bb925d677bb997ec28130f7de41c195510e87fa643a4cae57864552962c.json b/.sqlx/query-162c05df1f44bb48d087b6e6e4b3a8ab868b6d0cc20143b176522c0791a7023c.json similarity index 90% rename from .sqlx/query-1dae7bb925d677bb997ec28130f7de41c195510e87fa643a4cae57864552962c.json rename to .sqlx/query-162c05df1f44bb48d087b6e6e4b3a8ab868b6d0cc20143b176522c0791a7023c.json index 9fc5ed11c..a41680000 100644 --- a/.sqlx/query-1dae7bb925d677bb997ec28130f7de41c195510e87fa643a4cae57864552962c.json +++ b/.sqlx/query-162c05df1f44bb48d087b6e6e4b3a8ab868b6d0cc20143b176522c0791a7023c.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "SELECT\n releases.id,\n releases.version,\n release_build_status.build_status as \"build_status!: BuildStatus\",\n releases.yanked,\n releases.is_library,\n releases.rustdoc_status,\n releases.target_name\n FROM releases\n INNER JOIN release_build_status ON releases.id = release_build_status.rid\n WHERE\n releases.crate_id = $1 AND\n release_build_status.build_status != 'in_progress'", + "query": "SELECT\n releases.id,\n releases.version,\n release_build_status.build_status as \"build_status!: BuildStatus\",\n releases.yanked,\n releases.is_library,\n releases.rustdoc_status,\n releases.target_name\n FROM releases\n INNER JOIN release_build_status ON releases.id = release_build_status.rid\n WHERE\n releases.crate_id = $1", "describe": { "columns": [ { @@ -65,5 +65,5 @@ true ] }, - "hash": "1dae7bb925d677bb997ec28130f7de41c195510e87fa643a4cae57864552962c" + "hash": "162c05df1f44bb48d087b6e6e4b3a8ab868b6d0cc20143b176522c0791a7023c" } diff --git a/.sqlx/query-3cb4dcb5778c77148aeb8dfc7f942ad45269ad7aab9e9c08fdaa9cb218dbc752.json b/.sqlx/query-3cb4dcb5778c77148aeb8dfc7f942ad45269ad7aab9e9c08fdaa9cb218dbc752.json new file mode 100644 index 000000000..0d8bee347 --- /dev/null +++ b/.sqlx/query-3cb4dcb5778c77148aeb8dfc7f942ad45269ad7aab9e9c08fdaa9cb218dbc752.json @@ -0,0 +1,26 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT\n crates.name,\n releases.version\n FROM builds\n INNER JOIN releases ON releases.id = builds.rid\n INNER JOIN crates ON releases.crate_id = crates.id\n WHERE\n builds.build_status = 'in_progress'\n ORDER BY builds.id ASC", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "name", + "type_info": "Text" + }, + { + "ordinal": 1, + "name": "version", + "type_info": "Text" + } + ], + "parameters": { + "Left": [] + }, + "nullable": [ + false, + false + ] + }, + "hash": "3cb4dcb5778c77148aeb8dfc7f942ad45269ad7aab9e9c08fdaa9cb218dbc752" +} diff --git a/.sqlx/query-e579486925d3d1927232675b2a03d5f8dd826d7136cdbba1331faf6e64c1f5eb.json b/.sqlx/query-771731efe02694173d758c04a4ec616e0171b05f09b71795af14270961fa8bd0.json similarity index 89% rename from .sqlx/query-e579486925d3d1927232675b2a03d5f8dd826d7136cdbba1331faf6e64c1f5eb.json rename to .sqlx/query-771731efe02694173d758c04a4ec616e0171b05f09b71795af14270961fa8bd0.json index 92269065c..f4299ecaa 100644 --- a/.sqlx/query-e579486925d3d1927232675b2a03d5f8dd826d7136cdbba1331faf6e64c1f5eb.json +++ b/.sqlx/query-771731efe02694173d758c04a4ec616e0171b05f09b71795af14270961fa8bd0.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "SELECT\n builds.id,\n builds.rustc_version,\n builds.docsrs_version,\n builds.build_status as \"build_status: BuildStatus\",\n builds.build_time,\n builds.errors\n FROM builds\n INNER JOIN releases ON releases.id = builds.rid\n INNER JOIN crates ON releases.crate_id = crates.id\n WHERE\n crates.name = $1 AND\n releases.version = $2 AND\n builds.build_status != 'in_progress'\n ORDER BY id DESC", + "query": "SELECT\n builds.id,\n builds.rustc_version,\n builds.docsrs_version,\n builds.build_status as \"build_status: BuildStatus\",\n builds.build_time,\n builds.errors\n FROM builds\n INNER JOIN releases ON releases.id = builds.rid\n INNER JOIN crates ON releases.crate_id = crates.id\n WHERE\n crates.name = $1 AND\n releases.version = $2\n ORDER BY id DESC", "describe": { "columns": [ { @@ -60,5 +60,5 @@ true ] }, - "hash": "e579486925d3d1927232675b2a03d5f8dd826d7136cdbba1331faf6e64c1f5eb" + "hash": "771731efe02694173d758c04a4ec616e0171b05f09b71795af14270961fa8bd0" } diff --git a/migrations/20240624085737_build-status-idx.down.sql b/migrations/20240624085737_build-status-idx.down.sql new file mode 100644 index 000000000..a2d740337 --- /dev/null +++ b/migrations/20240624085737_build-status-idx.down.sql @@ -0,0 +1 @@ +DROP INDEX builds_build_status_idx; diff --git a/migrations/20240624085737_build-status-idx.up.sql b/migrations/20240624085737_build-status-idx.up.sql new file mode 100644 index 000000000..7525a7442 --- /dev/null +++ b/migrations/20240624085737_build-status-idx.up.sql @@ -0,0 +1 @@ +CREATE INDEX builds_build_status_idx ON builds USING btree (build_status ASC); diff --git a/src/web/builds.rs b/src/web/builds.rs index 45a1b6e3a..c94afe439 100644 --- a/src/web/builds.rs +++ b/src/web/builds.rs @@ -117,7 +117,10 @@ pub(crate) async fn build_list_json_handler( get_builds(&mut conn, &name, &version) .await? .iter() - .map(|build| { + .filter_map(|build| { + if build.build_status == BuildStatus::InProgress { + return None; + } // for backwards compatibility in this API, we // * convert the build status to a boolean // * already filter out in-progress builds @@ -125,13 +128,13 @@ pub(crate) async fn build_list_json_handler( // even when we start showing in-progress builds in the UI, // we might still not show them here for backwards // compatibility. - serde_json::json!({ + Some(serde_json::json!({ "id": build.id, "rustc_version": build.rustc_version, "docsrs_version": build.docsrs_version, "build_status": build.build_status.is_success(), "build_time": build.build_time, - }) + })) }) .collect::>(), ), @@ -255,8 +258,7 @@ async fn get_builds( INNER JOIN crates ON releases.crate_id = crates.id WHERE crates.name = $1 AND - releases.version = $2 AND - builds.build_status != 'in_progress' + releases.version = $2 ORDER BY id DESC"#, name, version.to_string(), @@ -558,29 +560,25 @@ mod tests { let response = env.frontend().get("/crate/foo/0.1.0/builds").send()?; - // FIXME: temporarily we don't show in-progress releases anywhere, which means we don't - // show releases without builds anywhere. - assert_eq!(response.status(), StatusCode::NOT_FOUND); - - // assert_cache_control(&response, CachePolicy::NoCaching, &env.config()); - // let page = kuchikiki::parse_html().one(response.text()?); + assert_cache_control(&response, CachePolicy::NoCaching, &env.config()); + let page = kuchikiki::parse_html().one(response.text()?); - // let rows: Vec<_> = page - // .select("ul > li a.release") - // .unwrap() - // .map(|row| row.text_contents()) - // .collect(); + let rows: Vec<_> = page + .select("ul > li a.release") + .unwrap() + .map(|row| row.text_contents()) + .collect(); - // assert!(rows.is_empty()); + assert!(rows.is_empty()); - // let warning = page - // .select_first(".warning") - // .expect("missing warning element") - // .text_contents(); + let warning = page + .select_first(".warning") + .expect("missing warning element") + .text_contents(); - // assert!(warning.contains("has not built")); - // assert!(warning.contains("queued")); - // assert!(warning.contains("open an issue")); + assert!(warning.contains("has not built")); + assert!(warning.contains("queued")); + assert!(warning.contains("open an issue")); Ok(()) }); diff --git a/src/web/crate_details.rs b/src/web/crate_details.rs index a6218dd9b..06c0f6bfd 100644 --- a/src/web/crate_details.rs +++ b/src/web/crate_details.rs @@ -375,8 +375,7 @@ pub(crate) async fn releases_for_crate( FROM releases INNER JOIN release_build_status ON releases.id = release_build_status.rid WHERE - releases.crate_id = $1 AND - release_build_status.build_status != 'in_progress'"#, + releases.crate_id = $1"#, crate_id, ) .fetch(&mut *conn) @@ -1292,25 +1291,22 @@ mod tests { .create()?; let response = env.frontend().get("/crate/foo/latest").send()?; - // FIXME: temporarily we don't show in-progress releases anywhere, which means we don't - // show releases without builds anywhere. - assert_eq!(response.status(), StatusCode::NOT_FOUND); - - // let page = kuchikiki::parse_html().one(response.text()?); - // let link = page - // .select_first("a.pure-menu-link[href='/crate/foo/0.1.0']") - // .unwrap(); - - // assert_eq!( - // link.as_node() - // .as_element() - // .unwrap() - // .attributes - // .borrow() - // .get("title") - // .unwrap(), - // "foo-0.1.0 is currently being built" - // ); + + let page = kuchikiki::parse_html().one(response.text()?); + let link = page + .select_first("a.pure-menu-link[href='/crate/foo/0.1.0']") + .unwrap(); + + assert_eq!( + link.as_node() + .as_element() + .unwrap() + .attributes + .borrow() + .get("title") + .unwrap(), + "foo-0.1.0 is currently being built" + ); Ok(()) }); diff --git a/src/web/mod.rs b/src/web/mod.rs index b0cc58de6..6020ab139 100644 --- a/src/web/mod.rs +++ b/src/web/mod.rs @@ -308,7 +308,7 @@ async fn match_version( }; // when matching semver requirements, we only want to look at non-yanked releases. - let flt = |r: &&Release| r.yanked == Some(false); + let flt = |r: &&Release| r.yanked.is_none() || r.yanked == Some(false); if let Some(release) = releases .iter() diff --git a/src/web/releases.rs b/src/web/releases.rs index 477a05c80..5f1da59ca 100644 --- a/src/web/releases.rs +++ b/src/web/releases.rs @@ -808,7 +808,8 @@ pub(crate) async fn activity_handler(mut conn: DbConnection) -> AxumResult, - active_deployments: Vec, + active_cdn_deployments: Vec, + in_progress_builds: Vec<(String, String)>, csp_nonce: String, } @@ -823,8 +824,9 @@ impl BuildQueuePage { pub(crate) async fn build_queue_handler( Extension(build_queue): Extension>, Extension(pool): Extension, + mut conn: DbConnection, ) -> AxumResult { - let (queue, active_deployments) = spawn_blocking(move || { + let (queue, active_cdn_deployments) = spawn_blocking(move || { let mut queue = build_queue.queued_crates()?; for krate in queue.iter_mut() { // The priority here is inverted: in the database if a crate has a higher priority it @@ -850,10 +852,28 @@ pub(crate) async fn build_queue_handler( }) .await?; + let in_progress_builds: Vec<(String, String)> = sqlx::query!( + r#"SELECT + crates.name, + releases.version + FROM builds + INNER JOIN releases ON releases.id = builds.rid + INNER JOIN crates ON releases.crate_id = crates.id + WHERE + builds.build_status = 'in_progress' + ORDER BY builds.id ASC"# + ) + .fetch_all(&mut *conn) + .await? + .into_iter() + .map(|rec| (rec.name, rec.version)) + .collect(); + Ok(BuildQueuePage { description: "crate documentation scheduled to build & deploy", queue, - active_deployments, + active_cdn_deployments, + in_progress_builds, csp_nonce: String::new(), }) } @@ -1725,9 +1745,9 @@ mod tests { let empty = kuchikiki::parse_html().one(web.get("/releases/queue").send()?.text()?); assert!(empty - .select(".release > strong") + .select(".release > div > strong") .expect("missing heading") - .any(|el| el.text_contents().contains("active CDN deployments"))); + .any(|el| dbg!(el.text_contents()).contains("active CDN deployments"))); let full = kuchikiki::parse_html().one(web.get("/releases/queue").send()?.text()?); let items = full diff --git a/templates/crate/builds.html b/templates/crate/builds.html index 4c659b8cf..2823c8a75 100644 --- a/templates/crate/builds.html +++ b/templates/crate/builds.html @@ -39,7 +39,11 @@ {%- else -%} - {# FIXME: temporarily this will never be shown since we hide in-progress releases for now #}
docs.rs has not built {{ metadata.name }}-{{ metadata.version }}
diff --git a/templates/releases/build_queue.html b/templates/releases/build_queue.html index 1e93066b4..a1f52534d 100644 --- a/templates/releases/build_queue.html +++ b/templates/releases/build_queue.html @@ -16,34 +16,56 @@ {%- block body -%}
- {%- if !active_deployments.is_empty() %} -
- active CDN deployments +
+
+ currently being built +
+
+ {%- if !active_cdn_deployments.is_empty() %} + active CDN deployments + {%- endif %} +
-
    - {% for krate in active_deployments -%} -
  1. - - {{ krate }} - -
  2. - {%- endfor %} -
+ {%- if !in_progress_builds.is_empty() %} +
    + {% for release in in_progress_builds -%} +
  1. + + {{ release.0 }} {{ release.1 }} + +
  2. + {%- endfor %} +
+ {%- else %} +
+

There is nothing currently being built

+
+ {%- endif %}
-
-

- After the build finishes it may take up to 20 minutes for all documentation - pages to be up-to-date and available to everybody. -

-

Especially /latest/ URLs might be affected.

-
+ {%- if !active_cdn_deployments.is_empty() %} +
    + {% for krate in active_cdn_deployments -%} +
  1. + + {{ krate }} + +
  2. + {%- endfor %} +
+
+

+ After the build finishes it may take up to 20 minutes for all documentation + pages to be up-to-date and available to everybody. +

+

Especially /latest/ URLs might be affected.

+
+ {%- endif %}
- {%- endif %}
Build Queue diff --git a/templates/style/style.scss b/templates/style/style.scss index d5c1a7841..74cdeb921 100644 --- a/templates/style/style.scss +++ b/templates/style/style.scss @@ -280,7 +280,7 @@ div.recent-releases-container { background-color: var(--background-color); } - .release { + .release, .build-in-progress { display: block; border-bottom: 1px solid var(--color-border); padding: 0.4em $search-result-right-left-padding; @@ -297,11 +297,13 @@ div.recent-releases-container { } .release:hover, - a.release:focus { + a.release:focus, + .build-in-progress:hover { background-color: var(--color-background-code); } - li:last-of-type .release { + li:last-of-type .release, + li:last-of-type .build-in-progress { border-bottom: none; }