1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
//! Hook that resolves a step without executing it.
//!
//! A [`StepInterceptor`] is consulted by
//! [`execute_step_config_intercepted`](crate::executor::execute_step_config_intercepted)
//! before the dispatcher picks an executor, and by
//! [`WorkflowContext::approval`](crate::context::WorkflowContext::approval)
//! before the gate suspends the run. Returning `Some(..)` short-circuits the
//! step: no process is spawned, no request is sent, no human is asked.
//!
//! Production wiring leaves the hook unset. In practice the only implementor is
//! [`crate::testing`], which uses it to run a handler's real logic against
//! canned step results.
use crate;
use crateEngineError;
use crateStepOutput;
/// Decision applied to an approval gate by a [`StepInterceptor`].
///
/// # Examples
///
/// ```
/// use ironflow_engine::executor::ApprovalOutcome;
///
/// let granted = ApprovalOutcome::Approved;
/// assert_eq!(granted, ApprovalOutcome::Approved);
///
/// let refused = ApprovalOutcome::Rejected { reason: "not on a Friday".to_string() };
/// assert_ne!(granted, refused);
/// ```
/// Resolves steps without executing them.
///
/// # Examples
///
/// ```
/// use ironflow_engine::config::{ShellConfig, StepConfig};
/// use ironflow_engine::error::EngineError;
/// use ironflow_engine::executor::{StepInterceptor, StepOutput};
/// use rust_decimal::Decimal;
/// use serde_json::json;
///
/// struct AlwaysOk;
///
/// impl StepInterceptor for AlwaysOk {
/// fn intercept(&self, config: &StepConfig) -> Option<Result<StepOutput, EngineError>> {
/// match config {
/// StepConfig::Shell(_) => Some(Ok(StepOutput {
/// output: json!({"stdout": "ok", "stderr": "", "exit_code": 0}),
/// duration_ms: 0,
/// cost_usd: Decimal::ZERO,
/// input_tokens: None,
/// output_tokens: None,
/// model: None,
/// debug_messages: None,
/// })),
/// _ => None,
/// }
/// }
/// }
///
/// let config = StepConfig::Shell(ShellConfig::new("./deploy.sh"));
/// let intercepted = AlwaysOk.intercept(&config).expect("shell is intercepted");
/// assert_eq!(intercepted.expect("canned output").stdout(), "ok");
/// ```