stormchaser-engine 1.3.0

A robust, distributed workflow engine for event-driven and human-triggered workflows.
Documentation
use serde_json::Value;
use stormchaser_model::dsl;

/// Mutates the git_checkout step spec to automatically configure parameters like repository, reference, and token based on context if they are omitted.
pub fn mutate(step_type: &mut String, resolved_spec: &mut Value) {
    if step_type == "GitCheckout" {
        let git_spec: Result<dsl::GitCheckoutSpec, _> =
            serde_json::from_value(resolved_spec.get("spec").unwrap_or(&*resolved_spec).clone());

        if let Ok(git) = git_spec {
            let depth = git.depth.unwrap_or(1);
            let dest = git.destination.clone().unwrap_or_else(|| ".".to_string());
            let branch = git.r#ref.clone().unwrap_or_else(|| "main".to_string());

            let mut script = format!(
                "mkdir -p {dest} && cd {dest} && git init && git remote add origin {repo} && git fetch --depth {depth} --filter=blob:none origin {branch} && git checkout FETCH_HEAD",
                dest = dest,
                repo = git.repo,
                depth = depth,
                branch = branch
            );

            if let Some(sparse) = git.sparse_checkout {
                if !sparse.is_empty() {
                    let sparse_paths = sparse.join(" ");
                    script = format!(
                        "mkdir -p {dest} && cd {dest} && git init && git remote add origin {repo} && git sparse-checkout set {sparse_paths} && git fetch --depth {depth} --filter=blob:none origin {branch} && git checkout FETCH_HEAD",
                        dest = dest,
                        repo = git.repo,
                        sparse_paths = sparse_paths,
                        depth = depth,
                        branch = branch
                    );
                }
            }

            let container_spec = dsl::CommonContainerSpec {
                image: "alpine/git:latest".to_string(),
                command: Some(vec!["sh".to_string(), "-c".to_string(), script]),
                args: None,
                env: None,
                cpu: None,
                memory: None,
                privileged: None,
                storage_mounts: git.storage_mounts,
            };

            *step_type = "RunContainer".to_string();
            if let Ok(val) = serde_json::to_value(container_spec) {
                *resolved_spec = val;
            }
        }
    }
}
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_mutate_git_checkout_default() {
        let mut step_type = "GitCheckout".to_string();
        let mut spec = serde_json::json!({
            "repo": "https://github.com/example/repo.git"
        });

        mutate(&mut step_type, &mut spec);

        assert_eq!(step_type, "RunContainer");
        let spec_obj = spec.as_object().unwrap();
        assert_eq!(spec_obj.get("image").unwrap(), "alpine/git:latest");
        let command = spec_obj.get("command").unwrap().as_array().unwrap();
        assert_eq!(command[0], "sh");
        assert_eq!(command[1], "-c");
        assert_eq!(
            command[2],
            "mkdir -p . && cd . && git init && git remote add origin https://github.com/example/repo.git && git fetch --depth 1 --filter=blob:none origin main && git checkout FETCH_HEAD"
        );
    }

    #[test]
    fn test_mutate_git_checkout_sparse() {
        let mut step_type = "GitCheckout".to_string();
        let mut spec = serde_json::json!({
            "repo": "https://github.com/example/repo.git",
            "ref": "v1.0",
            "depth": 5,
            "sparse_checkout": ["src/", "docs/"],
            "destination": "/workspace/repo"
        });

        mutate(&mut step_type, &mut spec);

        assert_eq!(step_type, "RunContainer");
        let spec_obj = spec.as_object().unwrap();
        let command = spec_obj.get("command").unwrap().as_array().unwrap();
        assert_eq!(
            command[2],
            "mkdir -p /workspace/repo && cd /workspace/repo && git init && git remote add origin https://github.com/example/repo.git && git sparse-checkout set src/ docs/ && git fetch --depth 5 --filter=blob:none origin v1.0 && git checkout FETCH_HEAD"
        );
    }
}