Skip to main content

ambient_ci/action_impl/
shell.rs

1#![allow(clippy::result_large_err)]
2
3use serde::{Deserialize, Serialize};
4
5use crate::{
6    action::{ActionError, Context},
7    action_impl::{spawn, ActionImpl},
8};
9
10/// Execute a snippet of shell script.
11///
12/// The snippet is executed using `bash`, with `set -xeuo pipefail` to make
13/// it fail if any command fails, or an unset variable is used, and to trace
14/// execution to allow easier debugging.
15#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
16pub struct Shell {
17    shell: String,
18}
19
20impl Shell {
21    /// Create a new `Shell` action.
22    pub fn new<S: Into<String>>(shell: S) -> Self {
23        let shell = shell.into();
24        Self { shell }
25    }
26
27    /// Shell snippet to run.
28    pub fn shell(&self) -> &str {
29        &self.shell
30    }
31}
32
33impl ActionImpl for Shell {
34    fn execute(&self, context: &mut Context) -> Result<(), ActionError> {
35        let snippet = bash_snippet(&self.shell);
36        spawn(context, &["bash", "-c", &snippet])?;
37        Ok(())
38    }
39}
40
41/// Construct a full snippet to give to Bash.
42pub fn bash_snippet(snippet: &str) -> String {
43    format!("set -xeuo pipefail\n{snippet}\n")
44}