use std::collections::HashMap;
use std::sync::Arc;
use async_trait::async_trait;
use crate::config::Config;
use crate::error::Result;
pub trait ProgressReporter: Send + Sync {
fn set_message(&self, message: &str);
}
pub struct StepContext {
pub config: Config,
pub dry_run: bool,
pub state: HashMap<String, String>,
pub progress: Option<Arc<dyn ProgressReporter>>,
}
impl StepContext {
pub fn report_progress(&self, message: &str) {
if let Some(ref reporter) = self.progress {
reporter.set_message(message);
}
}
}
#[derive(Debug, Clone)]
pub struct StepOutput {
pub status: StepStatus,
pub message: String,
pub duration_ms: u64,
pub dry_run_details: Option<DryRunDetails>,
}
#[derive(Debug, Clone)]
pub struct DryRunDetails {
pub file_changes: Vec<FileChange>,
pub docker_preview: Option<DockerPreview>,
pub notes: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct FileChange {
pub path: String,
pub operation: FileOperation,
pub diff: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum FileOperation {
Create,
Modify,
Delete,
}
#[derive(Debug, Clone)]
pub struct DockerPreview {
pub image_name: String,
pub tags: Vec<String>,
pub build_args: Vec<(String, String)>,
pub layers_estimate: Option<usize>,
}
impl StepOutput {
pub fn ok(message: impl Into<String>) -> Self {
Self {
status: StepStatus::Success,
message: message.into(),
duration_ms: 0,
dry_run_details: None,
}
}
pub fn skipped(message: impl Into<String>) -> Self {
Self {
status: StepStatus::Skipped,
message: message.into(),
duration_ms: 0,
dry_run_details: None,
}
}
pub fn with_dry_run_details(mut self, details: DryRunDetails) -> Self {
self.dry_run_details = Some(details);
self
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum StepStatus {
Success,
Skipped,
Failed,
}
impl std::fmt::Display for StepStatus {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
StepStatus::Success => write!(f, "✓"),
StepStatus::Skipped => write!(f, "⊘"),
StepStatus::Failed => write!(f, "✗"),
}
}
}
pub mod cloudfront;
pub mod docker;
pub mod git;
pub mod github;
pub mod health;
pub mod kubernetes;
pub mod notify;
#[async_trait]
pub trait Step: Send + Sync {
fn name(&self) -> &str;
fn description(&self) -> &str;
async fn validate(&self, ctx: &StepContext) -> Result<()>;
async fn execute(&self, ctx: &StepContext) -> Result<StepOutput>;
async fn dry_run(&self, ctx: &StepContext) -> Result<StepOutput>;
async fn rollback(&self, _ctx: &StepContext) -> Result<()> {
Ok(())
}
}