@@ -581,7 +581,32 @@ impl RustwideBuilder {
581581 None
582582 } ;
583583
584- let has_examples = build. host_source_dir ( ) . join ( "examples" ) . is_dir ( ) ;
584+ let mut async_conn = self . runtime . block_on ( self . db . get_async ( ) ) ?;
585+
586+ self . runtime . block_on ( finish_build (
587+ & mut async_conn,
588+ build_id,
589+ & res. result . rustc_version ,
590+ & res. result . docsrs_version ,
591+ if res. result . successful {
592+ BuildStatus :: Success
593+ } else {
594+ BuildStatus :: Failure
595+ } ,
596+ documentation_size,
597+ None ,
598+ ) ) ?;
599+
600+ {
601+ let _span = info_span ! ( "store_build_logs" ) . entered ( ) ;
602+ let build_log_path = format ! ( "build-logs/{build_id}/{default_target}.txt" ) ;
603+ self . storage . store_one ( build_log_path, res. build_log ) ?;
604+ for ( target, log) in target_build_logs {
605+ let build_log_path = format ! ( "build-logs/{build_id}/{target}.txt" ) ;
606+ self . storage . store_one ( build_log_path, log) ?;
607+ }
608+ }
609+
585610 if res. result . successful {
586611 self . metrics . successful_builds . inc ( ) ;
587612 } else if res. cargo_metadata . root ( ) . is_library ( ) {
@@ -611,8 +636,26 @@ impl RustwideBuilder {
611636 let cargo_metadata = res. cargo_metadata . root ( ) ;
612637 let repository = self . get_repo ( cargo_metadata) ?;
613638
614- let mut async_conn = self . runtime . block_on ( self . db . get_async ( ) ) ?;
639+ // when we have an unsuccessful build, but the release was already successfullly
640+ // built in the past, don't touch the release record so the docs stay intact.
641+ // This mainly happens with manually triggered or automated rebuilds.
642+ // The `release_build_status` table is already updated with the information from
643+ // the current build via `finish_build`.
644+ let current_release_build_status = self . runtime . block_on ( sqlx:: query_scalar!(
645+ r#"
646+ SELECT build_status AS "build_status: BuildStatus"
647+ FROM release_build_status
648+ WHERE rid = $1
649+ "# ,
650+ release_id. 0 ,
651+ ) . fetch_optional ( & mut * async_conn) ) ?;
652+
653+ if !res. result . successful && current_release_build_status == Some ( BuildStatus :: Success ) {
654+ info ! ( "build was unsuccessful, but the release was already successfully built in the past. Skipping release record update." ) ;
655+ return Ok ( false ) ;
656+ }
615657
658+ let has_examples = build. host_source_dir ( ) . join ( "examples" ) . is_dir ( ) ;
616659 self . runtime . block_on ( finish_release (
617660 & mut async_conn,
618661 crate_id,
@@ -639,31 +682,6 @@ impl RustwideBuilder {
639682 ) ) ?;
640683 }
641684
642- let build_status = if res. result . successful {
643- BuildStatus :: Success
644- } else {
645- BuildStatus :: Failure
646- } ;
647- self . runtime . block_on ( finish_build (
648- & mut async_conn,
649- build_id,
650- & res. result . rustc_version ,
651- & res. result . docsrs_version ,
652- build_status,
653- documentation_size,
654- None ,
655- ) ) ?;
656-
657- {
658- let _span = info_span ! ( "store_build_logs" ) . entered ( ) ;
659- let build_log_path = format ! ( "build-logs/{build_id}/{default_target}.txt" ) ;
660- self . storage . store_one ( build_log_path, res. build_log ) ?;
661- for ( target, log) in target_build_logs {
662- let build_log_path = format ! ( "build-logs/{build_id}/{target}.txt" ) ;
663- self . storage . store_one ( build_log_path, log) ?;
664- }
665- }
666-
667685 // Some crates.io crate data is mutable, so we proactively update it during a release
668686 if !is_local {
669687 match self
@@ -1023,8 +1041,12 @@ impl Default for BuildPackageSummary {
10231041
10241042#[ cfg( test) ]
10251043mod tests {
1044+ use std:: iter;
1045+
10261046 use super :: * ;
10271047 use crate :: db:: types:: Feature ;
1048+ use crate :: registry_api:: ReleaseData ;
1049+ use crate :: storage:: CompressionAlgorithm ;
10281050 use crate :: test:: { wrapper, AxumRouterTestExt , TestEnvironment } ;
10291051
10301052 fn get_features (
@@ -1297,6 +1319,91 @@ mod tests {
12971319 } )
12981320 }
12991321
1322+ #[ test]
1323+ #[ ignore]
1324+ fn test_failed_build_with_existing_successful_release ( ) {
1325+ wrapper ( |env| {
1326+ // rand 0.8.5 fails to build with recent nightly versions
1327+ // https://github.com/rust-lang/docs.rs/issues/26750
1328+ let crate_ = "rand" ;
1329+ let version = "0.8.5" ;
1330+
1331+ // create a successful release & build in the database
1332+ let release_id = env. runtime ( ) . block_on ( async {
1333+ let mut conn = env. async_db ( ) . await . async_conn ( ) . await ;
1334+ let crate_id = initialize_crate ( & mut conn, crate_) . await ?;
1335+ let release_id = initialize_release ( & mut conn, crate_id, version) . await ?;
1336+ let build_id = initialize_build ( & mut conn, release_id) . await ?;
1337+ finish_build (
1338+ & mut conn,
1339+ build_id,
1340+ "some-version" ,
1341+ "other-version" ,
1342+ BuildStatus :: Success ,
1343+ None ,
1344+ None ,
1345+ )
1346+ . await ?;
1347+ finish_release (
1348+ & mut conn,
1349+ crate_id,
1350+ release_id,
1351+ & MetadataPackage :: default ( ) ,
1352+ Path :: new ( "/unknown/" ) ,
1353+ "x86_64-unknown-linux-gnu" ,
1354+ serde_json:: Value :: Array ( vec ! [ ] ) ,
1355+ vec ! [
1356+ "i686-pc-windows-msvc" . into( ) ,
1357+ "i686-unknown-linux-gnu" . into( ) ,
1358+ "x86_64-apple-darwin" . into( ) ,
1359+ "x86_64-pc-windows-msvc" . into( ) ,
1360+ "x86_64-unknown-linux-gnu" . into( ) ,
1361+ ] ,
1362+ & ReleaseData :: default ( ) ,
1363+ true ,
1364+ false ,
1365+ iter:: once ( CompressionAlgorithm :: Bzip2 ) ,
1366+ None ,
1367+ true ,
1368+ 42 ,
1369+ )
1370+ . await ?;
1371+
1372+ Ok :: < _ , anyhow:: Error > ( release_id)
1373+ } ) ?;
1374+
1375+ fn check_rustdoc_status ( env : & TestEnvironment , rid : ReleaseId ) -> Result < ( ) > {
1376+ assert_eq ! (
1377+ env. runtime( ) . block_on( async {
1378+ let mut conn = env. async_db( ) . await . async_conn( ) . await ;
1379+ sqlx:: query_scalar!(
1380+ "SELECT rustdoc_status FROM releases WHERE id = $1" ,
1381+ rid. 0
1382+ )
1383+ . fetch_one( & mut * conn)
1384+ . await
1385+ } ) ?,
1386+ Some ( true )
1387+ ) ;
1388+ Ok ( ( ) )
1389+ }
1390+
1391+ check_rustdoc_status ( env, release_id) ?;
1392+
1393+ let mut builder = RustwideBuilder :: init ( env) . unwrap ( ) ;
1394+ builder. update_toolchain ( ) ?;
1395+ assert ! (
1396+ // not successful build
1397+ !builder
1398+ . build_package( crate_, version, PackageKind :: CratesIo ) ?
1399+ . successful
1400+ ) ;
1401+
1402+ check_rustdoc_status ( env, release_id) ?;
1403+ Ok ( ( ) )
1404+ } ) ;
1405+ }
1406+
13001407 #[ test]
13011408 #[ ignore]
13021409 fn test_proc_macro ( ) {
0 commit comments