diff --git a/.sqlx/query-64d91ec806ed67d6cffd1a797da5059cc8fb44b37f94dc77877c88d266c5ac9b.json b/.sqlx/query-64d91ec806ed67d6cffd1a797da5059cc8fb44b37f94dc77877c88d266c5ac9b.json new file mode 100644 index 000000000..4eb0f97f7 --- /dev/null +++ b/.sqlx/query-64d91ec806ed67d6cffd1a797da5059cc8fb44b37f94dc77877c88d266c5ac9b.json @@ -0,0 +1,63 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT\n rustc_version,\n docsrs_version,\n build_status as \"build_status: BuildStatus\",\n documentation_size,\n errors,\n rustc_nightly_date\n FROM builds\n WHERE id = $1", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "rustc_version", + "type_info": "Varchar" + }, + { + "ordinal": 1, + "name": "docsrs_version", + "type_info": "Varchar" + }, + { + "ordinal": 2, + "name": "build_status: BuildStatus", + "type_info": { + "Custom": { + "name": "build_status", + "kind": { + "Enum": [ + "in_progress", + "success", + "failure" + ] + } + } + } + }, + { + "ordinal": 3, + "name": "documentation_size", + "type_info": "Int8" + }, + { + "ordinal": 4, + "name": "errors", + "type_info": "Text" + }, + { + "ordinal": 5, + "name": "rustc_nightly_date", + "type_info": "Date" + } + ], + "parameters": { + "Left": [ + "Int4" + ] + }, + "nullable": [ + true, + true, + false, + true, + true, + true + ] + }, + "hash": "64d91ec806ed67d6cffd1a797da5059cc8fb44b37f94dc77877c88d266c5ac9b" +} diff --git a/.sqlx/query-f9151734057f3e6562b1a56d1665ad3707b0ca37bbfca2d75e6e05b350dade04.json b/.sqlx/query-ac2450acd8bbec632668499a18c59644f6cfdc87bd6d280ca8db6a146929c8f5.json similarity index 73% rename from .sqlx/query-f9151734057f3e6562b1a56d1665ad3707b0ca37bbfca2d75e6e05b350dade04.json rename to .sqlx/query-ac2450acd8bbec632668499a18c59644f6cfdc87bd6d280ca8db6a146929c8f5.json index 333b4d146..3d5210ed4 100644 --- a/.sqlx/query-f9151734057f3e6562b1a56d1665ad3707b0ca37bbfca2d75e6e05b350dade04.json +++ b/.sqlx/query-ac2450acd8bbec632668499a18c59644f6cfdc87bd6d280ca8db6a146929c8f5.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "UPDATE builds\n SET\n rustc_version = $1,\n docsrs_version = $2,\n build_status = $3,\n build_server = $4,\n errors = $5,\n documentation_size = $6,\n build_finished = NOW()\n WHERE\n id = $7\n RETURNING rid", + "query": "UPDATE builds\n SET\n rustc_version = $1,\n docsrs_version = $2,\n build_status = $3,\n build_server = $4,\n errors = $5,\n documentation_size = $6,\n rustc_nightly_date = $7,\n build_finished = NOW()\n WHERE\n id = $8\n RETURNING rid", "describe": { "columns": [ { @@ -28,6 +28,7 @@ "Text", "Text", "Int8", + "Date", "Int4" ] }, @@ -35,5 +36,5 @@ false ] }, - "hash": "f9151734057f3e6562b1a56d1665ad3707b0ca37bbfca2d75e6e05b350dade04" + "hash": "ac2450acd8bbec632668499a18c59644f6cfdc87bd6d280ca8db6a146929c8f5" } diff --git a/.sqlx/query-c955871bcda914feac9cfb23fe010399c0b3f75e92ac425fa4ec337e9b250c26.json b/.sqlx/query-c955871bcda914feac9cfb23fe010399c0b3f75e92ac425fa4ec337e9b250c26.json new file mode 100644 index 000000000..61ff84b5f --- /dev/null +++ b/.sqlx/query-c955871bcda914feac9cfb23fe010399c0b3f75e92ac425fa4ec337e9b250c26.json @@ -0,0 +1,57 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT\n rustc_version,\n docsrs_version,\n build_status as \"build_status: BuildStatus\",\n errors,\n rustc_nightly_date\n FROM builds\n WHERE id = $1", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "rustc_version", + "type_info": "Varchar" + }, + { + "ordinal": 1, + "name": "docsrs_version", + "type_info": "Varchar" + }, + { + "ordinal": 2, + "name": "build_status: BuildStatus", + "type_info": { + "Custom": { + "name": "build_status", + "kind": { + "Enum": [ + "in_progress", + "success", + "failure" + ] + } + } + } + }, + { + "ordinal": 3, + "name": "errors", + "type_info": "Text" + }, + { + "ordinal": 4, + "name": "rustc_nightly_date", + "type_info": "Date" + } + ], + "parameters": { + "Left": [ + "Int4" + ] + }, + "nullable": [ + true, + true, + false, + true, + true + ] + }, + "hash": "c955871bcda914feac9cfb23fe010399c0b3f75e92ac425fa4ec337e9b250c26" +} diff --git a/migrations/20241018052241_builds-rustc-nightly-date.down.sql b/migrations/20241018052241_builds-rustc-nightly-date.down.sql new file mode 100644 index 000000000..1214744df --- /dev/null +++ b/migrations/20241018052241_builds-rustc-nightly-date.down.sql @@ -0,0 +1,4 @@ +DROP INDEX builds_nightly_date_idx; + +ALTER TABLE builds + DROP COLUMN rustc_nightly_date; diff --git a/migrations/20241018052241_builds-rustc-nightly-date.up.sql b/migrations/20241018052241_builds-rustc-nightly-date.up.sql new file mode 100644 index 000000000..166fae558 --- /dev/null +++ b/migrations/20241018052241_builds-rustc-nightly-date.up.sql @@ -0,0 +1,8 @@ +ALTER TABLE builds + ADD COLUMN rustc_nightly_date DATE; + +CREATE INDEX builds_nightly_date_idx ON builds USING btree (rustc_nightly_date); + +UPDATE builds + SET rustc_nightly_date = CAST(SUBSTRING(rustc_version FROM ' (\d+-\d+-\d+)\)$') AS DATE) + WHERE rustc_version IS NOT NULL; diff --git a/src/db/add_package.rs b/src/db/add_package.rs index 4182f0697..ac6eed8b6 100644 --- a/src/db/add_package.rs +++ b/src/db/add_package.rs @@ -4,7 +4,7 @@ use crate::{ error::Result, registry_api::{CrateData, CrateOwner, ReleaseData}, storage::CompressionAlgorithm, - utils::MetadataPackage, + utils::{rustc_version::parse_rustc_date, MetadataPackage}, web::crate_details::{latest_release, releases_for_crate}, }; use anyhow::Context; @@ -17,7 +17,7 @@ use std::{ io::{BufRead, BufReader}, path::Path, }; -use tracing::{debug, info, instrument}; +use tracing::{debug, error, info, instrument}; /// Adds a package into database. /// @@ -248,6 +248,20 @@ pub(crate) async fn finish_build( debug!("updating build after finishing"); let hostname = hostname::get()?; + let rustc_date = match parse_rustc_date(rustc_version) { + Ok(date) => Some(date), + Err(err) => { + // in the database we see cases where the rustc version is missing + // in the builds-table. In this case & if we can't parse the version + // we just want to log an error, but still finish the build. + error!( + "Failed to parse date from rustc version \"{}\": {:?}", + rustc_version, err + ); + None + } + }; + let release_id = sqlx::query_scalar!( "UPDATE builds SET @@ -257,9 +271,10 @@ pub(crate) async fn finish_build( build_server = $4, errors = $5, documentation_size = $6, + rustc_nightly_date = $7, build_finished = NOW() WHERE - id = $7 + id = $8 RETURNING rid", rustc_version, docsrs_version, @@ -267,6 +282,7 @@ pub(crate) async fn finish_build( hostname.to_str().unwrap_or(""), errors, documentation_size.map(|v| v as i64), + rustc_date, build_id, ) .fetch_one(&mut *conn) @@ -612,6 +628,7 @@ mod test { use crate::registry_api::OwnerKind; use crate::test::*; use crate::utils::CargoMetadata; + use chrono::NaiveDate; use test_case::test_case; #[test] @@ -649,7 +666,56 @@ mod test { } #[test] - fn test_finish_build_success() { + fn test_finish_build_success_valid_rustc_date() { + async_wrapper(|env| async move { + let mut conn = env.async_db().await.async_conn().await; + let crate_id = initialize_crate(&mut conn, "krate").await?; + let release_id = initialize_release(&mut conn, crate_id, "0.1.0").await?; + let build_id = initialize_build(&mut conn, release_id).await?; + + finish_build( + &mut conn, + build_id, + "rustc 1.84.0-nightly (e7c0d2750 2024-10-15)", + "docsrs_version", + BuildStatus::Success, + None, + None, + ) + .await?; + + let row = sqlx::query!( + r#"SELECT + rustc_version, + docsrs_version, + build_status as "build_status: BuildStatus", + errors, + rustc_nightly_date + FROM builds + WHERE id = $1"#, + build_id + ) + .fetch_one(&mut *conn) + .await?; + + assert_eq!( + row.rustc_version, + Some("rustc 1.84.0-nightly (e7c0d2750 2024-10-15)".into()) + ); + assert_eq!(row.docsrs_version, Some("docsrs_version".into())); + assert_eq!(row.build_status, BuildStatus::Success); + assert_eq!( + row.rustc_nightly_date, + Some(NaiveDate::from_ymd_opt(2024, 10, 15).unwrap()) + ); + assert!(row.errors.is_none()); + + Ok(()) + }) + } + + #[test] + fn test_finish_build_success_invalid_rustc_date() { async_wrapper(|env| async move { let mut conn = env.async_db().await.async_conn().await; let crate_id = initialize_crate(&mut conn, "krate").await?; @@ -673,7 +739,8 @@ mod test { docsrs_version, build_status as "build_status: BuildStatus", documentation_size, - errors + errors, + rustc_nightly_date FROM builds WHERE id = $1"#, build_id @@ -685,6 +752,7 @@ mod test { assert_eq!(row.docsrs_version, Some("docsrs_version".into())); assert_eq!(row.build_status, BuildStatus::Success); assert_eq!(row.documentation_size, Some(42)); + assert!(row.rustc_nightly_date.is_none()); assert!(row.errors.is_none()); Ok(()) diff --git a/src/utils/mod.rs b/src/utils/mod.rs index d591b9404..34352a483 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -21,7 +21,7 @@ pub mod daemon; mod html; mod queue; pub(crate) mod queue_builder; -mod rustc_version; +pub(crate) mod rustc_version; use anyhow::Result; use serde::de::DeserializeOwned; use serde::Serialize; diff --git a/src/utils/rustc_version.rs b/src/utils/rustc_version.rs index be318f1d6..59d201525 100644 --- a/src/utils/rustc_version.rs +++ b/src/utils/rustc_version.rs @@ -21,7 +21,7 @@ pub fn parse_rustc_version>(version: S) -> Result { )) } -fn parse_rustc_date>(version: S) -> Result { +pub(crate) fn parse_rustc_date>(version: S) -> Result { static RE: Lazy = Lazy::new(|| Regex::new(r" (\d+)-(\d+)-(\d+)\)$").unwrap()); let cap = RE