microsoft/openvmm
Publicmirrored fromhttps://github.com/microsoft/openvmmAvailable
flowey/flowey_cli/src/cli/mod.rs
109lines · modecode
| 1 | // Copyright (c) Microsoft Corporation. |
| 2 | // Licensed under the MIT License. |
| 3 | |
| 4 | //! A set of CLI commands which are common to _all_ flowey implementations. |
| 5 | |
| 6 | use clap::Parser; |
| 7 | use clap::Subcommand; |
| 8 | use clap::ValueEnum; |
| 9 | use flowey_core::node::FlowBackend; |
| 10 | use flowey_core::pipeline::IntoPipeline; |
| 11 | use serde::Deserialize; |
| 12 | use serde::Serialize; |
| 13 | use std::path::Path; |
| 14 | |
| 15 | pub mod debug; |
| 16 | pub mod exec_snippet; |
| 17 | pub mod pipeline; |
| 18 | pub mod regen; |
| 19 | pub mod var_db; |
| 20 | |
| 21 | #[derive(Parser)] |
| 22 | #[clap(name = "flowey", about = "backend-agnostic declarative flow runner")] |
| 23 | struct Cli<P: Subcommand> { |
| 24 | #[clap(subcommand)] |
| 25 | command: Commands<P>, |
| 26 | } |
| 27 | |
| 28 | #[derive(Subcommand)] |
| 29 | enum Commands<P: Subcommand> { |
| 30 | Pipeline(pipeline::Pipeline<P>), |
| 31 | Regen(regen::Regen), |
| 32 | |
| 33 | #[clap(hide = true, alias = "e")] |
| 34 | ExecSnippet(exec_snippet::ExecSnippet), |
| 35 | #[clap(hide = true, alias = "v")] |
| 36 | VarDb(var_db::VarDb), |
| 37 | |
| 38 | #[clap(subcommand)] |
| 39 | Debug(debug::DebugCommands), |
| 40 | } |
| 41 | |
| 42 | pub fn cli_main<P: Subcommand + IntoPipeline>( |
| 43 | flowey_crate: &str, |
| 44 | repo_root: &Path, |
| 45 | ) -> anyhow::Result<()> { |
| 46 | let cli = Cli::<P>::parse(); |
| 47 | |
| 48 | // Check if the runtime variable DB includes a "FLOWEY_LOG" variable, and |
| 49 | // use that to override the log level. |
| 50 | // |
| 51 | // This mechanism is in-place because some YAML pipeline defn langs (*cough* |
| 52 | // ADO *cough*) don't let you set pipeline-level env vars which are |
| 53 | // automatically inherited by all shell contexts. |
| 54 | let mut log_override = None; |
| 55 | if let Commands::VarDb(var_db::VarDb { job_idx, .. }) |
| 56 | | Commands::ExecSnippet(exec_snippet::ExecSnippet { job_idx, .. }) = &cli.command |
| 57 | { |
| 58 | log_override = try_get_flowey_log(*job_idx).unwrap_or_default(); |
| 59 | } |
| 60 | |
| 61 | if let Some(log_level) = log_override { |
| 62 | ci_logger::init_with_level(&log_level).unwrap(); |
| 63 | } else { |
| 64 | ci_logger::init("FLOWEY_LOG").unwrap(); |
| 65 | } |
| 66 | |
| 67 | match cli.command { |
| 68 | Commands::Debug(cmd) => cmd.run(), |
| 69 | Commands::Pipeline(cmd) => cmd.run(flowey_crate, repo_root), |
| 70 | Commands::Regen(cmd) => cmd.run(repo_root), |
| 71 | Commands::ExecSnippet(cmd) => cmd.run(), |
| 72 | Commands::VarDb(cmd) => cmd.run(), |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | #[derive(Copy, Clone, ValueEnum, Serialize, Deserialize)] |
| 77 | pub enum FlowBackendCli { |
| 78 | Local, |
| 79 | Ado, |
| 80 | Github, |
| 81 | } |
| 82 | |
| 83 | impl From<FlowBackendCli> for FlowBackend { |
| 84 | fn from(v: FlowBackendCli) -> FlowBackend { |
| 85 | match v { |
| 86 | FlowBackendCli::Local => FlowBackend::Local, |
| 87 | FlowBackendCli::Ado => FlowBackend::Ado, |
| 88 | FlowBackendCli::Github => FlowBackend::Github, |
| 89 | } |
| 90 | } |
| 91 | } |
| 92 | |
| 93 | fn try_get_flowey_log(job_idx: usize) -> anyhow::Result<Option<String>> { |
| 94 | // skip if the env var is already set |
| 95 | if std::env::var("FLOWEY_LOG").is_err() { |
| 96 | let log_level = var_db::open_var_db(job_idx)? |
| 97 | .try_get_var("FLOWEY_LOG") |
| 98 | .map(|(val, _)| { |
| 99 | serde_json::from_slice::<String>(&val) |
| 100 | .expect("found FLOWEY_LOG in db, but it wasn't a json string!") |
| 101 | }); |
| 102 | |
| 103 | if let Some(log_level) = log_level { |
| 104 | return Ok(Some(log_level)); |
| 105 | } |
| 106 | } |
| 107 | |
| 108 | Ok(None) |
| 109 | } |
| 110 | |