Skip to main content

harmont_cli/cli/
mod.rs

1pub mod init;
2pub mod pipelines;
3pub mod plugin;
4pub mod render;
5pub mod run;
6pub mod version;
7
8pub use plugin::PluginCommand;
9pub use run::RunArgs;
10
11use std::path::PathBuf;
12
13use anyhow::Result;
14use clap::{Parser, Subcommand};
15
16use crate::context::RunContext;
17
18#[derive(Debug, Parser)]
19#[command(
20    name = "hm",
21    version,
22    about = "hm — CLI for the Harmont CI platform",
23    long_about = "hm is the command-line interface for Harmont.\n\n\
24                   Run `hm run` to push local code through a pipeline without committing.",
25    propagate_version = true,
26    arg_required_else_help = true,
27    disable_help_subcommand = true
28)]
29pub struct Cli {
30    /// Enable verbose/debug logging.
31    #[arg(long, short, global = true)]
32    pub verbose: bool,
33
34    /// Disable colored output.
35    #[arg(long, global = true)]
36    pub no_color: bool,
37
38    /// Write a Chrome trace JSON to the given path for performance analysis.
39    #[arg(long, global = true, hide = true, value_name = "PATH")]
40    pub debug_trace: Option<std::path::PathBuf>,
41
42    #[command(subcommand)]
43    pub command: Command,
44}
45
46#[derive(Debug, Clone, Subcommand)]
47pub enum Command {
48    /// Initialize a .hm/ pipeline from a project template.
49    Init(init::InitArgs),
50
51    /// Run a pipeline locally via Docker.
52    Run(RunArgs),
53
54    /// Print the pipeline discovery envelope (JSON) for every pipeline in the repo.
55    Pipelines(pipelines::PipelinesArgs),
56
57    /// Render one pipeline's v0 IR (JSON) without running it.
58    Render(render::RenderArgs),
59
60    /// Show hm version.
61    Version,
62
63    /// Manage plugins.
64    #[command(subcommand)]
65    Plugin(PluginCommand),
66
67    /// Manage harmont Docker image cache.
68    #[command(subcommand)]
69    Cache(CacheCommand),
70
71    /// Interact with the Harmont cloud API.
72    #[command(subcommand)]
73    Cloud(hm_plugin_cloud::cli::CloudCommand),
74}
75
76#[derive(Debug, Clone, Subcommand)]
77pub enum CacheCommand {
78    /// Save harmont Docker images to a cache directory.
79    Save(CacheSaveArgs),
80    /// Restore harmont Docker images from a cache directory.
81    Restore(CacheRestoreArgs),
82    /// Remove all cached workspaces and Docker images.
83    Clean,
84}
85
86#[derive(Debug, Clone, clap::Args)]
87pub struct CacheSaveArgs {
88    /// Directory to save image tars into.
89    pub dir: PathBuf,
90}
91
92#[derive(Debug, Clone, clap::Args)]
93pub struct CacheRestoreArgs {
94    /// Directory containing cached image tars.
95    pub dir: PathBuf,
96}
97
98/// Dispatch a parsed CLI command to the appropriate handler. Returns an exit code.
99///
100/// # Errors
101///
102/// Returns an error if the dispatched handler fails.
103pub async fn dispatch(command: Command, ctx: RunContext) -> Result<i32> {
104    match command {
105        Command::Init(args) => crate::commands::init::handle(args).await.map(|()| 0),
106        Command::Run(args) => crate::commands::run::handle(args, ctx).await,
107        Command::Pipelines(args) => crate::cli::pipelines::run(args).await.map(|()| 0),
108        Command::Render(args) => crate::cli::render::run(args).await.map(|()| 0),
109        Command::Cache(cmd) => match cmd {
110            CacheCommand::Save(args) => crate::commands::cache::handle_save(&args.dir).await,
111            CacheCommand::Restore(args) => crate::commands::cache::handle_restore(&args.dir).await,
112            CacheCommand::Clean => crate::commands::cache::handle_clean().await,
113        },
114        Command::Version => version::run().await.map(|()| 0),
115        Command::Plugin(cmd) => plugin::run(cmd).await.map(|()| 0),
116        Command::Cloud(cmd) => {
117            let env = std::env::vars().collect();
118            hm_plugin_cloud::cli::dispatch_command(cmd, env).await
119        }
120    }
121}