aivcs_core/multi_repo/
error.rs1use thiserror::Error;
4
5#[derive(Debug, Error)]
7pub enum MultiRepoError {
8 #[error("dependency cycle detected involving repos: {repos:?}")]
10 DependencyCycle { repos: Vec<String> },
11
12 #[error("repo not found in graph: {repo}")]
14 RepoNotFound { repo: String },
15
16 #[error("release sequencing failed for repo {repo}: {reason}")]
18 SequencingFailed { repo: String, reason: String },
19
20 #[error("CI aggregation error for objective '{objective}': {detail}")]
22 AggregationError { objective: String, detail: String },
23
24 #[error("backport failed for commit {commit_sha} → branch {target_branch}: {reason}")]
26 BackportFailed {
27 commit_sha: String,
28 target_branch: String,
29 reason: String,
30 },
31
32 #[error("provenance artifact error: {0}")]
34 Provenance(String),
35
36 #[error("storage error: {0}")]
38 Storage(String),
39
40 #[error("domain error: {0}")]
42 Domain(#[from] crate::domain::error::AivcsError),
43}
44
45pub type MultiRepoResult<T> = std::result::Result<T, MultiRepoError>;
47
48#[cfg(test)]
49mod tests {
50 use super::*;
51
52 #[test]
53 fn test_dependency_cycle_error_displays_repo_names() {
54 let err = MultiRepoError::DependencyCycle {
55 repos: vec!["org/a".to_string(), "org/b".to_string()],
56 };
57 let msg = err.to_string();
58 assert!(msg.contains("org/a"));
59 assert!(msg.contains("org/b"));
60 }
61
62 #[test]
63 fn test_backport_failed_error_displays_commit_and_branch() {
64 let err = MultiRepoError::BackportFailed {
65 commit_sha: "abc123".to_string(),
66 target_branch: "release/1.0".to_string(),
67 reason: "conflict in foo.rs".to_string(),
68 };
69 let msg = err.to_string();
70 assert!(msg.contains("abc123"));
71 assert!(msg.contains("release/1.0"));
72 assert!(msg.contains("conflict"));
73 }
74
75 #[test]
76 fn test_repo_not_found_error_displays_repo() {
77 let err = MultiRepoError::RepoNotFound {
78 repo: "org/missing".to_string(),
79 };
80 assert!(err.to_string().contains("org/missing"));
81 }
82}