use crate::autonomic::policies::{
BranchBehindConfig, EvidenceStaleConfig, GitPhaseDirtyConfig, PublishNotAdjudicatedConfig,
TargetPressureConfig, ToolchainMismatchConfig, TrybuildChangedConfig,
};
#[derive(Debug)]
pub struct PolicyEngine {
pub apply: bool,
pub target_pressure: TargetPressureConfig,
pub toolchain_mismatch: ToolchainMismatchConfig,
pub trybuild_changed: TrybuildChangedConfig,
pub branch_behind: BranchBehindConfig,
pub publish_not_adjudicated: PublishNotAdjudicatedConfig,
pub git_phase_dirty: GitPhaseDirtyConfig,
pub evidence_stale: EvidenceStaleConfig,
}
impl Default for PolicyEngine {
fn default() -> Self {
Self {
apply: false,
target_pressure: TargetPressureConfig::default(),
toolchain_mismatch: ToolchainMismatchConfig::default(),
trybuild_changed: TrybuildChangedConfig::default(),
branch_behind: BranchBehindConfig::default(),
publish_not_adjudicated: PublishNotAdjudicatedConfig::default(),
git_phase_dirty: GitPhaseDirtyConfig::default(),
evidence_stale: EvidenceStaleConfig::default(),
}
}
}
#[derive(Debug, Clone)]
pub struct PolicyResult {
pub policy_name: String,
pub executed: bool,
pub error: Option<String>,
}
#[derive(Debug)]
pub struct PolicyEngineResult {
pub results: Vec<PolicyResult>,
pub total_executed: usize,
pub total_failed: usize,
}
impl PolicyEngine {
pub fn new() -> Self {
Self::default()
}
pub fn with_apply(mut self, apply: bool) -> Self {
self.apply = apply;
self
}
pub fn execute_all(&self) -> PolicyEngineResult {
use crate::autonomic::policies;
let mut results = Vec::new();
let mut total_executed = 0;
let mut total_failed = 0;
let mut run = |name: &str, condition: bool, exec: Result<(), String>| match exec {
Ok(_) => {
if condition {
total_executed += 1;
}
results.push(PolicyResult {
policy_name: name.to_string(),
executed: condition,
error: None,
});
}
Err(e) => {
results.push(PolicyResult {
policy_name: name.to_string(),
executed: true,
error: Some(e),
});
total_failed += 1;
}
};
let p1 = policies::target_pressure::check_pressure(&self.target_pressure);
run(
"TargetPressurePolicy",
p1,
if p1 {
policies::target_pressure::execute(&self.target_pressure, self.apply)
} else {
Ok(())
},
);
let p2 = policies::toolchain_mismatch::check_mismatch(&self.toolchain_mismatch);
run(
"ToolchainMismatchPolicy",
p2,
if p2 {
policies::toolchain_mismatch::execute(&self.toolchain_mismatch, self.apply)
} else {
Ok(())
},
);
let p3 = policies::trybuild_changed::check_changed(&self.trybuild_changed);
run(
"TrybuildChangedPolicy",
p3,
if p3 {
policies::trybuild_changed::execute(&self.trybuild_changed, self.apply)
} else {
Ok(())
},
);
let p4 = policies::branch_behind::check_behind(&self.branch_behind);
run(
"BranchBehindPolicy",
p4,
if p4 {
policies::branch_behind::execute(&self.branch_behind, self.apply)
} else {
Ok(())
},
);
let p5 =
policies::publish_not_adjudicated::check_needs_dry_run(&self.publish_not_adjudicated);
run(
"PublishNotAdjudicatedPolicy",
p5,
if p5 {
policies::publish_not_adjudicated::execute(
&self.publish_not_adjudicated,
self.apply,
)
} else {
Ok(())
},
);
let p6 = policies::git_phase_dirty::check_dirty();
run(
"GitPhaseDirtyPolicy",
p6,
if p6 {
policies::git_phase_dirty::execute(&self.git_phase_dirty, self.apply)
} else {
Ok(())
},
);
let p7 = policies::evidence_stale::check_stale(&self.evidence_stale);
run(
"EvidenceStalePolicy",
p7,
if p7 {
policies::evidence_stale::execute(&self.evidence_stale, self.apply)
} else {
Ok(())
},
);
PolicyEngineResult { results, total_executed, total_failed }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_policy_engine_default() {
let engine = PolicyEngine::default();
assert!(!engine.apply);
}
#[test]
fn test_policy_engine_with_apply() {
let engine = PolicyEngine::new().with_apply(true);
assert!(engine.apply);
}
#[test]
fn test_execute_all_dry_run() {
let engine = PolicyEngine::new().with_apply(false);
let result = engine.execute_all();
assert_eq!(result.results.len(), 7); assert!(result.total_failed <= 7);
}
#[test]
fn test_policy_engine_idempotency() {
let engine = PolicyEngine::new().with_apply(false);
let result1 = engine.execute_all();
let result2 = engine.execute_all();
assert_eq!(result1.results.len(), result2.results.len());
for i in 0..result1.results.len() {
assert_eq!(result1.results[i].policy_name, result2.results[i].policy_name);
}
}
}