glory_cli/command/
end2end.rs1use 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}