8fd807f174
crate BREAKING CHANGE: Moved engine/ module (cgroups, executor, pm, upm, types) and shared types (command, repology, time) from workshop-baker to new workshop-engine crate. All internal error types consolidated into workshop-engine::error. Import paths changed throughout codebase.
121 lines
3.6 KiB
Rust
121 lines
3.6 KiB
Rust
use workshop_engine::{Engine, EventSender, ExecutionContext};
|
|
use crate::bake::parser::Function;
|
|
use crate::bake::constant::{DEFAULT_WORKSPACE, TRIVIAL_SCRIPT_NAME};
|
|
use crate::bake::error::BakeError;
|
|
use crate::cli::Cli;
|
|
use crate::prebake::PrebakeConfig;
|
|
use crate::prebake::security::get_drop_after;
|
|
use crate::prebake::stage::PrebakeStage;
|
|
use crate::prebake;
|
|
use std::path::{Path, PathBuf};
|
|
|
|
mod builder;
|
|
pub mod constant;
|
|
mod decorator;
|
|
pub mod parser;
|
|
pub mod error;
|
|
mod schedule;
|
|
|
|
pub async fn bake(
|
|
script_path: &Path,
|
|
bake_base_path: &Path,
|
|
prebake_path: &Path,
|
|
cli: &Cli,
|
|
ctx: &mut ExecutionContext,
|
|
event_tx: EventSender,
|
|
) -> Result<(), BakeError> {
|
|
let script_content = std::fs::read_to_string(script_path)?;
|
|
let prebake_content = std::fs::read_to_string(prebake_path)?;
|
|
let prebake = prebake::parse(prebake_content.as_str()).map_err(|e| {
|
|
log::error!("Failed to parse prebake.yml: {}", e);
|
|
log::error!("This is unexpected!");
|
|
BakeError::YamlParseError(e)
|
|
})?;
|
|
let workspace = get_workspace(&prebake);
|
|
let functions = parser::parse_script(&script_content)?;
|
|
|
|
let has_pipeline = functions.pipeline_functions.iter().any(|f| {
|
|
f.decorators
|
|
.iter()
|
|
.any(|d| matches!(d, decorator::Decorator::Pipeline))
|
|
});
|
|
let trivial = false;
|
|
let use_template = true;
|
|
|
|
let engine = Engine::new();
|
|
if let Some(env) = &prebake.envvars {
|
|
if let Some(prebake_env) = &env.bake {
|
|
ctx.env_vars.extend(prebake_env.clone());
|
|
}
|
|
}
|
|
|
|
if !has_pipeline || trivial {
|
|
let function = Function {
|
|
name: TRIVIAL_SCRIPT_NAME.to_string(),
|
|
decorators: vec![],
|
|
body: script_content,
|
|
};
|
|
let script =
|
|
builder::build_script(&function, bake_base_path, &workspace, None, use_template)?;
|
|
let result = engine.execute_script(&script, &ctx, &event_tx).await;
|
|
result?;
|
|
} else {
|
|
let sorted_functions = schedule::sort_function(functions.pipeline_functions)?;
|
|
let remaining = functions.remaining_code;
|
|
for func in sorted_functions {
|
|
let mut modified_func = func.clone();
|
|
modified_func.body = remaining.clone() + &func.body;
|
|
let script = builder::build_script(
|
|
&modified_func,
|
|
bake_base_path,
|
|
&workspace,
|
|
None,
|
|
use_template,
|
|
)?;
|
|
let result = engine.execute_script(&script, &ctx, &event_tx).await;
|
|
result?;
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn get_workspace(prebake_config: &PrebakeConfig) -> PathBuf {
|
|
prebake_config
|
|
.bootstrap
|
|
.as_ref()
|
|
.and_then(|b| b.workspace.as_ref())
|
|
.map(|ws| {
|
|
if ws.fallback {
|
|
PathBuf::from(DEFAULT_WORKSPACE)
|
|
} else {
|
|
PathBuf::from(ws.path.clone())
|
|
}
|
|
})
|
|
.unwrap_or_else(|| PathBuf::from(DEFAULT_WORKSPACE))
|
|
}
|
|
|
|
fn privileged(prebake_config: &PrebakeConfig) -> bool {
|
|
if let Some(bootstrap) = &prebake_config.bootstrap {
|
|
if bootstrap.user == "root" {
|
|
return true;
|
|
}
|
|
}
|
|
let drop_after = get_drop_after(&prebake_config.security).unwrap_or_default();
|
|
PrebakeStage::Never == drop_after
|
|
}
|
|
|
|
type TaskResult = Result<(), BakeError>;
|
|
|
|
type TaskFn = Box<dyn FnOnce() -> TaskResult + Send>;
|
|
|
|
// TODO: Learn closure and continue
|
|
// async fn run<F>(f:F) -> TaskFn {
|
|
// let engine = Engine::new();
|
|
// engine.execute_script
|
|
// }
|
|
|
|
// fn with_timeout<F>(f: F, duration: i32) -> TaskFn {
|
|
|
|
// }
|