glory_cli/command/
end2end.rs

1use std::sync::Arc;
2
3use anyhow::bail;
4use camino::Utf8Path;
5use tokio::process::Command;
6
7use crate::config::{Config, Project};
8use crate::ext::anyhow::{anyhow, Context, Result};
9use crate::service::serve;
10use crate::signal::Interrupt;
11
12pub async fn end2end_all(conf: &Config) -> Result<()> {
13    for proj in &conf.projects {
14        end2end_proj(proj).await?;
15    }
16    Ok(())
17}
18
19pub async fn end2end_proj(proj: &Arc<Project>) -> Result<()> {
20    if let Some(e2e) = &proj.end2end {
21        if !super::build::build_proj(proj).await.dot()? {
22            return Ok(());
23        }
24
25        let server = serve::spawn(proj).await;
26        try_run(&e2e.cmd, &e2e.dir).await.context(format!("running: {}", &e2e.cmd))?;
27        Interrupt::request_shutdown().await;
28        server.await.dot()??;
29    } else {
30        log::info!("end2end the Crate.toml package.metadata.glory.end2end_cmd parameter not set")
31    }
32    Ok(())
33}
34
35async fn try_run(cmd: &str, dir: &Utf8Path) -> Result<()> {
36    let mut parts = cmd.split(' ');
37    let exe = parts.next().ok_or_else(|| anyhow!("Invalid command {cmd:?}"))?;
38
39    let args = parts.collect::<Vec<_>>();
40
41    log::trace!("End2End running {cmd:?}");
42    let mut process = Command::new(exe)
43        .args(args)
44        .current_dir(dir)
45        .spawn()
46        .context(format!("Could not spawn command {cmd:?}"))?;
47
48    let mut int = Interrupt::subscribe_any();
49
50    tokio::select! {
51          _ = int.recv() => Ok(()),
52          result = process.wait() => {
53            let status = result?;
54            if !status.success() {
55                bail!("Command terminated with exit code {}", status)
56            }
57            Ok(())
58        }
59    }
60}