Skip to main content

dk_runner/steps/
command.rs

1use std::collections::HashMap;
2use std::path::Path;
3use std::time::Duration;
4
5use anyhow::Result;
6
7use crate::executor::{Executor, StepOutput};
8use crate::workflow::validator::validate_command;
9
10/// Run a command step, validating it first against the allowlist.
11pub async fn run_command_step(
12    executor: &dyn Executor,
13    command: &str,
14    work_dir: &Path,
15    timeout: Duration,
16    env: &HashMap<String, String>,
17) -> Result<StepOutput> {
18    validate_command(command)?;
19    Ok(executor.run_command(command, work_dir, timeout, env).await)
20}
21
22#[cfg(test)]
23mod tests {
24    use super::*;
25    use crate::executor::process::ProcessExecutor;
26    use crate::executor::StepStatus;
27
28    #[tokio::test]
29    async fn test_run_allowed_command() {
30        let exec = ProcessExecutor::new();
31        let dir = std::env::temp_dir();
32        let out = run_command_step(&exec, "echo hello", &dir, Duration::from_secs(5), &HashMap::new())
33            .await
34            .unwrap();
35        assert_eq!(out.status, StepStatus::Pass);
36    }
37
38    #[tokio::test]
39    async fn test_run_disallowed_command_errors() {
40        let exec = ProcessExecutor::new();
41        let dir = std::env::temp_dir();
42        let result = run_command_step(&exec, "rm -rf /", &dir, Duration::from_secs(5), &HashMap::new()).await;
43        assert!(result.is_err());
44    }
45}