use super::state::LifecycleState;
use super::state_validation::ValidatedLifecycleState;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ValidationSeverity {
Error,
Warning,
Info,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ValidationIssue {
pub severity: ValidationSeverity,
pub message: String,
pub field: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ValidationResult {
pub issues: Vec<ValidationIssue>,
pub is_valid: bool,
}
impl ValidationResult {
pub fn new() -> Self {
Self {
issues: Vec::new(),
is_valid: true,
}
}
pub fn add_issue(&mut self, severity: ValidationSeverity, message: String) {
self.issues.push(ValidationIssue {
severity,
message,
field: None,
});
if severity == ValidationSeverity::Error {
self.is_valid = false;
}
}
pub fn add_issue_with_field(
&mut self, severity: ValidationSeverity, message: String, field: String,
) {
self.issues.push(ValidationIssue {
severity,
message,
field: Some(field),
});
if severity == ValidationSeverity::Error {
self.is_valid = false;
}
}
}
impl Default for ValidationResult {
fn default() -> Self {
Self::new()
}
}
pub struct ReadinessValidator;
impl ReadinessValidator {
pub fn new() -> Self {
Self
}
pub fn validate(&self, state: &LifecycleState) -> ValidationResult {
let mut result = ValidationResult::new();
match ValidatedLifecycleState::new(state.clone()) {
Ok(_) => {
}
Err(e) => {
result.add_issue(
ValidationSeverity::Error,
format!("Lifecycle state validation failed: {}", e),
);
return result;
}
}
let completed_phases: std::collections::HashSet<&str> = state
.phase_history
.iter()
.filter(|r| r.success)
.map(|r| r.phase.as_str())
.collect();
if completed_phases.contains("deploy") && !completed_phases.contains("test") {
result.add_issue(
ValidationSeverity::Error,
"Deploy phase executed without test phase completion".to_string(),
);
}
if completed_phases.contains("deploy") {
let recommended_phases = ["build", "test"];
for phase in recommended_phases {
if !completed_phases.contains(phase) {
result.add_issue(
ValidationSeverity::Warning,
format!("Deploy phase executed without {} phase completion", phase),
);
}
}
}
for cache_key in &state.cache_keys {
if !completed_phases.contains(cache_key.phase.as_str()) {
result.add_issue_with_field(
ValidationSeverity::Error,
format!(
"Cache key references non-existent phase: {}",
cache_key.phase
),
cache_key.phase.clone(),
);
}
}
result
}
}
impl Default for ReadinessValidator {
fn default() -> Self {
Self::new()
}
}