feat: snippets (#51)

## Goals

This PR adds snippets which is being discussed in #41 .

It will generate snippet lines for *ONLY* our containerfile module

- [x] allow for modules to specify snippets
- [x] append snippets to module run inside Containerfile
- [ ] write supporting test

## Preview
Recipe.yml

```yml
# image will be published to ghcr.io/<user>/<name>
name: orora

description: A starting point for further customization of uBlue images. Make your own! https://ublue.it/making-your-own/

base-image: ghcr.io/ublue-os/silverblue-main
image-version: latest # latest is also supported if you want new updates ASAP

modules:
  - type: signing
    snippets:
      - COPY --from=ghcr.io/blue-build/cli:latest-installer /out/BLUEBUILD /usr/bin/BLUEBUILD
```

Generated Container File snippet

```docker
RUN chmod +x /tmp/modules/signing/signing.sh && source /tmp/exports.sh && /tmp/modules/signing/signing.sh '{"type":"signing","snippets":["COPY --from=ghcr.io/blue-build/cli:latest-installer /out/BLUEBUILD /usr/bin/BLUEBUILD"]}'
COPY --from=ghcr.io/blue-build/cli:latest-installer /out/BLUEBUILD /usr/bin/BLUEBUILD
```

---------

Co-authored-by: Gerald Pinder <gmpinder@gmail.com>
This commit is contained in:
Hikari 2024-02-07 12:03:26 -06:00 committed by GitHub
parent 2492bb0eee
commit 0d8fd93917
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 29 additions and 9 deletions

3
.gitignore vendored
View file

@ -3,4 +3,5 @@
.vscode/
# Local testing for bluebuild recipe files
/config/
/config/*
Containerfile

View file

@ -121,12 +121,12 @@ fn has_cosign_file() -> bool {
}
#[must_use]
fn get_containerfile_list(module: &Module) -> Option<Vec<String>> {
if module.module_type.as_ref()? == "containerfile" {
fn get_module_type_list(module: &Module, typ: &str, list_key: &str) -> Option<Vec<String>> {
if module.module_type.as_ref()? == typ {
Some(
module
.config
.get("containerfiles")?
.get(list_key)?
.as_sequence()?
.iter()
.filter_map(|t| Some(t.as_str()?.to_owned()))
@ -137,6 +137,16 @@ fn get_containerfile_list(module: &Module) -> Option<Vec<String>> {
}
}
#[must_use]
fn get_containerfile_list(module: &Module) -> Option<Vec<String>> {
get_module_type_list(module, "containerfile", "containerfiles")
}
#[must_use]
fn get_containerfile_snippets(module: &Module) -> Option<Vec<String>> {
get_module_type_list(module, "containerfile", "snippets")
}
#[must_use]
fn print_containerfile(containerfile: &str) -> String {
debug!("print_containerfile({containerfile})");
@ -156,7 +166,7 @@ fn print_containerfile(containerfile: &str) -> String {
fn print_module_context(module: &Module) -> String {
serde_json::to_string(module).unwrap_or_else(|e| {
error!("Failed to parse module: {e}");
error!("Failed to parse module!!!!!: {e}");
process::exit(1);
})
}

View file

@ -209,6 +209,11 @@ pub struct ModuleExt {
}
impl ModuleExt {
/// # Parse a module file returning a [`ModuleExt`]
///
/// # Errors
/// Can return an `anyhow` Error if the file cannot be read or deserialized
/// into a [`ModuleExt`]
pub fn parse_module_from_file(file_name: &str) -> Result<ModuleExt> {
let file_path = PathBuf::from("config").join(file_name);
let file_path = if file_path.is_absolute() {
@ -246,6 +251,7 @@ pub struct Module {
}
impl Module {
#[must_use]
pub fn get_modules(modules: &[Self]) -> Vec<Self> {
modules
.iter()

View file

@ -34,8 +34,8 @@ pub fn serde_yaml_err(contents: &str) -> impl Fn(serde_yaml::Error) -> SerdeErro
contents.to_string(),
(
err.into(),
location.map_or(0, |l| l.line()).into(),
location.map_or(0, |l| l.column()).into(),
location.map_or(0, serde_yaml::Location::line).into(),
location.map_or(0, serde_yaml::Location::column).into(),
),
)
}

View file

@ -23,9 +23,7 @@ COPY cosign.pub /usr/share/ublue-os/cosign.pub
# Feel free to remove these lines if you want to speed up image builds and don't want any bling
COPY --from=ghcr.io/ublue-os/bling:latest /rpms /tmp/bling/rpms
COPY --from=ghcr.io/ublue-os/bling:latest /files /tmp/bling/files
COPY --from=docker.io/mikefarah/yq /usr/bin/yq /usr/bin/yq
COPY --from=gcr.io/projectsigstore/cosign /ko-app/cosign /usr/bin/cosign
COPY --from=ghcr.io/blue-build/cli:
@ -57,6 +55,11 @@ ARG BASE_IMAGE="{{ recipe.base_image }}"
{{ self::print_containerfile(c) }}
{%- endfor %}
{%- endif %}
{%- if let Some(snippets) = self::get_containerfile_snippets(module) %}
{%- for s in snippets %}
{{ s }}
{%- endfor %}
{%- endif %}
{%- else if type == "files" %}
{%- if let Some(files) = self::get_files_list(module) %}
{%- for (src, dest) in files %}