xtask/cmd/change_logs/
check_pr.rs1use std::collections::HashSet;
2use std::path::PathBuf;
3
4use anyhow::Context;
5
6use super::util::Fragment;
7use crate::cmd::IGNORED_PACKAGES;
8use crate::cmd::change_logs::util::package_to_logs;
9
10#[derive(Debug, Clone, clap::Parser)]
11pub struct CheckPr {
12 pr_number: u64,
14 #[clap(long, default_value = "true", action = clap::ArgAction::Set)]
15 required: bool,
16}
17
18impl CheckPr {
19 pub fn run(self) -> anyhow::Result<()> {
20 let start = std::time::Instant::now();
21
22 let metadata = crate::utils::metadata()?;
23
24 let workspace_package_ids = metadata.workspace_members.iter().cloned().collect::<HashSet<_>>();
25
26 let path = metadata
27 .workspace_root
28 .join("changes.d")
29 .join(format!("pr-{}.toml", self.pr_number));
30
31 eprintln!("checking {path}");
32
33 if !self.required && !path.exists() {
34 return Ok(());
35 }
36
37 let fragment = Fragment::new(self.pr_number, &PathBuf::from(path))?;
38
39 let workspace_package_names = metadata
40 .packages
41 .iter()
42 .filter(|p| workspace_package_ids.contains(&p.id) && !IGNORED_PACKAGES.contains(&p.name.as_str()))
43 .map(|p| p.name.as_str())
44 .collect::<HashSet<_>>();
45
46 let mut has_logs = false;
47
48 for (package, item) in fragment.packages() {
49 anyhow::ensure!(
50 workspace_package_names.contains(package),
51 "package `{}` is not in the workspace",
52 package
53 );
54
55 let logs = package_to_logs(self.pr_number, item.clone()).context("parse")?;
56
57 anyhow::ensure!(!logs.is_empty(), "no change logs found for package `{}`", package);
58
59 has_logs = true;
60 }
61
62 anyhow::ensure!(has_logs, "no change logs found for any package");
63
64 eprintln!("Done in {:?}", start.elapsed());
65
66 Ok(())
67 }
68}