/ src / bin / cmd / run.rs
run.rs
 1  use std::path::{Path, PathBuf};
 2  
 3  use clap::Parser;
 4  
 5  use super::{AmbientError, Config, Leaf};
 6  use ambient_ci::{project::Projects, run::cmd_run, runlog::RunLog};
 7  
 8  /// Run CI on projects.
 9  #[derive(Debug, Parser)]
10  pub struct Run {
11      /// Project specification file. May contain any number of projects.
12      #[clap(long)]
13      projects: Option<PathBuf>,
14  
15      /// Which projects to run CI for, from the ones in the PROJECTS
16      /// file. Default is all of them.
17      chosen: Option<Vec<String>>,
18  
19      /// Run log.
20      #[clap(long)]
21      log: Option<PathBuf>,
22  
23      /// rsync target for publishing artifacts with rsync program.
24      #[clap(long, aliases = ["rsync", "target"])]
25      rsync_target: Option<String>,
26  
27      /// dput target for publishing .deb package.
28      #[clap(long, alias = "dput")]
29      dput_target: Option<String>,
30  
31      /// Path to `ambient-execute-plan` binary to use to run CI in VM.
32      #[clap(long)]
33      executor: Option<PathBuf>,
34  
35      /// Only pretend to run CI.
36      #[clap(long)]
37      dry_run: bool,
38  
39      /// Run even if repository hasn't changed.
40      #[clap(long)]
41      force: bool,
42  
43      /// Use UEFI with VM.
44      #[clap(long)]
45      uefi: bool,
46  }
47  
48  impl Leaf for Run {
49      fn run(&self, config: &Config, runlog: &mut RunLog) -> Result<(), AmbientError> {
50          let mut config = config.clone();
51  
52          if let Some(executor) = &self.executor {
53              config.set_executor(Path::new(executor));
54          };
55  
56          if let Some(s) = &self.rsync_target {
57              config.set_rsync_target(s);
58          }
59  
60          if let Some(s) = &self.dput_target {
61              config.set_dput_target(s);
62          };
63  
64          let projects = if let Some(filename) = &self.projects {
65              filename.to_path_buf()
66          } else {
67              config.projects().into()
68          };
69          let projects = Projects::from_file(&projects).map_err(RunError::Projects)?;
70  
71          config.lint(&projects)?;
72  
73          let result = cmd_run(
74              &config,
75              runlog,
76              &projects,
77              self.chosen.as_deref(),
78              self.dry_run,
79              self.force,
80              self.uefi || config.uefi(),
81          );
82          match result {
83              Ok(_) => (),
84              // Err(ambient_ci::run::RunError::RunFailed) => (),
85              Err(_) => result.map_err(RunError::Run)?,
86          }
87  
88          Ok(())
89      }
90  }
91  
92  #[derive(Debug, thiserror::Error)]
93  pub enum RunError {
94      #[error(transparent)]
95      Run(#[from] ambient_ci::run::RunError),
96  
97      #[error("failed to load projects file")]
98      Projects(#[source] ambient_ci::project::ProjectError),
99  }