Skip to content

Commit 2f0964f

Browse files
committed
feat: add x_exec.container, build_deps, and checksum_bsum metadata
1 parent 76bdd66 commit 2f0964f

9 files changed

Lines changed: 153 additions & 18 deletions

File tree

sbuild-linter/src/build_config/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ pub struct BuildConfig {
2222
pub app_id: Option<String>,
2323
pub build_util: Option<Vec<String>>,
2424
pub build_asset: Option<Vec<BuildAsset>>,
25+
pub build_deps: Option<Vec<String>>,
2526
pub category: Vec<String>,
2627
pub description: Option<Description>,
2728
pub homepage: Option<Vec<String>>,
@@ -112,6 +113,14 @@ impl BuildConfig {
112113
}
113114
}
114115

116+
write_field_comments(writer, "build_deps")?;
117+
if let Some(ref build_deps) = self.build_deps {
118+
writeln!(writer, "{}build_deps:", indent_str)?;
119+
for dep in build_deps {
120+
writeln!(writer, "{} - \"{}\"", indent_str, dep)?;
121+
}
122+
}
123+
115124
write_field_comments(writer, "ghcr_pkg")?;
116125
if let Some(ref ghcr_pkg) = self.ghcr_pkg {
117126
writeln!(writer, "{}ghcr_pkg: \"{}\"", indent_str, ghcr_pkg)?;

sbuild-linter/src/validator.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,10 +245,17 @@ impl ValidationContext {
245245
let mut valid = true;
246246
let mut x_exec = XExec::default();
247247

248+
// container (optional)
249+
if let Some(container_node) = Self::mapping_get(node, "container") {
250+
if let Some(s) = self.expect_non_empty_string(container_node, "x_exec.container") {
251+
x_exec.container = Some(s);
252+
}
253+
}
254+
248255
// shell (required)
249256
if let Some(shell_node) = Self::mapping_get(node, "shell") {
250257
if let Some(s) = self.expect_non_empty_string(shell_node, "x_exec.shell") {
251-
if which::which_global(&s).is_ok() {
258+
if x_exec.container.is_some() || which::which_global(&s).is_ok() {
252259
x_exec.shell = s;
253260
} else {
254261
self.error(
@@ -538,7 +545,7 @@ impl ValidationContext {
538545

539546
if let Some(url_node) = Self::mapping_get(asset_node, "url") {
540547
if let Some(u) = self.expect_non_empty_string(url_node, "build_asset.url") {
541-
if !is_valid_url(&u) {
548+
if !u.contains("${") && !is_valid_url(&u) {
542549
self.error(
543550
"build_asset.url",
544551
&format!("'{}' is not a valid URL.", u),
@@ -698,6 +705,9 @@ impl ValidationContext {
698705
"build_asset" => {
699706
config.build_asset = self.validate_build_asset(val_node);
700707
}
708+
"build_deps" => {
709+
config.build_deps = self.expect_string_array(val_node, "build_deps", false);
710+
}
701711
"category" => {
702712
if let Some(cats) = self.expect_string_array(val_node, "category", false) {
703713
for c in &cats {

sbuild-linter/src/xexec.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ pub struct XExec {
1212
pub depends: Option<Vec<String>>,
1313
pub entrypoint: Option<String>,
1414
pub pkgver: Option<String>,
15+
pub container: Option<String>,
1516
pub shell: String,
1617
pub run: String,
1718
}
@@ -54,6 +55,10 @@ impl XExec {
5455
writeln!(writer, "{}entrypoint: \"{}\"", indent_str, entrypoint)?;
5556
}
5657

58+
if let Some(ref container) = self.container {
59+
writeln!(writer, "{}container: \"{}\"", indent_str, container)?;
60+
}
61+
5762
writeln!(writer, "{}shell: \"{}\"", indent_str, self.shell)?;
5863

5964
if let Some(ref pkgver) = self.pkgver {

sbuild-meta/src/metadata.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,9 @@ pub struct PackageMetadata {
125125
#[serde(skip_serializing_if = "Option::is_none")]
126126
pub shasum: Option<String>,
127127

128+
#[serde(skip_serializing_if = "Option::is_none")]
129+
pub checksum_bsum: Option<String>,
130+
128131
// Build info
129132
#[serde(skip_serializing_if = "Option::is_none")]
130133
pub build_id: Option<String>,
@@ -317,6 +320,11 @@ impl PackageMetadata {
317320
self.shasum = Some(shasum.to_string());
318321
}
319322
}
323+
if self.checksum_bsum.is_none() {
324+
if let Some(cb) = manifest.get_annotation("dev.pkgforge.soar.checksum_bsum") {
325+
self.checksum_bsum = Some(cb.to_string());
326+
}
327+
}
320328

321329
// Generate blob reference and download URLs
322330
let filenames = manifest.filenames();
@@ -408,6 +416,9 @@ impl PackageMetadata {
408416
if let Some(v) = get_str("shasum") {
409417
self.shasum = Some(v);
410418
}
419+
if let Some(v) = get_str("checksum_bsum") {
420+
self.checksum_bsum = Some(v);
421+
}
411422
if let Some(v) = get_str("icon") {
412423
self.icon = Some(v);
413424
}

sbuild/src/builder.rs

Lines changed: 74 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ use crate::{
2828
},
2929
types::{OutputStream, PackageType, SoarEnv},
3030
utils::{
31-
calc_magic_bytes, download, is_static_elf, pack_appimage, self_extract_appimage, temp_file,
31+
calc_magic_bytes, download, expand_env_vars, is_static_elf, pack_appimage,
32+
self_extract_appimage, temp_file,
3233
},
3334
};
3435

@@ -116,6 +117,14 @@ impl BuildContext {
116117
let existing_envs: Vec<(String, Option<String>)> =
117118
inherit_keys.iter().map(|key| get_env_var(key)).collect();
118119

120+
let arch = ARCH.to_string();
121+
let arch_alt = match ARCH {
122+
"x86_64" => "amd64",
123+
"aarch64" => "arm64",
124+
_ => ARCH,
125+
}
126+
.to_string();
127+
119128
let paths = format!("{}:{}", soar_bin, paths);
120129
let mut vars: Vec<(String, String)> = [
121130
("pkg", self.pkg.clone()),
@@ -128,6 +137,8 @@ impl BuildContext {
128137
("pkg_ver", self.remote_pkgver.clone()),
129138
("pkgver", self.pkgver.clone()),
130139
("remote_pkgver", self.remote_pkgver.clone()),
140+
("arch", arch),
141+
("arch_alt", arch_alt),
131142
]
132143
.into_iter()
133144
.flat_map(|(key, value)| {
@@ -188,15 +199,23 @@ impl Builder {
188199
}
189200
}
190201

191-
pub async fn download_build_assets(&mut self, build_assets: &[BuildAsset]) {
202+
pub async fn download_build_assets(
203+
&mut self,
204+
build_assets: &[BuildAsset],
205+
context: &BuildContext,
206+
) {
207+
let env_vars = context.env_vars(&self.soar_env.bin_path);
192208
for asset in build_assets {
209+
let url = expand_env_vars(&asset.url, &env_vars);
210+
let out = expand_env_vars(&asset.out, &env_vars);
211+
193212
self.logger
194-
.info(format!("Downloading build asset from {}", asset.url));
213+
.info(format!("Downloading build asset from {}", url));
195214

196-
let out_path = format!("SBUILD_TEMP/{}", asset.out);
197-
if download(&asset.url, out_path).await.is_err() {
215+
let out_path = out.to_string();
216+
if download(&url, out_path).await.is_err() {
198217
self.logger
199-
.error(format!("Failed to download build asset from {}", asset.url));
218+
.error(format!("Failed to download build asset from {}", url));
200219
std::process::exit(1);
201220
};
202221
}
@@ -270,7 +289,9 @@ impl Builder {
270289

271290
fs::create_dir_all(&context.tmpdir).unwrap();
272291

273-
if self.external {
292+
let is_container = build_config.x_exec.container.is_some();
293+
294+
if self.external && !is_container {
274295
if let Some(build_utils) = build_config.build_util.clone() {
275296
let mut child = Command::new("soar")
276297
.env_clear()
@@ -291,17 +312,54 @@ impl Builder {
291312
}
292313

293314
if let Some(ref build_assets) = build_config.build_asset {
294-
self.download_build_assets(build_assets).await;
315+
self.download_build_assets(build_assets, context).await;
295316
}
296317

297-
let mut child = Command::new(&exec_file)
298-
.env_clear()
299-
.envs(context.env_vars(&self.soar_env.bin_path))
300-
.stdout(Stdio::piped())
301-
.stderr(Stdio::piped())
302-
.stdin(Stdio::null())
303-
.spawn()
304-
.unwrap();
318+
let mut child = if let Some(ref container) = build_config.x_exec.container {
319+
let image = if container.contains(':') {
320+
container.clone()
321+
} else {
322+
format!("{}:{}", container, ARCH)
323+
};
324+
325+
let env_vars = context.env_vars(&self.soar_env.bin_path);
326+
let mut cmd = Command::new("docker");
327+
cmd.args(["run", "--rm", "--privileged", "--net=host", "--pull=always"]);
328+
329+
for (key, value) in &env_vars {
330+
if key == "PATH" {
331+
continue;
332+
}
333+
let val = match key.as_str() {
334+
"sbuild_outdir" | "SBUILD_OUTDIR" => "/sbuild".to_string(),
335+
"sbuild_tmpdir" | "SBUILD_TMPDIR" => "/sbuild/SBUILD_TEMP".to_string(),
336+
_ => value.clone(),
337+
};
338+
cmd.arg("-e").arg(format!("{}={}", key, val));
339+
}
340+
341+
cmd.args(["-v", &format!("{}:/sbuild:rw", context.outdir.display())]);
342+
cmd.args(["-v", &format!("{}:/exec_script:ro", exec_file)]);
343+
cmd.args(["-w", "/sbuild"]);
344+
cmd.arg(&image);
345+
cmd.arg("/exec_script");
346+
347+
cmd.env_clear()
348+
.stdout(Stdio::piped())
349+
.stderr(Stdio::piped())
350+
.stdin(Stdio::null())
351+
.spawn()
352+
.unwrap()
353+
} else {
354+
Command::new(&exec_file)
355+
.env_clear()
356+
.envs(context.env_vars(&self.soar_env.bin_path))
357+
.stdout(Stdio::piped())
358+
.stderr(Stdio::piped())
359+
.stdin(Stdio::null())
360+
.spawn()
361+
.unwrap()
362+
};
305363

306364
if let Err(err) = self.prepare_resources(&build_config, context).await {
307365
self.logger.warn(&err);

sbuild/src/commands/build.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,15 @@ async fn post_build_processing(
577577
(None, None, None)
578578
};
579579

580+
let checksum_bsum = {
581+
let checksum_path = pkg_dir.join("CHECKSUM");
582+
if checksum_path.exists() {
583+
checksum::b3sum(&checksum_path).ok()
584+
} else {
585+
None
586+
}
587+
};
588+
580589
let ghcr_total_size: u64 = files_to_push
581590
.iter()
582591
.filter_map(|f| fs::metadata(f).ok().map(|m| m.len()))
@@ -591,6 +600,7 @@ async fn post_build_processing(
591600
&tag,
592601
bsum.as_deref(),
593602
shasum.as_deref(),
603+
checksum_bsum.as_deref(),
594604
binary_size,
595605
Some(ghcr_total_size),
596606
) {
@@ -627,6 +637,7 @@ async fn post_build_processing(
627637
build_script: recipe_url.map(|s| s.to_string()),
628638
bsum,
629639
shasum,
640+
checksum_bsum,
630641
};
631642

632643
if cli.dry_run {
@@ -799,6 +810,15 @@ async fn post_build_processing(
799810
(None, None, None)
800811
};
801812

813+
let checksum_bsum = {
814+
let checksum_path = outdir.join("CHECKSUM");
815+
if checksum_path.exists() {
816+
checksum::b3sum(&checksum_path).ok()
817+
} else {
818+
None
819+
}
820+
};
821+
802822
let ghcr_total_size: u64 = files_to_push
803823
.iter()
804824
.filter_map(|f| fs::metadata(f).ok().map(|m| m.len()))
@@ -813,6 +833,7 @@ async fn post_build_processing(
813833
&tag,
814834
bsum.as_deref(),
815835
shasum.as_deref(),
836+
checksum_bsum.as_deref(),
816837
binary_size,
817838
Some(ghcr_total_size),
818839
) {
@@ -849,6 +870,7 @@ async fn post_build_processing(
849870
build_script: recipe_url.map(|s| s.to_string()),
850871
bsum,
851872
shasum,
873+
checksum_bsum,
852874
};
853875

854876
if cli.dry_run {

sbuild/src/ghcr.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ pub struct PackageAnnotations {
4242
pub bsum: Option<String>,
4343
/// SHA256 checksum of the main binary
4444
pub shasum: Option<String>,
45+
/// BLAKE3 checksum of the CHECKSUM file
46+
pub checksum_bsum: Option<String>,
4547
}
4648

4749
/// GHCR client for pushing packages
@@ -212,6 +214,12 @@ impl GhcrClient {
212214
if let Some(ref shasum) = meta.shasum {
213215
annotations.insert("dev.pkgforge.soar.shasum".to_string(), shasum.clone());
214216
}
217+
if let Some(ref checksum_bsum) = meta.checksum_bsum {
218+
annotations.insert(
219+
"dev.pkgforge.soar.checksum_bsum".to_string(),
220+
checksum_bsum.clone(),
221+
);
222+
}
215223

216224
annotations
217225
}

sbuild/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ pub fn update_json_metadata(
5050
tag: &str,
5151
bsum: Option<&str>,
5252
shasum: Option<&str>,
53+
checksum_bsum: Option<&str>,
5354
binary_size: Option<u64>,
5455
ghcr_total_size: Option<u64>,
5556
) -> Result<(), String> {
@@ -86,6 +87,9 @@ pub fn update_json_metadata(
8687
if let Some(s) = shasum {
8788
obj.insert("shasum".to_string(), serde_json::json!(s));
8889
}
90+
if let Some(cb) = checksum_bsum {
91+
obj.insert("checksum_bsum".to_string(), serde_json::json!(cb));
92+
}
8993

9094
if let Some(s) = binary_size {
9195
obj.insert("size".to_string(), serde_json::json!(format_size(s)));

sbuild/src/utils.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,3 +185,11 @@ pub fn is_static_elf<P: AsRef<Path>>(file_path: P) -> bool {
185185
let elf = Elf::parse(&mmap).unwrap();
186186
elf.interpreter.is_none()
187187
}
188+
189+
pub fn expand_env_vars(input: &str, vars: &[(String, String)]) -> String {
190+
let mut result = input.to_string();
191+
for (key, value) in vars {
192+
result = result.replace(&format!("${{{}}}", key), value);
193+
}
194+
result
195+
}

0 commit comments

Comments
 (0)