vorpal-sdk 0.2.0-alpha

Vorpal SDK for building Vorpal configurations.
Documentation
use crate::{
    api::artifact::{
        ArtifactSystem,
        ArtifactSystem::{Aarch64Darwin, Aarch64Linux, X8664Darwin, X8664Linux},
    },
    artifact::{get_env_key, go, step, ArtifactBuilder, ArtifactSource, ArtifactSourceBuilder},
    context::ConfigContext,
};
use anyhow::{bail, Result};
use indoc::formatdoc;

pub struct GoBuilder<'a> {
    aliases: Vec<String>,
    artifacts: Vec<String>,
    build_arguments: Vec<String>,
    build_directory: Option<&'a str>,
    build_path: Option<&'a str>,
    includes: Vec<&'a str>,
    name: &'a str,
    source: Option<ArtifactSource>,
    source_scripts: Vec<String>,
    systems: Vec<ArtifactSystem>,
}

pub fn get_goos(target: ArtifactSystem) -> Result<String> {
    let goos = match target {
        Aarch64Darwin | X8664Darwin => "darwin",
        Aarch64Linux | X8664Linux => "linux",
        _ => bail!("unsupported 'go' system: {:?}", target),
    };

    Ok(goos.to_string())
}

pub fn get_goarch(target: ArtifactSystem) -> Result<String> {
    let goarch = match target {
        Aarch64Darwin | Aarch64Linux => "arm64",
        X8664Darwin | X8664Linux => "amd64",
        _ => bail!("unsupported 'go' system: {:?}", target),
    };

    Ok(goarch.to_string())
}

impl<'a> GoBuilder<'a> {
    pub fn new(name: &'a str, systems: Vec<ArtifactSystem>) -> Self {
        Self {
            aliases: vec![],
            artifacts: vec![],
            build_arguments: vec![],
            build_directory: None,
            build_path: None,
            includes: vec![],
            name,
            source: None,
            source_scripts: vec![],
            systems,
        }
    }

    pub fn with_alias(mut self, alias: String) -> Self {
        if !self.aliases.contains(&alias) {
            self.aliases.push(alias);
        }
        self
    }

    pub fn with_build_arguments(mut self, arguments: Vec<String>) -> Self {
        self.build_arguments = arguments;
        self
    }

    pub fn with_artifacts(mut self, artifacts: Vec<String>) -> Self {
        self.artifacts = artifacts;
        self
    }

    pub fn with_build_directory(mut self, directory: &'a str) -> Self {
        self.build_directory = Some(directory);
        self
    }

    pub fn with_build_path(mut self, path: &'a str) -> Self {
        self.build_path = Some(path);
        self
    }

    pub fn with_includes(mut self, includes: Vec<&'a str>) -> Self {
        self.includes = includes;
        self
    }

    pub fn with_source(mut self, source: ArtifactSource) -> Self {
        self.source = Some(source);
        self
    }

    pub fn with_source_script(mut self, script: &'a str) -> Self {
        if !self.source_scripts.contains(&script.to_string()) {
            self.source_scripts.push(script.to_string());
        }
        self
    }

    pub async fn build(self, context: &mut ConfigContext) -> Result<String> {
        let source_path = ".";

        let mut source_builder = ArtifactSourceBuilder::new(self.name, source_path);

        if !self.includes.is_empty() {
            let source_includes = self.includes.iter().map(|s| s.to_string()).collect();
            source_builder = source_builder.with_includes(source_includes);
        }

        let mut source = source_builder.build();

        if let Some(src) = self.source {
            source = src;
        }

        let source_dir = format!("./source/{}", source.name);

        let mut step_script = formatdoc! {r#"
            pushd {source_dir}

            mkdir -p $VORPAL_OUTPUT/bin"#,
        };

        if !self.source_scripts.is_empty() {
            let source_scripts = self.source_scripts.join("\n");

            step_script = formatdoc! {r#"
                {step_script}

                {source_scripts}"#,
            };
        }

        let build_directory = self.build_directory.unwrap_or(source_path);
        let build_path = self.build_path.unwrap_or(source_path);

        step_script = formatdoc! {r#"
            {step_script}

            go build -C {build_directory} -o $VORPAL_OUTPUT/bin/{name} {build_path}

            go clean -modcache"#,
            name = self.name,
        };

        let go = go::build(context).await?;
        let goarch = get_goarch(context.get_system())?;
        let goos = get_goos(context.get_system())?;

        let steps = vec![
            step::shell(
                context,
                [vec![go.clone()], self.artifacts].concat(),
                vec![
                    "CGO_ENABLED=0".to_string(),
                    format!("GOARCH={}", goarch),
                    "GOCACHE=$VORPAL_WORKSPACE/go/cache".to_string(),
                    format!("GOOS={}", goos),
                    "GOPATH=$VORPAL_WORKSPACE/go".to_string(),
                    format!("PATH={}/bin", get_env_key(&go)),
                ],
                step_script,
            )
            .await?,
        ];

        let mut builder = ArtifactBuilder::new(self.name, steps, self.systems).with_source(source);

        for alias in self.aliases {
            builder = builder.with_alias(alias);
        }

        builder.build(context).await
    }
}