pub struct ShellConfig {
pub command: String,
pub args: Option<Vec<String>>,
pub timeout_secs: Option<u64>,
pub dir: Option<String>,
pub env: Vec<(String, String)>,
pub clean_env: bool,
pub outputs: Vec<ArtifactOutput>,
pub inputs: Vec<ArtifactInput>,
pub allow_failure: bool,
pub exit_code_as_output: bool,
pub retry: Option<RetryPolicy>,
}Expand description
Serializable configuration for a shell step.
§Examples
use ironflow_engine::config::ShellConfig;
let config = ShellConfig::new("cargo build --release")
.timeout_secs(300)
.dir("/app")
.output("target/report.html");Fields§
§command: StringThe command line passed to sh -c, or the program to run when
args is set.
args: Option<Vec<String>>Arguments of command when it runs without a shell.
Some means exec mode: command is spawned directly with these
arguments, none of them is interpreted. None means command goes
through sh -c. Set by ShellConfig::exec.
timeout_secs: Option<u64>Timeout in seconds (default: 300).
dir: Option<String>Working directory.
env: Vec<(String, String)>Environment variables to set.
clean_env: boolIf true, start with a clean environment.
outputs: Vec<ArtifactOutput>Files the step promises to produce, collected once it finishes.
inputs: Vec<ArtifactInput>Artifacts of earlier steps to place in the working directory first.
allow_failure: boolWhen true, a failure of this step does not fail the run. The step is
still marked Failed but execution continues and the run finishes with
RunStatus::Warning instead of Failed.
exit_code_as_output: boolWhen true, a non-zero exit code is a normal output instead of an
error: the step is Completed and its output carries the real code.
Timeout, spawn and input-preparation failures stay errors.
retry: Option<RetryPolicy>Optional step-level retry policy. When set, a transient failure retries the step locally with exponential backoff before propagating the error.
Implementations§
Source§impl ShellConfig
impl ShellConfig
Sourcepub fn new(command: &str) -> Self
pub fn new(command: &str) -> Self
Create a new shell config with the given command.
The command is passed to sh -c, so pipes, redirects and globs work.
§Security
Never build the command from data the workflow does not control (its
input, a webhook payload, a human answer, an agent output): a quote or a
; in that data runs arbitrary commands on the worker. Use
ShellConfig::exec to pass such data as arguments, or
env to hand it to a script as a variable.
§Examples
use ironflow_engine::config::ShellConfig;
let config = ShellConfig::new("echo hello");
assert_eq!(config.command, "echo hello");Sourcepub fn exec(program: &str, args: &[&str]) -> Self
pub fn exec(program: &str, args: &[&str]) -> Self
Create a config that runs program directly, without a shell.
Each argument reaches the program as is: quotes, ;, $(..),
backticks and globs are plain text. This is the way to run a command
built from untrusted data. The program is looked up in PATH.
§Examples
use ironflow_engine::config::ShellConfig;
let name = "Ada'; rm -rf / #";
let config = ShellConfig::exec("printf", &["Hello, %s!\n", name]);
assert_eq!(config.command, "printf");
assert_eq!(config.args.as_deref().map(<[String]>::len), Some(2));Sourcepub fn timeout_secs(self, secs: u64) -> Self
pub fn timeout_secs(self, secs: u64) -> Self
Set the timeout in seconds.
Sourcepub fn output(self, pattern: &str) -> Self
pub fn output(self, pattern: &str) -> Self
Declare a file the step produces, typed from its name.
pattern is a glob resolved against dir. Every match is
stored as an artifact named after the file. When the step succeeds and
the pattern matches nothing, the step fails.
§Examples
use ironflow_engine::config::ShellConfig;
let config = ShellConfig::new("cargo build").output("target/*.log");
assert_eq!(config.outputs.len(), 1);Sourcepub fn output_typed(self, pattern: &str, content_type: &str) -> Self
pub fn output_typed(self, pattern: &str, content_type: &str) -> Self
Declare a produced file with an explicit MIME type.
§Examples
use ironflow_engine::config::ShellConfig;
let config = ShellConfig::new("./gen").output_typed("data", "application/json");
assert_eq!(config.outputs[0].content_type.as_deref(), Some("application/json"));Sourcepub fn input(self, artifact: &ArtifactRef) -> Self
pub fn input(self, artifact: &ArtifactRef) -> Self
Consume an artifact produced by an earlier step of the same run.
The handle comes from the producing step, see ArtifactRef. The
artifact is written into the working directory under its own name
before the command runs. Use input_at to choose
another path.
§Examples
use ironflow_engine::config::ShellConfig;
use ironflow_engine::context::WorkflowContext;
use ironflow_engine::error::EngineError;
let build = ctx.shell("build", ShellConfig::new("./gen").output("report.html")).await?;
let report = build.artifact("report.html")?;
let config = ShellConfig::new("./publish").input(&report);
assert_eq!(config.inputs[0].destination(), "report.html");Sourcepub fn allow_failure(self) -> Self
pub fn allow_failure(self) -> Self
Mark this step as allowed to fail without stopping the run.
§Examples
use ironflow_engine::config::ShellConfig;
let config = ShellConfig::new("cargo clippy").allow_failure();
assert!(config.allow_failure);Sourcepub fn exit_code_as_output(self) -> Self
pub fn exit_code_as_output(self) -> Self
Treat a non-zero exit code as data instead of a failure.
The step is Completed: StepOutput::is_success() is false and
exit_code() returns the real code, so the handler can branch on it
(a conflicting git merge, red tests). The run is not degraded and
allow_failure is not triggered. A non-zero
exit is no longer an error, so a retry policy does not retry it.
Timeout, spawn failure and input-preparation failure remain errors and
follow allow_failure.
§Examples
use ironflow_engine::config::ShellConfig;
let config = ShellConfig::new("git merge feature").exit_code_as_output();
assert!(config.exit_code_as_output);Sourcepub fn retry_policy(self, policy: RetryPolicy) -> Self
pub fn retry_policy(self, policy: RetryPolicy) -> Self
Set a step-level retry policy.
§Examples
use ironflow_core::retry::RetryPolicy;
use ironflow_engine::config::ShellConfig;
let config = ShellConfig::new("curl http://api")
.retry_policy(RetryPolicy::new(3));
assert!(config.retry.is_some());Sourcepub fn input_at(self, artifact: &ArtifactRef, dest: &str) -> Self
pub fn input_at(self, artifact: &ArtifactRef, dest: &str) -> Self
Consume an artifact and write it to an explicit path.
§Examples
use ironflow_engine::config::ShellConfig;
use ironflow_engine::context::WorkflowContext;
use ironflow_engine::error::EngineError;
let build = ctx.shell("build", ShellConfig::new("./gen").output("report.html")).await?;
let report = build.artifact("report.html")?;
let config = ShellConfig::new("./publish").input_at(&report, "in/r.html");
assert_eq!(config.inputs[0].destination(), "in/r.html");