Skip to main content

callisto_graph/
infer.rs

1use std::path::PathBuf;
2
3#[cfg(feature = "inference")]
4use callisto_model::CommandRunner;
5use callisto_model::{CommitSha, Package, Severity, Version};
6
7use crate::config::PreMajorInferencePolicy;
8use crate::error::GraphError;
9
10pub trait SeverityInference: Send + Sync {
11    fn infer(
12        &self,
13        pkg: &Package,
14        window: InferenceWindowSpec<'_>,
15    ) -> Result<Option<InferenceOutcome>, GraphError>;
16}
17
18pub struct InferenceWindowSpec<'a> {
19    pub pathspecs: &'a [PathBuf],
20    pub since: Option<CommitSha>,
21    pub current_version: &'a Version,
22    pub has_prior_release: bool,
23    pub policy: PreMajorInferencePolicy,
24}
25
26#[derive(Clone, Debug, PartialEq, Eq)]
27pub struct InferenceOutcome {
28    pub severity: Severity,
29    pub commit_count: usize,
30    pub remapped: bool,
31    pub commits: Vec<(CommitSha, String)>,
32}
33
34pub struct NoInference;
35
36impl SeverityInference for NoInference {
37    fn infer(
38        &self,
39        _pkg: &Package,
40        _window: InferenceWindowSpec<'_>,
41    ) -> Result<Option<InferenceOutcome>, GraphError> {
42        Ok(None)
43    }
44}
45
46#[cfg(feature = "inference")]
47pub struct CommitInference<'a, R: CommandRunner> {
48    pub runner: &'a R,
49    pub root: PathBuf,
50}
51
52#[cfg(feature = "inference")]
53impl<'a, R: CommandRunner> SeverityInference for CommitInference<'a, R> {
54    fn infer(
55        &self,
56        pkg: &Package,
57        window: InferenceWindowSpec<'_>,
58    ) -> Result<Option<InferenceOutcome>, GraphError> {
59        use callisto_conventional::{infer_severity, InferenceInput, InferenceWindow};
60
61        let inf_window = match window.since {
62            Some(sha) => InferenceWindow::SinceCommit(sha),
63            None => InferenceWindow::FullHistory,
64        };
65
66        let input = InferenceInput {
67            package: &pkg.id,
68            pathspecs: window.pathspecs,
69            window: inf_window,
70            current_version: window.current_version,
71            has_prior_release: window.has_prior_release,
72        };
73
74        let raw = infer_severity(self.runner, &self.root, &input)?;
75        if raw.commit_count == 0 {
76            return Ok(None);
77        }
78
79        let (severity, remapped) = crate::aggregate::apply_pre_major(
80            raw.severity,
81            window.policy,
82            window.current_version,
83            window.has_prior_release,
84        );
85
86        let commits = raw
87            .commits
88            .into_iter()
89            .map(|c| (c.sha().clone(), c.subject().to_string()))
90            .collect();
91
92        Ok(Some(InferenceOutcome {
93            severity,
94            commit_count: raw.commit_count,
95            remapped,
96            commits,
97        }))
98    }
99}