feat: Embed build scripts and extract into temp dir for build (#516)
This decouples the need for a published image for the bulid scripts and will now embed them into the binary instead. This will make it so that anyone that forks the CLI is able to make adjustments to the build scripts and use them immediately. This will be needed for testing #515
This commit is contained in:
parent
2149a75760
commit
a7d862abf0
17 changed files with 266 additions and 154 deletions
|
|
@ -1,4 +1,7 @@
|
|||
use std::path::{Path, PathBuf};
|
||||
use std::{
|
||||
env,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use blue_build_process_management::{
|
||||
drivers::{
|
||||
|
|
@ -23,12 +26,12 @@ use blue_build_utils::{
|
|||
use bon::Builder;
|
||||
use clap::Args;
|
||||
use log::{debug, info, trace, warn};
|
||||
use miette::{IntoDiagnostic, Result, bail};
|
||||
use miette::{Context, IntoDiagnostic, Result, bail};
|
||||
use oci_distribution::Reference;
|
||||
use rayon::prelude::*;
|
||||
use tempfile::TempDir;
|
||||
|
||||
use crate::commands::generate::GenerateCommand;
|
||||
use crate::{BuildScripts, commands::generate::GenerateCommand};
|
||||
|
||||
use super::BlueBuildCommand;
|
||||
|
||||
|
|
@ -186,6 +189,16 @@ impl BlueBuildCommand for BuildCommand {
|
|||
|
||||
recipes.into_iter().filter(|recipe| same.insert(recipe.clone())).collect()
|
||||
});
|
||||
let build_scripts_dir = BuildScripts::extract_mount_dir()?;
|
||||
let build_scripts_dir = build_scripts_dir
|
||||
.path()
|
||||
.strip_prefix(
|
||||
env::current_dir()
|
||||
.into_diagnostic()
|
||||
.wrap_err("Failed to get current_dir")?,
|
||||
)
|
||||
.into_diagnostic()
|
||||
.wrap_err("Failed to strip path prefix for build scripts dir")?;
|
||||
|
||||
recipe_paths.par_iter().try_for_each(|recipe| {
|
||||
GenerateCommand::builder()
|
||||
|
|
@ -196,6 +209,7 @@ impl BlueBuildCommand for BuildCommand {
|
|||
)
|
||||
.skip_validation(self.skip_validation)
|
||||
.maybe_platform(self.platform)
|
||||
.build_scripts_dir(build_scripts_dir)
|
||||
.recipe(recipe)
|
||||
.drivers(self.drivers)
|
||||
.build()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
use std::{
|
||||
env,
|
||||
ops::Not,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
|
@ -10,19 +9,16 @@ use blue_build_process_management::drivers::{
|
|||
use blue_build_recipe::Recipe;
|
||||
use blue_build_template::{ContainerFileTemplate, Template};
|
||||
use blue_build_utils::{
|
||||
constants::{
|
||||
BB_SKIP_VALIDATION, BUILD_SCRIPTS_IMAGE_REF, CONFIG_PATH, RECIPE_FILE, RECIPE_PATH,
|
||||
},
|
||||
constants::{BB_SKIP_VALIDATION, CONFIG_PATH, RECIPE_FILE, RECIPE_PATH},
|
||||
syntax_highlighting::{self, DefaultThemes},
|
||||
};
|
||||
use bon::Builder;
|
||||
use cached::proc_macro::cached;
|
||||
use clap::{Args, crate_version};
|
||||
use clap::Args;
|
||||
use log::{debug, info, trace, warn};
|
||||
use miette::{IntoDiagnostic, Result};
|
||||
use oci_distribution::Reference;
|
||||
|
||||
use crate::{commands::validate::ValidateCommand, shadow};
|
||||
use crate::commands::validate::ValidateCommand;
|
||||
|
||||
use super::BlueBuildCommand;
|
||||
|
||||
|
|
@ -80,6 +76,10 @@ pub struct GenerateCommand {
|
|||
#[builder(default)]
|
||||
skip_validation: bool,
|
||||
|
||||
#[clap(skip)]
|
||||
#[builder(into)]
|
||||
build_scripts_dir: Option<PathBuf>,
|
||||
|
||||
#[clap(flatten)]
|
||||
#[builder(default)]
|
||||
drivers: DriverArgs,
|
||||
|
|
@ -149,12 +149,15 @@ impl GenerateCommand {
|
|||
.build(),
|
||||
)?
|
||||
.digest;
|
||||
let build_scripts_image = &determine_scripts_tag(self.platform)?;
|
||||
let repo = &Driver::get_repo_url()?;
|
||||
let build_features = &[
|
||||
#[cfg(feature = "bootc")]
|
||||
"bootc".into(),
|
||||
];
|
||||
let build_scripts_dir = self
|
||||
.build_scripts_dir
|
||||
.as_deref()
|
||||
.unwrap_or_else(|| Path::new(".bluebuild-scripts"));
|
||||
|
||||
let template = ContainerFileTemplate::builder()
|
||||
.os_version(
|
||||
|
|
@ -168,7 +171,7 @@ impl GenerateCommand {
|
|||
.recipe_path(recipe_path.as_path())
|
||||
.registry(®istry)
|
||||
.repo(repo)
|
||||
.build_scripts_image(build_scripts_image)
|
||||
.build_scripts_dir(build_scripts_dir)
|
||||
.base_digest(base_digest)
|
||||
.maybe_nushell_version(recipe.nushell_version.as_ref())
|
||||
.build_features(build_features)
|
||||
|
|
@ -188,40 +191,3 @@ impl GenerateCommand {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cached(
|
||||
result = true,
|
||||
key = "Option<Platform>",
|
||||
convert = r#"{ platform }"#,
|
||||
sync_writes = "by_key"
|
||||
)]
|
||||
fn determine_scripts_tag(platform: Option<Platform>) -> Result<Reference> {
|
||||
trace!("determine_scripts_tag({platform:?})");
|
||||
|
||||
let opts = GetMetadataOpts::builder().maybe_platform(platform);
|
||||
format!("{BUILD_SCRIPTS_IMAGE_REF}:{}", shadow::COMMIT_HASH)
|
||||
.parse()
|
||||
.into_diagnostic()
|
||||
.and_then(|image| {
|
||||
Driver::get_metadata(opts.clone().image(&image).build())
|
||||
.inspect_err(|e| trace!("{e:?}"))
|
||||
.map(|_| image)
|
||||
})
|
||||
.or_else(|_| {
|
||||
let image: Reference = format!("{BUILD_SCRIPTS_IMAGE_REF}:{}", shadow::BRANCH)
|
||||
.parse()
|
||||
.into_diagnostic()?;
|
||||
Driver::get_metadata(opts.clone().image(&image).build())
|
||||
.inspect_err(|e| trace!("{e:?}"))
|
||||
.map(|_| image)
|
||||
})
|
||||
.or_else(|_| {
|
||||
let image: Reference = format!("{BUILD_SCRIPTS_IMAGE_REF}:v{}", crate_version!())
|
||||
.parse()
|
||||
.into_diagnostic()?;
|
||||
Driver::get_metadata(opts.image(&image).build())
|
||||
.inspect_err(|e| trace!("{e:?}"))
|
||||
.map(|_| image)
|
||||
})
|
||||
.inspect(|image| debug!("Using build scripts image: {image}"))
|
||||
}
|
||||
|
|
|
|||
85
src/lib.rs
85
src/lib.rs
|
|
@ -1,6 +1,89 @@
|
|||
//! The root library for blue-build.
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
||||
shadow_rs::shadow!(shadow);
|
||||
use std::{
|
||||
fs::{self, OpenOptions},
|
||||
io::{Read, Write},
|
||||
ops::Not,
|
||||
os::unix::fs::PermissionsExt,
|
||||
};
|
||||
|
||||
use blue_build_utils::constants::{BLUE_BUILD_SCRIPTS_DIR_IGNORE, GITIGNORE_PATH};
|
||||
use miette::{Context, IntoDiagnostic, Result, miette};
|
||||
use rust_embed::Embed;
|
||||
use tempfile::TempDir;
|
||||
|
||||
pub mod commands;
|
||||
|
||||
shadow_rs::shadow!(shadow);
|
||||
|
||||
#[derive(Embed)]
|
||||
#[folder = "scripts/"]
|
||||
pub(crate) struct BuildScripts;
|
||||
|
||||
impl BuildScripts {
|
||||
pub fn extract_mount_dir() -> Result<TempDir> {
|
||||
Self::update_gitignore()?;
|
||||
|
||||
let tempdir = TempDir::with_prefix_in(".bluebuild-scripts_", ".")
|
||||
.into_diagnostic()
|
||||
.wrap_err("Failed to create tempdir for build scripts.")?;
|
||||
|
||||
for file_path in Self::iter() {
|
||||
let file = Self::get(file_path.as_ref())
|
||||
.ok_or_else(|| miette!("Failed to get file {file_path}"))?;
|
||||
let file_path = tempdir.path().join(&*file_path);
|
||||
fs::write(&file_path, &file.data)
|
||||
.into_diagnostic()
|
||||
.wrap_err_with(|| {
|
||||
format!("Failed to write build script file {}", file_path.display())
|
||||
})?;
|
||||
|
||||
let mut perm = fs::metadata(&file_path)
|
||||
.into_diagnostic()
|
||||
.wrap_err_with(|| {
|
||||
format!(
|
||||
"Failed to get file permissions for file {}",
|
||||
file_path.display()
|
||||
)
|
||||
})?
|
||||
.permissions();
|
||||
|
||||
perm.set_mode(0o755);
|
||||
fs::set_permissions(&file_path, perm).into_diagnostic()?;
|
||||
}
|
||||
|
||||
Ok(tempdir)
|
||||
}
|
||||
|
||||
fn update_gitignore() -> Result<()> {
|
||||
let file = &mut OpenOptions::new()
|
||||
.read(true)
|
||||
.append(true)
|
||||
.create(true)
|
||||
.open(GITIGNORE_PATH)
|
||||
.into_diagnostic()
|
||||
.wrap_err_with(|| format!("Failed to open {GITIGNORE_PATH} for editing"))?;
|
||||
|
||||
let ignore_contents = {
|
||||
let mut cont = String::new();
|
||||
file.read_to_string(&mut cont)
|
||||
.into_diagnostic()
|
||||
.wrap_err_with(|| format!("Failed to read {GITIGNORE_PATH}"))?;
|
||||
cont
|
||||
};
|
||||
|
||||
if ignore_contents
|
||||
.contains(BLUE_BUILD_SCRIPTS_DIR_IGNORE)
|
||||
.not()
|
||||
{
|
||||
writeln!(file, "{BLUE_BUILD_SCRIPTS_DIR_IGNORE}")
|
||||
.into_diagnostic()
|
||||
.wrap_err_with(|| {
|
||||
format!("Failed to add {BLUE_BUILD_SCRIPTS_DIR_IGNORE} to {GITIGNORE_PATH}")
|
||||
})?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue