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