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
|
image-version: latest
|
||||||
alt-tags:
|
alt-tags:
|
||||||
- arm64
|
- arm64
|
||||||
stages: []
|
stages:
|
||||||
|
- from-file: stages.yml
|
||||||
modules:
|
modules:
|
||||||
- from-file: flatpaks.yml
|
- from-file: flatpaks.yml
|
||||||
|
|
||||||
|
|
@ -33,8 +34,33 @@ modules:
|
||||||
- type: test-module
|
- type: test-module
|
||||||
source: local
|
source: local
|
||||||
|
|
||||||
|
- type: test-nu-modules
|
||||||
|
source: local
|
||||||
|
test-prop:
|
||||||
|
- this
|
||||||
|
- is
|
||||||
|
- a
|
||||||
|
- test
|
||||||
|
|
||||||
- type: containerfile
|
- type: containerfile
|
||||||
containerfiles:
|
containerfiles:
|
||||||
- labels
|
- labels
|
||||||
snippets:
|
snippets:
|
||||||
- RUN echo "This is a snippet" && ostree container commit
|
- 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};
|
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> {
|
pub struct ModuleRequiredFields<'a> {
|
||||||
#[builder(into)]
|
#[builder(into)]
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
pub module_type: Cow<'a, str>,
|
pub module_type: ModuleTypeVersion<'a>,
|
||||||
|
|
||||||
#[builder(into)]
|
#[builder(into)]
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
|
@ -38,7 +42,7 @@ const fn is_false(b: &bool) -> bool {
|
||||||
impl<'a> ModuleRequiredFields<'a> {
|
impl<'a> ModuleRequiredFields<'a> {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn get_module_type_list(&'a self, typ: &str, list_key: &str) -> Option<Vec<String>> {
|
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(
|
Some(
|
||||||
self.config
|
self.config
|
||||||
.get(list_key)?
|
.get(list_key)?
|
||||||
|
|
@ -217,7 +221,7 @@ impl Module<'_> {
|
||||||
required_fields: None,
|
required_fields: None,
|
||||||
from_file: Some(file_name),
|
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) {
|
if traversed_files.contains(&file_name) {
|
||||||
bail!(
|
bail!(
|
||||||
"{} File {} has already been parsed:\n{traversed_files:?}",
|
"{} File {} has already been parsed:\n{traversed_files:?}",
|
||||||
|
|
@ -260,14 +264,21 @@ impl Module<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
#[allow(clippy::missing_panics_doc)]
|
||||||
pub fn example() -> Self {
|
pub fn example() -> Self {
|
||||||
Self::builder()
|
Self::builder()
|
||||||
.required_fields(
|
.required_fields(
|
||||||
ModuleRequiredFields::builder()
|
ModuleRequiredFields::builder()
|
||||||
.module_type("module-name")
|
.module_type("script")
|
||||||
.config(IndexMap::from_iter([
|
.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(),
|
.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
|
module
|
||||||
.required_fields
|
.required_fields
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.is_some_and(|rf| rf.module_type == "akmods")
|
.is_some_and(|rf| rf.module_type.typ() == "akmods")
|
||||||
})
|
})
|
||||||
.filter_map(|module| {
|
.filter_map(|module| {
|
||||||
Some(
|
Some(
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@ impl Stage<'_> {
|
||||||
required_fields: None,
|
required_fields: None,
|
||||||
from_file: Some(file_name),
|
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) {
|
if traversed_files.contains(&file_name) {
|
||||||
bail!(
|
bail!(
|
||||||
"{} File {} has already been parsed:\n{traversed_files:?}",
|
"{} File {} has already been parsed:\n{traversed_files:?}",
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,9 @@
|
||||||
ARG CACHEBUST="{{ build_id }}"
|
ARG CACHEBUST="{{ build_id }}"
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
{%- if module.module_type == "containerfile" %}
|
{%- if module.module_type.typ() == "containerfile" %}
|
||||||
{%- include "modules/containerfile/containerfile.j2" %}
|
{%- include "modules/containerfile/containerfile.j2" %}
|
||||||
{%- else if module.module_type == "copy" %}
|
{%- else if module.module_type.typ() == "copy" %}
|
||||||
{%- include "modules/copy/copy.j2" %}
|
{%- include "modules/copy/copy.j2" %}
|
||||||
{%- else %}
|
{%- else %}
|
||||||
RUN \
|
RUN \
|
||||||
|
|
@ -22,15 +22,15 @@ RUN \
|
||||||
{%- else if module.is_local_source() %}
|
{%- else if module.is_local_source() %}
|
||||||
--mount=type=bind,from=stage-modules,src=/modules,dst=/tmp/modules,rw \
|
--mount=type=bind,from=stage-modules,src=/modules,dst=/tmp/modules,rw \
|
||||||
{%- else %}
|
{%- 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 %}
|
{%- 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 \
|
--mount=type=bind,from=stage-akmods-{{ module.generate_akmods_info(os_version).stage_name }},src=/rpms,dst=/tmp/rpms,rw \
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
--mount=type=bind,from={{ build_scripts_image }},src=/scripts/,dst=/tmp/scripts/ \
|
--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/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 \
|
--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 %}
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
|
|
@ -45,9 +45,9 @@ RUN \
|
||||||
ARG CACHEBUST="{{ build_id }}"
|
ARG CACHEBUST="{{ build_id }}"
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
{%- if module.module_type == "containerfile" %}
|
{%- if module.module_type.typ() == "containerfile" %}
|
||||||
{%- include "modules/containerfile/containerfile.j2" %}
|
{%- include "modules/containerfile/containerfile.j2" %}
|
||||||
{%- else if module.module_type == "copy" %}
|
{%- else if module.module_type.typ() == "copy" %}
|
||||||
{%- include "modules/copy/copy.j2" %}
|
{%- include "modules/copy/copy.j2" %}
|
||||||
{%- else %}
|
{%- else %}
|
||||||
RUN \
|
RUN \
|
||||||
|
|
@ -61,10 +61,10 @@ RUN \
|
||||||
{%- else if module.is_local_source() %}
|
{%- else if module.is_local_source() %}
|
||||||
--mount=type=bind,from=stage-modules,src=/modules,dst=/tmp/modules,rw \
|
--mount=type=bind,from=stage-modules,src=/modules,dst=/tmp/modules,rw \
|
||||||
{%- else %}
|
{%- 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 %}
|
{%- endif %}
|
||||||
--mount=type=bind,from={{ build_scripts_image }},src=/scripts/,dst=/tmp/scripts/ \
|
--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 %}
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,7 @@ pub const XDG_RUNTIME_DIR: &str = "XDG_RUNTIME_DIR";
|
||||||
// Misc
|
// Misc
|
||||||
pub const BUILD_SCRIPTS_IMAGE_REF: &str = "ghcr.io/blue-build/cli/build-scripts";
|
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_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 COSIGN_IMAGE: &str = "ghcr.io/sigstore/cosign/cosign:v2.4.1";
|
||||||
pub const NUSHELL_IMAGE: &str = "ghcr.io/blue-build/nushell-image";
|
pub const NUSHELL_IMAGE: &str = "ghcr.io/blue-build/nushell-image";
|
||||||
pub const OCI_ARCHIVE: &str = "oci-archive";
|
pub const OCI_ARCHIVE: &str = "oci-archive";
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue