mod agent;
mod approval;
mod artifact;
mod http;
mod shell;
mod workflow;
pub use agent::AgentStepConfig;
pub use approval::ApprovalConfig;
pub use artifact::{ArtifactInput, ArtifactOutput};
pub use http::HttpConfig;
pub use shell::ShellConfig;
pub use workflow::WorkflowStepConfig;
use ironflow_core::retry::RetryPolicy;
use ironflow_store::entities::StepKind;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum StepConfig {
Shell(ShellConfig),
Http(HttpConfig),
Agent(AgentStepConfig),
Workflow(WorkflowStepConfig),
Approval(ApprovalConfig),
}
impl StepConfig {
pub fn allow_failure(&self) -> bool {
match self {
StepConfig::Shell(c) => c.allow_failure,
StepConfig::Http(c) => c.allow_failure,
StepConfig::Agent(c) => c.allow_failure,
StepConfig::Workflow(_) | StepConfig::Approval(_) => false,
}
}
pub fn retry(&self) -> Option<&RetryPolicy> {
match self {
StepConfig::Shell(c) => c.retry.as_ref(),
StepConfig::Http(c) => c.retry.as_ref(),
StepConfig::Agent(c) => c.retry.as_ref(),
StepConfig::Workflow(c) => c.retry.as_ref(),
StepConfig::Approval(_) => None,
}
}
pub fn kind(&self) -> StepKind {
match self {
StepConfig::Shell(_) => StepKind::Shell,
StepConfig::Http(_) => StepKind::Http,
StepConfig::Agent(_) => StepKind::Agent,
StepConfig::Workflow(_) => StepKind::Workflow,
StepConfig::Approval(_) => StepKind::Approval,
}
}
}
impl From<ShellConfig> for StepConfig {
fn from(c: ShellConfig) -> Self {
StepConfig::Shell(c)
}
}
impl From<HttpConfig> for StepConfig {
fn from(c: HttpConfig) -> Self {
StepConfig::Http(c)
}
}
impl From<AgentStepConfig> for StepConfig {
fn from(c: AgentStepConfig) -> Self {
StepConfig::Agent(c)
}
}
#[cfg(test)]
mod tests {
use ironflow_core::retry::RetryPolicy;
use super::*;
#[test]
fn retry_accessor_returns_policy_for_each_variant() {
let shell = StepConfig::Shell(ShellConfig::new("echo").retry_policy(RetryPolicy::new(2)));
assert_eq!(shell.retry().unwrap().max_retries(), 2);
let http = StepConfig::Http(HttpConfig::get("http://x").retry_policy(RetryPolicy::new(3)));
assert_eq!(http.retry().unwrap().max_retries(), 3);
let workflow = StepConfig::Workflow(
WorkflowStepConfig::new("build", serde_json::json!({}))
.retry_policy(RetryPolicy::new(4)),
);
assert_eq!(workflow.retry().unwrap().max_retries(), 4);
let agent = StepConfig::Agent(AgentStepConfig::new("test"));
assert!(agent.retry().is_none());
let approval = StepConfig::Approval(ApprovalConfig::new("ok?"));
assert!(approval.retry().is_none());
}
#[test]
fn serde_roundtrip() {
let configs = vec![
StepConfig::Shell(ShellConfig::new("echo test")),
StepConfig::Http(HttpConfig::get("http://example.com")),
StepConfig::Agent(AgentStepConfig::new("summarize")),
StepConfig::Workflow(WorkflowStepConfig::new("build", serde_json::json!({}))),
StepConfig::Approval(ApprovalConfig::new("Deploy to production?")),
];
for config in configs {
let json = serde_json::to_string(&config).expect("serialize");
let back: StepConfig = serde_json::from_str(&json).expect("deserialize");
let json2 = serde_json::to_string(&back).expect("serialize2");
assert_eq!(json, json2);
}
}
}