pub mod config; pub mod constant; pub mod error; pub mod event; pub mod plugin; pub mod stage; pub mod template; pub mod types; use crate::cli::Cli; use crate::finalize::constant::FINALIZE_STANDALONE_PLUGIN_PATH; use crate::finalize::plugin::fetch::{self, FetchArgument}; pub use config::*; pub use error::FinalizeError; use std::path::Path; use std::path::PathBuf; use workshop_engine::EventSender; pub fn parse(path: &Path) -> Result { let content = std::fs::read_to_string(path).map_err(FinalizeError::IoError)?; let config: FinalizeConfig = serde_yaml::from_str(&content)?; Ok(config) } pub async fn finalize( finalize_path: &Path, _cli: &Cli, ctx: &mut workshop_engine::ExecutionContext, event_tx: EventSender, ) -> Result<(), FinalizeError> { let mut finalize = parse(finalize_path)?; let validate_result = finalize.validate(); if let Err(errors) = validate_result { for error in &errors { log::error!("Error: {}", error); } return Err(FinalizeError::ValidateError(errors)); }; if ctx.standalone { // In standalone mode, finalize should download plugin by itself log::debug!("Downloading {} plugins", finalize.plugin.len()); let plugin_path = PathBuf::from(FINALIZE_STANDALONE_PLUGIN_PATH); // if plugin_path.exists() { // std::fs::remove_dir_all(&plugin_path).map_err(FinalizeError::IoError)?; // } for (name, data) in finalize.plugin.iter_mut() { log::info!("Downloading plugin {}", name); let (source, config) = data.iter_mut().next().unwrap_or_else(|| { panic!( "Internal Error: Plugin {} has no source configured, this should have been caught by validation!", name ) }); let fetch_argument = FetchArgument { checksum: config.checksum.clone(), shallow: config.shallow, }; fetch::fetch_plugin(source, name, &plugin_path, fetch_argument).await?; config.runtime.fspath = Some(plugin_path.join(name)); } } // Register Plugins log::info!("Registering {} plugins", finalize.plugin.len()); let registered_plugins = plugin::register(finalize.plugin, None)?; // Early hook let earlyhook_result = stage::hook::hook( finalize.hooks.as_ref().and_then(|h| h.early.as_ref()), ctx, event_tx.clone(), ®istered_plugins, ) .await; // Determine if we should continue with artifacts/latehook // If prior stages failed, we still send notification but skip artifacts let _prior_failed = earlyhook_result.is_err(); // Prepare artifacts // TODO: artifact stage implementation // Late hook stage::hook::hook( finalize.hooks.as_ref().and_then(|h| h.late.as_ref()), ctx, event_tx.clone(), ®istered_plugins, ) .await?; Ok(()) }