@@ -93,37 +93,53 @@ pub(crate) async fn build_details_handler(
9393 . ok_or ( AxumNope :: BuildNotFound ) ?;
9494
9595 let ( output, all_log_filenames, current_filename) = if let Some ( output) = row. output {
96+ // legacy case, for old builds the build log was stored in the database.
9697 ( output, Vec :: new ( ) , None )
9798 } else {
99+ // for newer builds we have the build logs stored in S3.
100+ // For a long time only for one target, then we started storing the logs for other targets
101+ // toFor a long time only for one target, then we started storing the logs for other
102+ // targets. In any case, all the logfiles are put into a folder we can just query.
98103 let prefix = format ! ( "build-logs/{}/" , id) ;
104+ let all_log_filenames: Vec < _ > = storage
105+ . list_prefix ( & prefix) // the result from S3 is ordered by key
106+ . await
107+ . map_ok ( |path| {
108+ path. strip_prefix ( & prefix)
109+ . expect ( "since we query for the prefix, it has to be always there" )
110+ . to_owned ( )
111+ } )
112+ . try_collect ( )
113+ . await ?;
99114
100- if let Some ( current_filename) = params
101- . filename
102- . or ( row. default_target . map ( |target| format ! ( "{}.txt" , target) ) )
103- {
104- let path = format ! ( "{prefix}{current_filename}" ) ;
105- let file = File :: from_path ( & storage, & path, & config) . await ?;
106- (
107- String :: from_utf8 ( file. 0 . content ) . context ( "non utf8" ) ?,
108- storage
109- . list_prefix ( & prefix) // the result from S3 is ordered by key
110- . await
111- . map_ok ( |path| {
112- path. strip_prefix ( & prefix)
113- . expect ( "since we query for the prefix, it has to be always there" )
114- . to_owned ( )
115- } )
116- . try_collect ( )
117- . await ?,
118- Some ( current_filename) ,
119- )
115+ let current_filename = if let Some ( filename) = params. filename {
116+ // if we have a given filename in the URL, we use that one.
117+ Some ( filename)
118+ } else if let Some ( default_target) = row. default_target {
119+ // without a filename in the URL, we try to show the build log
120+ // for the default target, if we have one.
121+ let wanted_filename = format ! ( "{default_target}.txt" ) ;
122+ if all_log_filenames. contains ( & wanted_filename) {
123+ Some ( wanted_filename)
124+ } else {
125+ None
126+ }
120127 } else {
121128 // this can only happen when `releases.default_target` is NULL,
122129 // which is the case for in-progress builds or builds which errored
123130 // before we could determine the target.
124131 // For the "error" case we show `row.errors`, which should contain what we need to see.
125- ( "" . into ( ) , Vec :: new ( ) , None )
126- }
132+ None
133+ } ;
134+
135+ let file_content = if let Some ( ref filename) = current_filename {
136+ let file = File :: from_path ( & storage, & format ! ( "{prefix}{filename}" ) , & config) . await ?;
137+ String :: from_utf8 ( file. 0 . content ) . context ( "non utf8" ) ?
138+ } else {
139+ "" . to_string ( )
140+ } ;
141+
142+ ( file_content, all_log_filenames, current_filename)
127143 } ;
128144
129145 Ok ( BuildDetailsPage {
@@ -197,6 +213,44 @@ mod tests {
197213 } ) ;
198214 }
199215
216+ #[ test]
217+ fn test_partial_build_result_plus_default_target_from_previous_build ( ) {
218+ async_wrapper ( |env| async move {
219+ let mut conn = env. async_db ( ) . await . async_conn ( ) . await ;
220+ let ( release_id, build_id) = fake_release_that_failed_before_build (
221+ & mut conn,
222+ "foo" ,
223+ "0.1.0" ,
224+ "some random error" ,
225+ )
226+ . await ?;
227+
228+ sqlx:: query!(
229+ "UPDATE releases SET default_target = 'x86_64-unknown-linux-gnu' WHERE id = $1" ,
230+ release_id. 0
231+ )
232+ . execute ( & mut * conn)
233+ . await ?;
234+
235+ let page = kuchikiki:: parse_html ( ) . one (
236+ env. web_app ( )
237+ . await
238+ . get ( & format ! ( "/crate/foo/0.1.0/builds/{build_id}" ) )
239+ . await ?
240+ . error_for_status ( ) ?
241+ . text ( )
242+ . await ?,
243+ ) ;
244+
245+ let info_text = page. select ( "pre" ) . unwrap ( ) . next ( ) . unwrap ( ) . text_contents ( ) ;
246+
247+ assert ! ( info_text. contains( "# pre-build errors" ) , "{}" , info_text) ;
248+ assert ! ( info_text. contains( "some random error" ) , "{}" , info_text) ;
249+
250+ Ok ( ( ) )
251+ } ) ;
252+ }
253+
200254 #[ test]
201255 fn db_build_logs ( ) {
202256 async_wrapper ( |env| async move {
0 commit comments