feat: Support versioned modules
This commit is contained in:
parent
74bd05643f
commit
2d150e3c93
7 changed files with 135 additions and 19 deletions
|
|
@ -6,7 +6,8 @@ base-image: quay.io/fedora/fedora-silverblue
|
|||
image-version: latest
|
||||
alt-tags:
|
||||
- arm64
|
||||
stages: []
|
||||
stages:
|
||||
- from-file: stages.yml
|
||||
modules:
|
||||
- from-file: flatpaks.yml
|
||||
|
||||
|
|
@ -33,8 +34,33 @@ modules:
|
|||
- type: test-module
|
||||
source: local
|
||||
|
||||
- type: test-nu-modules
|
||||
source: local
|
||||
test-prop:
|
||||
- this
|
||||
- is
|
||||
- a
|
||||
- test
|
||||
|
||||
- type: containerfile
|
||||
containerfiles:
|
||||
- labels
|
||||
snippets:
|
||||
- RUN echo "This is a snippet" && ostree container commit
|
||||
|
||||
- type: copy
|
||||
from: alpine-test
|
||||
src: /test.txt
|
||||
dest: /
|
||||
- type: copy
|
||||
from: ubuntu-test
|
||||
src: /test.txt
|
||||
dest: /
|
||||
- type: copy
|
||||
from: debian-test
|
||||
src: /test.txt
|
||||
dest: /
|
||||
- type: copy
|
||||
from: fedora-test
|
||||
src: /test.txt
|
||||
dest: /
|
||||
|
|
|
|||
|
|
@ -11,11 +11,15 @@ use serde_yaml::Value;
|
|||
|
||||
use crate::{base_recipe_path, AkmodsInfo, ModuleExt};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Builder, Default)]
|
||||
mod type_ver;
|
||||
|
||||
pub use type_ver::*;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Builder)]
|
||||
pub struct ModuleRequiredFields<'a> {
|
||||
#[builder(into)]
|
||||
#[serde(rename = "type")]
|
||||
pub module_type: Cow<'a, str>,
|
||||
pub module_type: ModuleTypeVersion<'a>,
|
||||
|
||||
#[builder(into)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
|
|
@ -38,7 +42,7 @@ const fn is_false(b: &bool) -> bool {
|
|||
impl<'a> ModuleRequiredFields<'a> {
|
||||
#[must_use]
|
||||
pub fn get_module_type_list(&'a self, typ: &str, list_key: &str) -> Option<Vec<String>> {
|
||||
if self.module_type == typ {
|
||||
if self.module_type.typ() == typ {
|
||||
Some(
|
||||
self.config
|
||||
.get(list_key)?
|
||||
|
|
@ -217,7 +221,7 @@ impl Module<'_> {
|
|||
required_fields: None,
|
||||
from_file: Some(file_name),
|
||||
} => {
|
||||
let file_name = PathBuf::from(file_name.as_ref());
|
||||
let file_name = PathBuf::from(&**file_name);
|
||||
if traversed_files.contains(&file_name) {
|
||||
bail!(
|
||||
"{} File {} has already been parsed:\n{traversed_files:?}",
|
||||
|
|
@ -260,14 +264,21 @@ impl Module<'_> {
|
|||
}
|
||||
|
||||
#[must_use]
|
||||
#[allow(clippy::missing_panics_doc)]
|
||||
pub fn example() -> Self {
|
||||
Self::builder()
|
||||
.required_fields(
|
||||
ModuleRequiredFields::builder()
|
||||
.module_type("module-name")
|
||||
.module_type("script")
|
||||
.config(IndexMap::from_iter([
|
||||
("module".to_string(), Value::String("config".to_string())),
|
||||
("goes".to_string(), Value::String("here".to_string())),
|
||||
(
|
||||
"snippets".to_string(),
|
||||
Value::Sequence(bon::vec!["echo 'Hello World!'"]),
|
||||
),
|
||||
(
|
||||
"scripts".to_string(),
|
||||
Value::Sequence(bon::vec!["install-program.sh"]),
|
||||
),
|
||||
]))
|
||||
.build(),
|
||||
)
|
||||
|
|
|
|||
78
recipe/src/module/type_ver.rs
Normal file
78
recipe/src/module/type_ver.rs
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ModuleTypeVersion<'scope> {
|
||||
typ: Cow<'scope, str>,
|
||||
version: Cow<'scope, str>,
|
||||
}
|
||||
|
||||
impl ModuleTypeVersion<'_> {
|
||||
#[must_use]
|
||||
pub fn typ(&self) -> &str {
|
||||
&self.typ
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn version(&self) -> &str {
|
||||
&self.version
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for ModuleTypeVersion<'_> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}@{}", &self.typ, &self.version)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'scope> From<&'scope str> for ModuleTypeVersion<'scope> {
|
||||
fn from(s: &'scope str) -> Self {
|
||||
if let Some((typ, version)) = s.split_once('@') {
|
||||
Self {
|
||||
typ: Cow::Borrowed(typ),
|
||||
version: Cow::Borrowed(version),
|
||||
}
|
||||
} else {
|
||||
Self {
|
||||
typ: Cow::Borrowed(s),
|
||||
version: Cow::Owned("latest".into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for ModuleTypeVersion<'_> {
|
||||
fn from(s: String) -> Self {
|
||||
if let Some((typ, version)) = s.split_once('@') {
|
||||
Self {
|
||||
typ: Cow::Owned(typ.to_owned()),
|
||||
version: Cow::Owned(version.to_owned()),
|
||||
}
|
||||
} else {
|
||||
Self {
|
||||
typ: Cow::Owned(s),
|
||||
version: Cow::Owned("latest".into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for ModuleTypeVersion<'_> {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
serializer.serialize_str(&self.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for ModuleTypeVersion<'_> {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let value: String = Deserialize::deserialize(deserializer)?;
|
||||
Ok(value.into())
|
||||
}
|
||||
}
|
||||
|
|
@ -72,7 +72,7 @@ impl ModuleExt<'_> {
|
|||
module
|
||||
.required_fields
|
||||
.as_ref()
|
||||
.is_some_and(|rf| rf.module_type == "akmods")
|
||||
.is_some_and(|rf| rf.module_type.typ() == "akmods")
|
||||
})
|
||||
.filter_map(|module| {
|
||||
Some(
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ impl Stage<'_> {
|
|||
required_fields: None,
|
||||
from_file: Some(file_name),
|
||||
} => {
|
||||
let file_name = PathBuf::from(file_name.as_ref());
|
||||
let file_name = PathBuf::from(&**file_name);
|
||||
if traversed_files.contains(&file_name) {
|
||||
bail!(
|
||||
"{} File {} has already been parsed:\n{traversed_files:?}",
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@
|
|||
ARG CACHEBUST="{{ build_id }}"
|
||||
{%- endif %}
|
||||
|
||||
{%- if module.module_type == "containerfile" %}
|
||||
{%- if module.module_type.typ() == "containerfile" %}
|
||||
{%- include "modules/containerfile/containerfile.j2" %}
|
||||
{%- else if module.module_type == "copy" %}
|
||||
{%- else if module.module_type.typ() == "copy" %}
|
||||
{%- include "modules/copy/copy.j2" %}
|
||||
{%- else %}
|
||||
RUN \
|
||||
|
|
@ -22,15 +22,15 @@ RUN \
|
|||
{%- else if module.is_local_source() %}
|
||||
--mount=type=bind,from=stage-modules,src=/modules,dst=/tmp/modules,rw \
|
||||
{%- else %}
|
||||
--mount=type=bind,from=ghcr.io/blue-build/modules/{{ module.module_type }}:latest,src=/modules,dst=/tmp/modules,rw \
|
||||
--mount=type=bind,from={{ blue_build_utils::constants::BLUE_BUILD_MODULE_IMAGE_REF }}/{{ module.module_type.typ() }}:{{ module.module_type.version() }},src=/modules,dst=/tmp/modules,rw \
|
||||
{%- endif %}
|
||||
{%- if module.module_type == "akmods" %}
|
||||
{%- if module.module_type.typ() == "akmods" %}
|
||||
--mount=type=bind,from=stage-akmods-{{ module.generate_akmods_info(os_version).stage_name }},src=/rpms,dst=/tmp/rpms,rw \
|
||||
{%- endif %}
|
||||
--mount=type=bind,from={{ build_scripts_image }},src=/scripts/,dst=/tmp/scripts/ \
|
||||
--mount=type=cache,dst=/var/cache/rpm-ostree,id=rpm-ostree-cache-{{ recipe.name }}-{{ recipe.image_version }},sharing=locked \
|
||||
--mount=type=cache,dst=/var/cache/libdnf5,id=dnf-cache-{{ recipe.name }}-{{ recipe.image_version }},sharing=locked \
|
||||
/tmp/scripts/run_module.sh '{{ module.module_type }}' '{{ module|json|safe }}'
|
||||
/tmp/scripts/run_module.sh '{{ module.module_type.typ() }}' '{{ module|json|safe }}'
|
||||
{%- endif %}
|
||||
{%- endif %}
|
||||
{%- endfor %}
|
||||
|
|
@ -45,9 +45,9 @@ RUN \
|
|||
ARG CACHEBUST="{{ build_id }}"
|
||||
{%- endif %}
|
||||
|
||||
{%- if module.module_type == "containerfile" %}
|
||||
{%- if module.module_type.typ() == "containerfile" %}
|
||||
{%- include "modules/containerfile/containerfile.j2" %}
|
||||
{%- else if module.module_type == "copy" %}
|
||||
{%- else if module.module_type.typ() == "copy" %}
|
||||
{%- include "modules/copy/copy.j2" %}
|
||||
{%- else %}
|
||||
RUN \
|
||||
|
|
@ -61,10 +61,10 @@ RUN \
|
|||
{%- else if module.is_local_source() %}
|
||||
--mount=type=bind,from=stage-modules,src=/modules,dst=/tmp/modules,rw \
|
||||
{%- else %}
|
||||
--mount=type=bind,from=ghcr.io/blue-build/modules/{{ module.module_type }}:latest,src=/modules,dst=/tmp/modules,rw \
|
||||
--mount=type=bind,from={{ blue_build_utils::constants::BLUE_BUILD_MODULE_IMAGE_REF }}/{{ module.module_type.typ() }}:{{ module.module_type.version() }},src=/modules,dst=/tmp/modules,rw \
|
||||
{%- endif %}
|
||||
--mount=type=bind,from={{ build_scripts_image }},src=/scripts/,dst=/tmp/scripts/ \
|
||||
/tmp/scripts/run_module.sh '{{ module.module_type }}' '{{ module|json|safe }}'
|
||||
/tmp/scripts/run_module.sh '{{ module.module_type.typ() }}' '{{ module|json|safe }}'
|
||||
{%- endif %}
|
||||
{%- endif %}
|
||||
{%- endfor %}
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ pub const XDG_RUNTIME_DIR: &str = "XDG_RUNTIME_DIR";
|
|||
// Misc
|
||||
pub const BUILD_SCRIPTS_IMAGE_REF: &str = "ghcr.io/blue-build/cli/build-scripts";
|
||||
pub const BLUE_BULID_IMAGE_REF: &str = "ghcr.io/blue-build/cli";
|
||||
pub const BLUE_BUILD_MODULE_IMAGE_REF: &str = "ghcr.io/blue-build/modules";
|
||||
pub const COSIGN_IMAGE: &str = "ghcr.io/sigstore/cosign/cosign:v2.4.1";
|
||||
pub const NUSHELL_IMAGE: &str = "ghcr.io/blue-build/nushell-image";
|
||||
pub const OCI_ARCHIVE: &str = "oci-archive";
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue