xtask/cmd/change_logs/
check_pr.rs

1use 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    /// The PR number to check
13    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}