Files
honey-biscuit-workshop/workshop-baker/src/bake.rs
T
Catty Steve 8fd807f174 refactor!: extract execution engine into standalone workshop-engine
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.
2026-04-26 23:07:08 +08:00

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 {
// }