fix(cli): reduce noise & better track progress within Harmony #91
12
Cargo.lock
generated
12
Cargo.lock
generated
@ -1821,6 +1821,7 @@ dependencies = [
|
|||||||
"harmony",
|
"harmony",
|
||||||
"harmony_tui",
|
"harmony_tui",
|
||||||
"indicatif",
|
"indicatif",
|
||||||
|
"indicatif-log-bridge",
|
||||||
"inquire",
|
"inquire",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"log",
|
"log",
|
||||||
@ -1840,6 +1841,7 @@ dependencies = [
|
|||||||
"futures-util",
|
"futures-util",
|
||||||
"harmony_cli",
|
"harmony_cli",
|
||||||
"indicatif",
|
"indicatif",
|
||||||
|
"indicatif-log-bridge",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"log",
|
"log",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
@ -2451,6 +2453,16 @@ dependencies = [
|
|||||||
"web-time",
|
"web-time",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indicatif-log-bridge"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "63703cf9069b85dbe6fe26e1c5230d013dee99d3559cd3d02ba39e099ef7ab02"
|
||||||
|
dependencies = [
|
||||||
|
"indicatif",
|
||||||
|
"log",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indoc"
|
name = "indoc"
|
||||||
version = "2.0.6"
|
version = "2.0.6"
|
||||||
|
|||||||
@ -13,8 +13,7 @@ use harmony_cli::cli_logger;
|
|||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
env_logger::init();
|
let cli_logger_handle = cli_logger::init();
|
||||||
let cli_logger_handle = tokio::spawn(cli_logger::init());
|
|
||||||
|
|
||||||
let topology = K8sAnywhereTopology::from_env();
|
let topology = K8sAnywhereTopology::from_env();
|
||||||
let mut maestro = Maestro::initialize(Inventory::autoload(), topology)
|
let mut maestro = Maestro::initialize(Inventory::autoload(), topology)
|
||||||
|
|||||||
@ -2,19 +2,31 @@ use log::debug;
|
|||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use tokio::sync::broadcast;
|
use tokio::sync::broadcast;
|
||||||
|
|
||||||
|
use super::interpret::InterpretStatus;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum HarmonyEvent {
|
pub enum HarmonyEvent {
|
||||||
PrepareTopologyStarted { name: String },
|
HarmonyStarted,
|
||||||
|
PrepareTopologyStarted {
|
||||||
|
name: String,
|
||||||
|
},
|
||||||
|
TopologyPrepared {
|
||||||
|
name: String,
|
||||||
|
status: InterpretStatus,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
static HARMONY_EVENT_BUS: Lazy<broadcast::Sender<HarmonyEvent>> = Lazy::new(|| {
|
static HARMONY_EVENT_BUS: Lazy<broadcast::Sender<HarmonyEvent>> = Lazy::new(|| {
|
||||||
// TODO: Adjust channel capacity
|
// TODO: Adjust channel capacity
|
||||||
let (tx, _rx) = broadcast::channel(18);
|
let (tx, _rx) = broadcast::channel(100);
|
||||||
tx
|
tx
|
||||||
});
|
});
|
||||||
|
|
||||||
pub fn instrument(event: HarmonyEvent) {
|
pub fn instrument(event: HarmonyEvent) -> Result<(), &'static str> {
|
||||||
HARMONY_EVENT_BUS.send(event).expect("couldn't send event");
|
match HARMONY_EVENT_BUS.send(event) {
|
||||||
|
Ok(_) => Ok(()),
|
||||||
|
Err(_) => Err("send error: no subscribers"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn subscribe<F, Fut>(name: &str, mut handler: F)
|
pub async fn subscribe<F, Fut>(name: &str, mut handler: F)
|
||||||
|
|||||||
@ -44,13 +44,22 @@ impl<T: Topology> Maestro<T> {
|
|||||||
pub async fn prepare_topology(&self) -> Result<Outcome, InterpretError> {
|
pub async fn prepare_topology(&self) -> Result<Outcome, InterpretError> {
|
||||||
instrumentation::instrument(HarmonyEvent::PrepareTopologyStarted {
|
instrumentation::instrument(HarmonyEvent::PrepareTopologyStarted {
|
||||||
name: self.topology.name().to_string(),
|
name: self.topology.name().to_string(),
|
||||||
});
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
instrumentation::instrument(HarmonyEvent::TopologyPrepared {
|
||||||
|
name: self.topology.name().to_string(),
|
||||||
|
status: InterpretStatus::SUCCESS,
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let outcome = self.topology.ensure_ready().await?;
|
let outcome = self.topology.ensure_ready().await?;
|
||||||
info!(
|
|
||||||
"Topology '{}' readiness check complete: {}",
|
instrumentation::instrument(HarmonyEvent::TopologyPrepared {
|
||||||
self.topology.name(),
|
name: self.topology.name().to_string(),
|
||||||
outcome.status
|
status: outcome.status.clone(),
|
||||||
);
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
self.topology_preparation_result
|
self.topology_preparation_result
|
||||||
.lock()
|
.lock()
|
||||||
|
|||||||
@ -93,9 +93,8 @@ impl K8sAnywhereTopology {
|
|||||||
return Err("Failed to run 'helm -version'".to_string());
|
return Err("Failed to run 'helm -version'".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print the version output
|
|
||||||
let version_output = String::from_utf8_lossy(&version_result.stdout);
|
let version_output = String::from_utf8_lossy(&version_result.stdout);
|
||||||
println!("Helm version: {}", version_output.trim());
|
debug!("Helm version: {}", version_output.trim());
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -126,7 +125,7 @@ impl K8sAnywhereTopology {
|
|||||||
// TODO this deserves some refactoring, it is becoming a bit hard to figure out
|
// TODO this deserves some refactoring, it is becoming a bit hard to figure out
|
||||||
// be careful when making modifications here
|
// be careful when making modifications here
|
||||||
if k8s_anywhere_config.use_local_k3d {
|
if k8s_anywhere_config.use_local_k3d {
|
||||||
info!("Using local k3d cluster because of use_local_k3d set to true");
|
debug!("Using local k3d cluster because of use_local_k3d set to true");
|
||||||
} else {
|
} else {
|
||||||
if let Some(kubeconfig) = &k8s_anywhere_config.kubeconfig {
|
if let Some(kubeconfig) = &k8s_anywhere_config.kubeconfig {
|
||||||
debug!("Loading kubeconfig {kubeconfig}");
|
debug!("Loading kubeconfig {kubeconfig}");
|
||||||
|
|||||||
@ -10,7 +10,7 @@ use dockerfile_builder::Dockerfile;
|
|||||||
use dockerfile_builder::instruction::{CMD, COPY, ENV, EXPOSE, FROM, RUN, USER, WORKDIR};
|
use dockerfile_builder::instruction::{CMD, COPY, ENV, EXPOSE, FROM, RUN, USER, WORKDIR};
|
||||||
use dockerfile_builder::instruction_builder::CopyBuilder;
|
use dockerfile_builder::instruction_builder::CopyBuilder;
|
||||||
use futures_util::StreamExt;
|
use futures_util::StreamExt;
|
||||||
use log::{debug, error, info};
|
use log::{debug, error, info, log_enabled};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use tar::Archive;
|
use tar::Archive;
|
||||||
|
|
||||||
@ -164,10 +164,12 @@ impl RustWebapp {
|
|||||||
|
|
||||||
let docker = Docker::connect_with_socket_defaults().unwrap();
|
let docker = Docker::connect_with_socket_defaults().unwrap();
|
||||||
|
|
||||||
|
let quiet = !log_enabled!(log::Level::Debug);
|
||||||
|
|
||||||
let build_image_options = bollard::query_parameters::BuildImageOptionsBuilder::default()
|
let build_image_options = bollard::query_parameters::BuildImageOptionsBuilder::default()
|
||||||
.dockerfile("Dockerfile.harmony")
|
.dockerfile("Dockerfile.harmony")
|
||||||
.t(image_name)
|
.t(image_name)
|
||||||
.q(false)
|
.q(quiet)
|
||||||
.version(bollard::query_parameters::BuilderVersion::BuilderV1)
|
.version(bollard::query_parameters::BuilderVersion::BuilderV1)
|
||||||
.platform("linux/x86_64");
|
.platform("linux/x86_64");
|
||||||
|
|
||||||
|
|||||||
@ -17,6 +17,7 @@ console = "0.16.0"
|
|||||||
indicatif = "0.18.0"
|
indicatif = "0.18.0"
|
||||||
lazy_static = "1.5.0"
|
lazy_static = "1.5.0"
|
||||||
log.workspace = true
|
log.workspace = true
|
||||||
|
indicatif-log-bridge = "0.2.3"
|
||||||
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
|||||||
@ -1,28 +1,68 @@
|
|||||||
use harmony::instrumentation::{self, HarmonyEvent};
|
use harmony::instrumentation::{self, HarmonyEvent};
|
||||||
use indicatif::ProgressBar;
|
use indicatif::{MultiProgress, ProgressBar};
|
||||||
use std::sync::{Arc, Mutex};
|
use indicatif_log_bridge::LogWrapper;
|
||||||
|
use std::{
|
||||||
|
collections::{HashMap, hash_map},
|
||||||
|
sync::{Arc, Mutex},
|
||||||
|
};
|
||||||
|
|
||||||
pub async fn init() {
|
pub fn init() -> tokio::task::JoinHandle<()> {
|
||||||
instrumentation::subscribe("CLI Logger", {
|
configure_logger();
|
||||||
let current_spinner = Arc::new(Mutex::new(None::<ProgressBar>));
|
let handle = tokio::spawn(handle_events());
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if instrumentation::instrument(HarmonyEvent::HarmonyStarted).is_ok() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handle
|
||||||
|
}
|
||||||
|
|
||||||
|
fn configure_logger() {
|
||||||
|
let logger =
|
||||||
|
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).build();
|
||||||
|
let level = logger.filter();
|
||||||
|
let multi = MultiProgress::new();
|
||||||
|
LogWrapper::new(multi.clone(), logger).try_init().unwrap();
|
||||||
|
log::set_max_level(level);
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_events() {
|
||||||
|
instrumentation::subscribe("Harmony CLI Logger", {
|
||||||
|
let progresses: Arc<Mutex<HashMap<String, MultiProgress>>> =
|
||||||
|
Arc::new(Mutex::new(HashMap::new()));
|
||||||
|
let topology_prepare_progress = Arc::new(Mutex::new(None::<ProgressBar>));
|
||||||
|
|
||||||
move |event| {
|
move |event| {
|
||||||
let spinner_clone = Arc::clone(¤t_spinner);
|
let progresses_clone = Arc::clone(&progresses);
|
||||||
|
let topology_prepare_progress_clone = Arc::clone(&topology_prepare_progress);
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
let mut spinner_guard = spinner_clone.lock().unwrap();
|
let mut progresses = progresses_clone.lock().unwrap();
|
||||||
|
let mut topology_prepare_progress = topology_prepare_progress_clone.lock().unwrap();
|
||||||
|
|
||||||
match event {
|
match event {
|
||||||
|
HarmonyEvent::HarmonyStarted => {}
|
||||||
HarmonyEvent::PrepareTopologyStarted { name } => {
|
HarmonyEvent::PrepareTopologyStarted { name } => {
|
||||||
println!(
|
let multi_progress = crate::progress::new_section(format!(
|
||||||
"{} Preparing environment: {name}...",
|
"{} Preparing environment: {name}...",
|
||||||
crate::theme::EMOJI_TOPOLOGY
|
crate::theme::EMOJI_TOPOLOGY,
|
||||||
);
|
));
|
||||||
|
(*progresses).insert(name, multi_progress);
|
||||||
}
|
}
|
||||||
|
HarmonyEvent::TopologyPrepared { name, status } => match status {
|
||||||
|
harmony::interpret::InterpretStatus::SUCCESS => todo!(),
|
||||||
|
harmony::interpret::InterpretStatus::FAILURE => todo!(),
|
||||||
|
harmony::interpret::InterpretStatus::RUNNING => todo!(),
|
||||||
|
harmony::interpret::InterpretStatus::QUEUED => todo!(),
|
||||||
|
harmony::interpret::InterpretStatus::BLOCKED => todo!(),
|
||||||
|
harmony::interpret::InterpretStatus::NOOP => todo!(),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.await
|
.await;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,7 @@ use harmony::{score::Score, topology::Topology};
|
|||||||
use inquire::Confirm;
|
use inquire::Confirm;
|
||||||
|
|
||||||
pub mod cli_logger; // FIXME: Don't make me pub
|
pub mod cli_logger; // FIXME: Don't make me pub
|
||||||
|
|
|||||||
|
pub mod progress;
|
||||||
pub mod theme;
|
pub mod theme;
|
||||||
|
|
||||||
#[cfg(feature = "tui")]
|
#[cfg(feature = "tui")]
|
||||||
|
|||||||
40
harmony_cli/src/progress.rs
Normal file
40
harmony_cli/src/progress.rs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use indicatif::{MultiProgress, ProgressBar};
|
||||||
|
|
||||||
|
pub fn new_section(title: String) -> MultiProgress {
|
||||||
|
let multi_progress = MultiProgress::new();
|
||||||
|
let _ = multi_progress.println(title);
|
||||||
|
|
||||||
|
multi_progress
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_spinner(multi_progress: &MultiProgress, message: String) -> ProgressBar {
|
||||||
|
let progress = multi_progress.add(ProgressBar::new_spinner());
|
||||||
|
|
||||||
|
progress.set_style(crate::theme::SPINNER_STYLE.clone());
|
||||||
|
progress.set_message(message);
|
||||||
|
progress.enable_steady_tick(Duration::from_millis(100));
|
||||||
|
|
||||||
|
progress
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn success(multi_progress: &MultiProgress, progress: Option<ProgressBar>, message: String) {
|
||||||
|
if let Some(progress) = progress {
|
||||||
|
multi_progress.remove(&progress)
|
||||||
|
}
|
||||||
|
|
||||||
|
let progress = multi_progress.add(ProgressBar::new_spinner());
|
||||||
|
progress.set_style(crate::theme::SUCCESS_SPINNER_STYLE.clone());
|
||||||
|
progress.finish_with_message(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn error(multi_progress: &MultiProgress, progress: Option<ProgressBar>, message: String) {
|
||||||
|
if let Some(progress) = progress {
|
||||||
|
multi_progress.remove(&progress)
|
||||||
|
}
|
||||||
|
|
||||||
|
let progress = multi_progress.add(ProgressBar::new_spinner());
|
||||||
|
progress.set_style(crate::theme::ERROR_SPINNER_STYLE.clone());
|
||||||
|
progress.finish_with_message(message);
|
||||||
|
}
|
||||||
@ -20,3 +20,4 @@ console = "0.16.0"
|
|||||||
lazy_static = "1.5.0"
|
lazy_static = "1.5.0"
|
||||||
once_cell = "1.21.3"
|
once_cell = "1.21.3"
|
||||||
harmony_cli = { path = "../harmony_cli" }
|
harmony_cli = { path = "../harmony_cli" }
|
||||||
|
indicatif-log-bridge = "0.2.3"
|
||||||
|
|||||||
@ -1,61 +1,106 @@
|
|||||||
use indicatif::ProgressBar;
|
use indicatif::{MultiProgress, ProgressBar};
|
||||||
|
use indicatif_log_bridge::LogWrapper;
|
||||||
use log::error;
|
use log::error;
|
||||||
use std::{
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
time::Duration,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::instrumentation::{self, HarmonyComposerEvent};
|
use crate::instrumentation::{self, HarmonyComposerEvent};
|
||||||
|
|
||||||
pub async fn init() {
|
pub fn init() -> tokio::task::JoinHandle<()> {
|
||||||
|
configure_logger();
|
||||||
|
let handle = tokio::spawn(handle_events());
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if instrumentation::instrument(HarmonyComposerEvent::HarmonyComposerStarted).is_ok() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handle
|
||||||
|
}
|
||||||
|
|
||||||
|
fn configure_logger() {
|
||||||
|
let logger =
|
||||||
|
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).build();
|
||||||
|
let level = logger.filter();
|
||||||
|
let multi = MultiProgress::new();
|
||||||
|
LogWrapper::new(multi.clone(), logger).try_init().unwrap();
|
||||||
|
log::set_max_level(level);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn handle_events() {
|
||||||
|
const PROGRESS_SETUP: &str = "project-initialization";
|
||||||
|
const PROGRESS_DEPLOYMENT: &str = "deployment";
|
||||||
|
|
||||||
instrumentation::subscribe("Harmony Composer Logger", {
|
instrumentation::subscribe("Harmony Composer Logger", {
|
||||||
let current_spinner = Arc::new(Mutex::new(None::<ProgressBar>));
|
let progresses: Arc<Mutex<HashMap<String, MultiProgress>>> =
|
||||||
|
Arc::new(Mutex::new(HashMap::new()));
|
||||||
|
let compilation_progress = Arc::new(Mutex::new(None::<ProgressBar>));
|
||||||
|
|
||||||
move |event| {
|
move |event| {
|
||||||
let spinner_clone = Arc::clone(¤t_spinner);
|
let progresses_clone = Arc::clone(&progresses);
|
||||||
|
let compilation_progress_clone = Arc::clone(&compilation_progress);
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
let mut spinner_guard = spinner_clone.lock().unwrap();
|
let mut progresses_guard = progresses_clone.lock().unwrap();
|
||||||
|
let mut compilation_progress_guard = compilation_progress_clone.lock().unwrap();
|
||||||
|
|
||||||
match event {
|
match event {
|
||||||
|
HarmonyComposerEvent::HarmonyComposerStarted => {}
|
||||||
HarmonyComposerEvent::ProjectInitializationStarted => {
|
HarmonyComposerEvent::ProjectInitializationStarted => {
|
||||||
println!(
|
let multi_progress = harmony_cli::progress::new_section(format!(
|
||||||
"{} Initializing Harmony project...",
|
"{} Initializing Harmony project...",
|
||||||
harmony_cli::theme::EMOJI_HARMONY
|
harmony_cli::theme::EMOJI_HARMONY,
|
||||||
);
|
));
|
||||||
|
(*progresses_guard).insert(PROGRESS_SETUP.to_string(), multi_progress);
|
||||||
}
|
}
|
||||||
HarmonyComposerEvent::ProjectInitialized => println!("\n"),
|
HarmonyComposerEvent::ProjectInitialized => println!("\n"),
|
||||||
HarmonyComposerEvent::ProjectCompilationStarted { details } => {
|
HarmonyComposerEvent::ProjectCompilationStarted { details } => {
|
||||||
let progress = ProgressBar::new_spinner();
|
let initialization_progress =
|
||||||
progress.set_style(harmony_cli::theme::SPINNER_STYLE.clone());
|
(*progresses_guard).get(PROGRESS_SETUP).unwrap();
|
||||||
progress.set_message(details);
|
let _ = initialization_progress.clear();
|
||||||
progress.enable_steady_tick(Duration::from_millis(100));
|
|
||||||
*spinner_guard = Some(progress);
|
let progress =
|
||||||
|
harmony_cli::progress::add_spinner(initialization_progress, details);
|
||||||
|
*compilation_progress_guard = Some(progress);
|
||||||
}
|
}
|
||||||
HarmonyComposerEvent::ProjectCompiled => {
|
HarmonyComposerEvent::ProjectCompiled => {
|
||||||
if let Some(progress) = spinner_guard.take() {
|
let initialization_progress =
|
||||||
progress.set_style(harmony_cli::theme::SUCCESS_SPINNER_STYLE.clone());
|
(*progresses_guard).get(PROGRESS_SETUP).unwrap();
|
||||||
progress.finish_with_message("project compiled");
|
|
||||||
}
|
harmony_cli::progress::success(
|
||||||
|
initialization_progress,
|
||||||
|
(*compilation_progress_guard).take(),
|
||||||
|
"project compiled".to_string(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
HarmonyComposerEvent::ProjectCompilationFailed { details } => {
|
HarmonyComposerEvent::ProjectCompilationFailed { details } => {
|
||||||
if let Some(progress) = spinner_guard.take() {
|
let initialization_progress =
|
||||||
progress.set_style(harmony_cli::theme::ERROR_SPINNER_STYLE.clone());
|
(*progresses_guard).get(PROGRESS_SETUP).unwrap();
|
||||||
progress.finish_with_message("failed to compile project");
|
|
||||||
error!("{details}");
|
harmony_cli::progress::error(
|
||||||
}
|
initialization_progress,
|
||||||
|
(*compilation_progress_guard).take(),
|
||||||
|
"failed to compile project".to_string(),
|
||||||
|
);
|
||||||
|
|
||||||
|
error!("{details}");
|
||||||
}
|
}
|
||||||
HarmonyComposerEvent::DeploymentStarted { target } => {
|
HarmonyComposerEvent::DeploymentStarted { target } => {
|
||||||
println!(
|
let multi_progress = harmony_cli::progress::new_section(format!(
|
||||||
"{} Starting deployment to {target}...\n",
|
"{} Starting deployment to {target}...\n\n",
|
||||||
harmony_cli::theme::EMOJI_DEPLOY
|
harmony_cli::theme::EMOJI_DEPLOY
|
||||||
);
|
));
|
||||||
|
(*progresses_guard).insert(PROGRESS_DEPLOYMENT.to_string(), multi_progress);
|
||||||
}
|
}
|
||||||
HarmonyComposerEvent::DeploymentCompleted { details } => println!("\n"),
|
HarmonyComposerEvent::DeploymentCompleted { details } => println!("\n"),
|
||||||
HarmonyComposerEvent::Shutdown => {
|
HarmonyComposerEvent::Shutdown => {
|
||||||
if let Some(progress) = spinner_guard.take() {
|
for (_, progresses) in (*progresses_guard).iter() {
|
||||||
progress.abandon();
|
progresses.clear().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ use tokio::sync::broadcast;
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum HarmonyComposerEvent {
|
pub enum HarmonyComposerEvent {
|
||||||
|
HarmonyComposerStarted,
|
||||||
ProjectInitializationStarted,
|
ProjectInitializationStarted,
|
||||||
ProjectInitialized,
|
ProjectInitialized,
|
||||||
ProjectCompilationStarted { details: String },
|
ProjectCompilationStarted { details: String },
|
||||||
@ -21,10 +22,11 @@ static HARMONY_COMPOSER_EVENT_BUS: Lazy<broadcast::Sender<HarmonyComposerEvent>>
|
|||||||
tx
|
tx
|
||||||
});
|
});
|
||||||
|
|
||||||
pub fn instrument(event: HarmonyComposerEvent) {
|
pub fn instrument(event: HarmonyComposerEvent) -> Result<(), &'static str> {
|
||||||
HARMONY_COMPOSER_EVENT_BUS
|
match HARMONY_COMPOSER_EVENT_BUS.send(event) {
|
||||||
.send(event)
|
Ok(_) => Ok(()),
|
||||||
.expect("couldn't send event");
|
Err(_) => Err("send error: no subscribers"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn subscribe<F, Fut>(name: &str, mut handler: F)
|
pub async fn subscribe<F, Fut>(name: &str, mut handler: F)
|
||||||
|
|||||||
@ -70,15 +70,14 @@ struct AllArgs {
|
|||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
env_logger::init();
|
let hc_logger_handle = harmony_composer_logger::init();
|
||||||
let hc_logger_handle = tokio::spawn(harmony_composer_logger::init());
|
|
||||||
let cli_args = GlobalArgs::parse();
|
let cli_args = GlobalArgs::parse();
|
||||||
|
|
||||||
let harmony_path = Path::new(&cli_args.harmony_path)
|
let harmony_path = Path::new(&cli_args.harmony_path)
|
||||||
.try_exists()
|
.try_exists()
|
||||||
.expect("couldn't check if path exists");
|
.expect("couldn't check if path exists");
|
||||||
|
|
||||||
instrumentation::instrument(HarmonyComposerEvent::ProjectInitializationStarted);
|
instrumentation::instrument(HarmonyComposerEvent::ProjectInitializationStarted).unwrap();
|
||||||
|
|
||||||
let harmony_bin_path: PathBuf = match harmony_path {
|
let harmony_bin_path: PathBuf = match harmony_path {
|
||||||
true => {
|
true => {
|
||||||
@ -92,7 +91,7 @@ async fn main() {
|
|||||||
false => todo!("implement autodetect code"),
|
false => todo!("implement autodetect code"),
|
||||||
};
|
};
|
||||||
|
|
||||||
instrumentation::instrument(HarmonyComposerEvent::ProjectInitialized);
|
instrumentation::instrument(HarmonyComposerEvent::ProjectInitialized).unwrap();
|
||||||
|
|
||||||
match cli_args.command {
|
match cli_args.command {
|
||||||
Some(command) => match command {
|
Some(command) => match command {
|
||||||
@ -127,17 +126,20 @@ async fn main() {
|
|||||||
let deploy = if args.staging {
|
let deploy = if args.staging {
|
||||||
instrumentation::instrument(HarmonyComposerEvent::DeploymentStarted {
|
instrumentation::instrument(HarmonyComposerEvent::DeploymentStarted {
|
||||||
target: "staging".to_string(),
|
target: "staging".to_string(),
|
||||||
});
|
})
|
||||||
|
.unwrap();
|
||||||
todo!("implement staging deployment")
|
todo!("implement staging deployment")
|
||||||
} else if args.prod {
|
} else if args.prod {
|
||||||
instrumentation::instrument(HarmonyComposerEvent::DeploymentStarted {
|
instrumentation::instrument(HarmonyComposerEvent::DeploymentStarted {
|
||||||
target: "prod".to_string(),
|
target: "prod".to_string(),
|
||||||
});
|
})
|
||||||
|
.unwrap();
|
||||||
todo!("implement prod deployment")
|
todo!("implement prod deployment")
|
||||||
} else {
|
} else {
|
||||||
instrumentation::instrument(HarmonyComposerEvent::DeploymentStarted {
|
instrumentation::instrument(HarmonyComposerEvent::DeploymentStarted {
|
||||||
target: "dev".to_string(),
|
target: "dev".to_string(),
|
||||||
});
|
})
|
||||||
|
.unwrap();
|
||||||
Command::new(harmony_bin_path).arg("-y").arg("-a").spawn()
|
Command::new(harmony_bin_path).arg("-y").arg("-a").spawn()
|
||||||
}
|
}
|
||||||
.expect("failed to run harmony deploy");
|
.expect("failed to run harmony deploy");
|
||||||
@ -145,7 +147,8 @@ async fn main() {
|
|||||||
let deploy_output = deploy.wait_with_output().unwrap();
|
let deploy_output = deploy.wait_with_output().unwrap();
|
||||||
instrumentation::instrument(HarmonyComposerEvent::DeploymentCompleted {
|
instrumentation::instrument(HarmonyComposerEvent::DeploymentCompleted {
|
||||||
details: String::from_utf8(deploy_output.stdout).unwrap(),
|
details: String::from_utf8(deploy_output.stdout).unwrap(),
|
||||||
});
|
})
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
Commands::All(_args) => todo!(
|
Commands::All(_args) => todo!(
|
||||||
"take all previous match arms and turn them into separate functions, and call them all one after the other"
|
"take all previous match arms and turn them into separate functions, and call them all one after the other"
|
||||||
@ -155,7 +158,7 @@ async fn main() {
|
|||||||
None => todo!("run interactively, ask for info on CLI"),
|
None => todo!("run interactively, ask for info on CLI"),
|
||||||
}
|
}
|
||||||
|
|
||||||
instrumentation::instrument(HarmonyComposerEvent::Shutdown);
|
instrumentation::instrument(HarmonyComposerEvent::Shutdown).unwrap();
|
||||||
|
|
||||||
let _ = tokio::try_join!(hc_logger_handle);
|
let _ = tokio::try_join!(hc_logger_handle);
|
||||||
}
|
}
|
||||||
@ -198,18 +201,20 @@ async fn compile_harmony(
|
|||||||
CompileMethod::LocalCargo => {
|
CompileMethod::LocalCargo => {
|
||||||
instrumentation::instrument(HarmonyComposerEvent::ProjectCompilationStarted {
|
instrumentation::instrument(HarmonyComposerEvent::ProjectCompilationStarted {
|
||||||
details: "compiling project with cargo".to_string(),
|
details: "compiling project with cargo".to_string(),
|
||||||
});
|
})
|
||||||
|
.unwrap();
|
||||||
compile_cargo(platform, harmony_location).await
|
compile_cargo(platform, harmony_location).await
|
||||||
}
|
}
|
||||||
CompileMethod::Docker => {
|
CompileMethod::Docker => {
|
||||||
instrumentation::instrument(HarmonyComposerEvent::ProjectCompilationStarted {
|
instrumentation::instrument(HarmonyComposerEvent::ProjectCompilationStarted {
|
||||||
details: "compiling project with docker".to_string(),
|
details: "compiling project with docker".to_string(),
|
||||||
});
|
})
|
||||||
|
.unwrap();
|
||||||
compile_docker(platform, harmony_location).await
|
compile_docker(platform, harmony_location).await
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
instrumentation::instrument(HarmonyComposerEvent::ProjectCompiled);
|
instrumentation::instrument(HarmonyComposerEvent::ProjectCompiled).unwrap();
|
||||||
path
|
path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user
See the PR comment above (in
examples/rust/main.rs) for more info