Files
serai/tests/reproducible-runtime/src/lib.rs
Luke Parker 36ac9c56a4 Remove workaround for lack of musl-dev now that musl-dev is provided in Rust Alpine images
Additionally, optimizes the build process a bit via leaving only the runtime
(and `busybox`) in the final image, and additionally building the runtime
without `std` (as we solely need the WASM blob from this process).
2025-12-04 11:58:38 -05:00

83 lines
2.1 KiB
Rust

#[test]
pub fn reproducibly_builds() {
use std::{collections::HashSet, path::PathBuf, process::Command};
use rand_core::{RngCore, OsRng};
const RUNS: usize = 3;
const TIMEOUT: u16 = 3 * 60 * 60; // 3 hours
let mut images = vec![];
for _ in 0 .. RUNS {
let mut image = [0; 32];
OsRng.fill_bytes(&mut image);
images.push(format!("runtime-{}", hex::encode(image)));
}
let path = Command::new("cargo")
.arg("locate-project")
.arg("--workspace")
.arg("--message-format")
.arg("plain")
.output()
.unwrap();
assert!(path.status.success());
let mut path = PathBuf::from(String::from_utf8(path.stdout).unwrap().trim());
assert_eq!(path.file_name().unwrap(), "Cargo.toml");
assert!(path.pop());
let mut commands = vec![];
for image in &images {
commands.push(
Command::new("docker")
.current_dir(&path)
.arg("build")
.arg("--progress")
.arg("plain")
.arg("--no-cache")
.arg("--file")
.arg("./orchestration/runtime/Dockerfile")
.arg("--tag")
.arg(image)
.arg(".")
.spawn()
.unwrap(),
);
}
let mut outputs = vec![];
for (image, mut command) in images.into_iter().zip(commands) {
assert!(command.wait().unwrap().success());
outputs.push(
Command::new("docker")
.arg("run")
.arg("--quiet")
.arg("--rm")
.arg(&image)
.arg("busybox")
.arg("sha256sum")
.arg("/serai.wasm")
.output(),
);
// Attempt to clean up the image
let _ = Command::new("docker").arg("rmi").arg(&image).output();
}
let mut expected = None;
for output in outputs {
let output = output.unwrap();
assert!(output.status.success());
if expected.is_none() {
expected = Some(output.stdout.clone());
}
assert_eq!(expected, Some(output.stdout));
}
let result = String::from_utf8(expected.unwrap()).unwrap();
let hash = result.split_whitespace().next().unwrap();
// Check this appears to be a 32-byte hash (encoded as hex)
assert_eq!(hash.len(), 64);
hex::decode(hash).unwrap();
println!("Hash: {hash}");
}