bb_cli/commands/
pr_build.rs1use crate::api::models::{BuildState, BuildStatus};
2use crate::api::{self, Client};
3use crate::commands::pr::Ctx;
4use crate::error::Result;
5use crate::output::{self, Format};
6use crate::repo::RepoSlug;
7use futures::stream::{self, StreamExt, TryStreamExt};
8use serde::Serialize;
9use std::collections::HashMap;
10
11const MAX_IN_FLIGHT: usize = 8;
15
16pub async fn statuses(client: &Client, slug: &RepoSlug, id: u64) -> Result<Vec<BuildStatus>> {
17 client
18 .paginate(&api::repo_path(
19 slug,
20 &format!("/pullrequests/{id}/statuses"),
21 ))
22 .await
23}
24
25pub async fn statuses_for(
26 client: &Client,
27 slug: &RepoSlug,
28 ids: &[u64],
29) -> Result<HashMap<u64, Vec<BuildStatus>>> {
30 stream::iter(ids.iter().copied())
31 .map(|id| async move { statuses(client, slug, id).await.map(|s| (id, s)) })
32 .buffer_unordered(MAX_IN_FLIGHT)
33 .try_collect()
34 .await
35}
36
37#[derive(Debug, Serialize)]
38struct BuildReport {
39 build_state: BuildState,
40 statuses: Vec<BuildStatus>,
41}
42
43pub async fn run(ctx: &Ctx, id: u64) -> Result<()> {
44 let spinner = output::spinner("fetching build statuses");
45 let found = statuses(&ctx.client, &ctx.slug, id).await?;
46 spinner.finish_and_clear();
47
48 let report = BuildReport {
49 build_state: BuildState::rollup(&found),
50 statuses: found,
51 };
52
53 match ctx.format {
54 Format::Json => output::print_json(&report)?,
55 Format::Human => {
56 output::heading(&format!(
57 "build: {}",
58 output::colored_cell(
59 report.build_state.label(),
60 output::tone_for(report.build_state)
61 )
62 ));
63 if report.statuses.is_empty() {
64 output::info("no build statuses");
65 } else {
66 output::print_table(
67 &["KEY", "NAME", "STATE", "URL"],
68 report
69 .statuses
70 .iter()
71 .map(|s| {
72 let state = BuildState::from_api(s.state.as_deref());
73 vec![
74 s.key.clone().unwrap_or_else(|| "-".into()),
75 s.name.clone().unwrap_or_else(|| "-".into()),
76 output::colored_cell(state.label(), output::tone_for(state)),
77 s.url.clone().unwrap_or_else(|| "-".into()),
78 ]
79 })
80 .collect(),
81 );
82 }
83 }
84 }
85 Ok(())
86}