Skip to content

Commit 210e150

Browse files
committed
wip
1 parent a3d07d3 commit 210e150

File tree

1 file changed

+126
-31
lines changed

1 file changed

+126
-31
lines changed

src/web/build_details.rs

+126-31
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,13 @@ 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);
99104
let all_log_filenames: Vec<_> = storage
100105
.list_prefix(&prefix) // the result from S3 is ordered by key
@@ -107,42 +112,34 @@ pub(crate) async fn build_details_handler(
107112
.try_collect()
108113
.await?;
109114

110-
let fetch_file = |filename: String| async {
111-
let file = File::from_path(&storage, &format!("{prefix}{filename}"), &config).await?;
112-
Ok::<_, anyhow::Error>(String::from_utf8(file.0.content).context("non utf8")?)
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+
}
127+
} else {
128+
// this can only happen when `releases.default_target` is NULL,
129+
// which is the case for in-progress builds or builds which errored
130+
// before we could determine the target.
131+
// For the "error" case we show `row.errors`, which should contain what we need to see.
132+
None
113133
};
114134

115-
let (filename, file_content) = if let Some(filename) = params.filename {
116-
(Some(filename.clone()), fetch_file(filename.clone()).await?)
117-
} else if let Some(default_target) = row.default_target {
118-
let filename = format!("{default_target}.txt");
119-
(
120-
Some(filename),
121-
match fetch_file(filename.clone()).await {
122-
Ok(content) => content,
123-
Err(_err) => "".to_string(),
124-
},
125-
)
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")?
126138
} else {
127-
(None, "".into())
139+
"".to_string()
128140
};
129141

130-
// .or(row.default_target.map(|target| format!("{}.txt", target)))
131-
// {
132-
// let path = format!("{prefix}{current_filename}");
133-
// let file = File::from_path(&storage, &path, &config).await?;
134-
// (
135-
// String::from_utf8(file.0.content).context("non utf8")?,
136-
// Some(current_filename),
137-
// )
138-
// } else {
139-
// // this can only happen when `releases.default_target` is NULL,
140-
// // which is the case for in-progress builds or builds which errored
141-
// // before we could determine the target.
142-
// // For the "error" case we show `row.errors`, which should contain what we need to see.
143-
// ("".into(), Vec::new(), None)
144-
// }
145-
(file_content, all_log_filenames, filename)
142+
(file_content, all_log_filenames, current_filename)
146143
};
147144

148145
Ok(BuildDetailsPage {
@@ -216,6 +213,44 @@ mod tests {
216213
});
217214
}
218215

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+
219254
#[test]
220255
fn db_build_logs() {
221256
async_wrapper(|env| async move {
@@ -308,6 +343,66 @@ mod tests {
308343
});
309344
}
310345

346+
// #[test]
347+
// fn build_details_for_build_with_pre_build_errors() {
348+
// async_wrapper(|env| async move {
349+
// let mut conn = env.async_db().await.async_conn().await;
350+
// let (release_id, build_id) =
351+
// fake_release_that_failed_before_build(&mut conn, "foo", "0.1.0", "some error")
352+
// .await?;
353+
354+
// let web = env.web_app().await;
355+
356+
// let page = kuchikiki::parse_html().one(
357+
// web.get("/crate/foo/0.1.0/builds")
358+
// .await?
359+
// .error_for_status()?
360+
// .text()
361+
// .await?,
362+
// );
363+
364+
// let node = page.select("ul > li a.release").unwrap().next().unwrap();
365+
// let build_url = {
366+
// let attrs = node.attributes.borrow();
367+
// attrs.get("href").unwrap().to_owned()
368+
// };
369+
370+
// let page = kuchikiki::parse_html().one(
371+
// web.get(&build_url)
372+
// .await?
373+
// .error_for_status()?
374+
// .text()
375+
// .await?,
376+
// );
377+
378+
// let log = page.select("pre").unwrap().next().unwrap().text_contents();
379+
380+
// assert!(log.contains("some error"));
381+
382+
// let all_log_links = get_all_log_links(&page);
383+
// assert_eq!(
384+
// all_log_links,
385+
// vec![(
386+
// "x86_64-unknown-linux-gnu.txt".into(),
387+
// format!("{build_url}/x86_64-unknown-linux-gnu.txt")
388+
// )]
389+
// );
390+
391+
// // now get the log with the specific filename in the URL
392+
// let log = kuchikiki::parse_html()
393+
// .one(web.get(&all_log_links[0].1).await?.text().await?)
394+
// .select("pre")
395+
// .unwrap()
396+
// .next()
397+
// .unwrap()
398+
// .text_contents();
399+
400+
// assert!(log.contains("some error"));
401+
402+
// Ok(())
403+
// });
404+
// }
405+
311406
#[test]
312407
fn s3_build_logs_multiple_targets() {
313408
async_wrapper(|env| async move {

0 commit comments

Comments
 (0)