cuenv_ci/executor/
config.rs1use crate::ir::CachePolicy;
7use cuenv_core::{DryRun, OutputCapture};
8use std::path::PathBuf;
9
10pub const DEFAULT_SHELL: &str = "/bin/sh";
12
13#[derive(Debug, Clone)]
15pub struct CIExecutorConfig {
16 pub project_root: PathBuf,
18
19 pub cache_root: Option<PathBuf>,
21
22 pub max_parallel: usize,
24
25 pub capture_output: OutputCapture,
27
28 pub dry_run: DryRun,
30
31 pub cache_policy_override: Option<CachePolicy>,
33
34 pub secret_salt: Option<String>,
36
37 pub secret_salt_prev: Option<String>,
39
40 pub shell_path: String,
42}
43
44impl Default for CIExecutorConfig {
45 fn default() -> Self {
46 Self {
47 project_root: PathBuf::from("."),
48 cache_root: None,
49 max_parallel: 4,
50 capture_output: OutputCapture::Capture,
51 dry_run: DryRun::No,
52 cache_policy_override: None,
53 secret_salt: None,
54 secret_salt_prev: None,
55 shell_path: DEFAULT_SHELL.to_string(),
56 }
57 }
58}
59
60impl CIExecutorConfig {
61 #[must_use]
63 pub fn new(project_root: PathBuf) -> Self {
64 Self {
65 project_root,
66 ..Default::default()
67 }
68 }
69
70 #[must_use]
72 pub fn with_cache_root(mut self, cache_root: PathBuf) -> Self {
73 self.cache_root = Some(cache_root);
74 self
75 }
76
77 #[must_use]
79 pub const fn with_max_parallel(mut self, max_parallel: usize) -> Self {
80 self.max_parallel = max_parallel;
81 self
82 }
83
84 #[must_use]
86 pub const fn with_capture_output(mut self, capture: OutputCapture) -> Self {
87 self.capture_output = capture;
88 self
89 }
90
91 #[must_use]
93 pub const fn with_dry_run(mut self, dry_run: DryRun) -> Self {
94 self.dry_run = dry_run;
95 self
96 }
97
98 #[must_use]
100 pub const fn with_cache_policy_override(mut self, policy: CachePolicy) -> Self {
101 self.cache_policy_override = Some(policy);
102 self
103 }
104
105 #[must_use]
107 pub fn with_secret_salt(mut self, salt: String) -> Self {
108 self.secret_salt = Some(salt);
109 self
110 }
111
112 #[must_use]
114 pub fn with_secret_salt_prev(mut self, salt: String) -> Self {
115 self.secret_salt_prev = Some(salt);
116 self
117 }
118
119 #[must_use]
121 pub fn with_shell_path(mut self, shell_path: impl Into<String>) -> Self {
122 self.shell_path = shell_path.into();
123 self
124 }
125
126 #[must_use]
128 pub fn effective_cache_root(&self) -> PathBuf {
129 self.cache_root
130 .clone()
131 .unwrap_or_else(|| self.project_root.join(".cuenv/cache"))
132 }
133}
134
135#[cfg(test)]
136mod tests {
137 use super::*;
138
139 #[test]
140 fn test_default_config() {
141 let config = CIExecutorConfig::default();
142 assert_eq!(config.max_parallel, 4);
143 assert!(config.capture_output.should_capture());
144 assert!(!config.dry_run.is_dry_run());
145 assert!(config.cache_policy_override.is_none());
146 }
147
148 #[test]
149 fn test_builder_pattern() {
150 let config = CIExecutorConfig::new(PathBuf::from("/project"))
151 .with_max_parallel(8)
152 .with_dry_run(DryRun::Yes)
153 .with_cache_policy_override(CachePolicy::Readonly);
154
155 assert_eq!(config.max_parallel, 8);
156 assert!(config.dry_run.is_dry_run());
157 assert_eq!(config.cache_policy_override, Some(CachePolicy::Readonly));
158 }
159
160 #[test]
161 fn test_effective_cache_root() {
162 let config = CIExecutorConfig::new(PathBuf::from("/project"));
163 assert_eq!(
164 config.effective_cache_root(),
165 PathBuf::from("/project/.cuenv/cache")
166 );
167
168 let config_with_override = CIExecutorConfig::new(PathBuf::from("/project"))
169 .with_cache_root(PathBuf::from("/tmp/cache"));
170 assert_eq!(
171 config_with_override.effective_cache_root(),
172 PathBuf::from("/tmp/cache")
173 );
174 }
175
176 #[test]
177 fn test_shell_path_default() {
178 let config = CIExecutorConfig::default();
179 assert_eq!(config.shell_path, "/bin/sh");
180 }
181
182 #[test]
183 fn test_shell_path_custom() {
184 let config = CIExecutorConfig::new(PathBuf::from("/project")).with_shell_path("/bin/bash");
185 assert_eq!(config.shell_path, "/bin/bash");
186 }
187}