deb: make tests parallel
This commit is contained in:
+58
-26
@@ -3,9 +3,10 @@ mod ephemeral;
|
||||
mod local;
|
||||
mod sbuild;
|
||||
|
||||
use crate::context;
|
||||
use crate::context::{self, Context};
|
||||
use std::error::Error;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Build mode for the binary build
|
||||
#[derive(PartialEq)]
|
||||
@@ -17,6 +18,7 @@ pub enum BuildMode {
|
||||
}
|
||||
|
||||
/// Build package in 'cwd' to a .deb
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn build_binary_package(
|
||||
arch: Option<&str>,
|
||||
series: Option<&str>,
|
||||
@@ -25,6 +27,7 @@ pub async fn build_binary_package(
|
||||
mode: Option<BuildMode>,
|
||||
ppa: Option<&[&str]>,
|
||||
inject_packages: Option<&[&str]>,
|
||||
ctx: Option<Arc<Context>>,
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
let cwd = cwd.unwrap_or_else(|| Path::new("."));
|
||||
|
||||
@@ -57,19 +60,35 @@ pub async fn build_binary_package(
|
||||
None
|
||||
};
|
||||
|
||||
// Use provided context or get current
|
||||
let base_ctx = ctx.unwrap_or_else(context::current);
|
||||
|
||||
let mut guard = if mode == BuildMode::Local {
|
||||
Some(ephemeral::EphemeralContextGuard::new(series, chroot_arch).await?)
|
||||
Some(
|
||||
ephemeral::EphemeralContextGuard::new_with_context(
|
||||
series,
|
||||
chroot_arch,
|
||||
base_ctx.clone(),
|
||||
)
|
||||
.await?,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Get the build context - either the ephemeral context or the base context
|
||||
let build_ctx = if mode == BuildMode::Local {
|
||||
context::current()
|
||||
} else {
|
||||
base_ctx.clone()
|
||||
};
|
||||
|
||||
// Prepare build directory
|
||||
let ctx = context::current();
|
||||
let build_root = ctx.create_temp_dir()?;
|
||||
let build_root = build_ctx.create_temp_dir()?;
|
||||
|
||||
// Ensure availability of all needed files for the build
|
||||
let parent_dir = cwd.parent().ok_or("Cannot find parent directory")?;
|
||||
ctx.ensure_available(parent_dir, &build_root)?;
|
||||
build_ctx.ensure_available(parent_dir, &build_root)?;
|
||||
let parent_dir_name = parent_dir
|
||||
.file_name()
|
||||
.ok_or("Cannot find parent directory name")?;
|
||||
@@ -87,19 +106,28 @@ pub async fn build_binary_package(
|
||||
cross,
|
||||
ppa,
|
||||
inject_packages,
|
||||
build_ctx.clone(),
|
||||
)
|
||||
.await?
|
||||
}
|
||||
BuildMode::Sbuild => sbuild::build(&package, &version, arch, series, &build_root, cross)?,
|
||||
BuildMode::Sbuild => sbuild::build(
|
||||
&package,
|
||||
&version,
|
||||
arch,
|
||||
series,
|
||||
&build_root,
|
||||
cross,
|
||||
build_ctx.clone(),
|
||||
)?,
|
||||
};
|
||||
|
||||
// Retrieve produced .deb files
|
||||
let remote_files = ctx.list_files(Path::new(&build_root))?;
|
||||
let remote_files = build_ctx.list_files(Path::new(&build_root))?;
|
||||
for remote_file in remote_files {
|
||||
if remote_file.extension().is_some_and(|ext| ext == "deb") {
|
||||
let file_name = remote_file.file_name().ok_or("Invalid remote filename")?;
|
||||
let local_dest = parent_dir.join(file_name);
|
||||
ctx.retrieve_path(&remote_file, &local_dest)?;
|
||||
build_ctx.retrieve_path(&remote_file, &local_dest)?;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,14 +223,14 @@ fn find_dsc_file(
|
||||
build_root: &str,
|
||||
package: &str,
|
||||
version: &str,
|
||||
ctx: &Arc<Context>,
|
||||
) -> Result<PathBuf, Box<dyn Error>> {
|
||||
// Strip epoch from version (e.g., "1:2.3.4-5" -> "2.3.4-5")
|
||||
let version_without_epoch = version.split_once(':').map(|(_, v)| v).unwrap_or(version);
|
||||
let dsc_name = format!("{}_{}.dsc", package, version_without_epoch);
|
||||
let dsc_path = PathBuf::from(build_root).join(&dsc_name);
|
||||
|
||||
// Check if the .dsc file exists in current context
|
||||
let ctx = context::current();
|
||||
// Check if the .dsc file exists in context
|
||||
if !ctx.exists(&dsc_path)? {
|
||||
return Err(format!("Could not find .dsc file at {}", dsc_path.display()).into());
|
||||
}
|
||||
@@ -211,7 +239,9 @@ fn find_dsc_file(
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use serial_test::serial;
|
||||
use super::*;
|
||||
use std::sync::Arc;
|
||||
|
||||
async fn test_build_end_to_end(
|
||||
package: &str,
|
||||
series: &str,
|
||||
@@ -241,17 +271,28 @@ mod tests {
|
||||
.expect("Cannot pull package");
|
||||
log::info!("Successfully pulled package {}", package);
|
||||
|
||||
// Create a fresh local context for this test
|
||||
let ctx = Arc::new(Context::new(crate::context::ContextConfig::Local));
|
||||
|
||||
// Change directory to the package directory
|
||||
let ctx = crate::context::current();
|
||||
let cwd =
|
||||
crate::deb::find_package_directory(cwd, package, &package_info.stanza.version, &ctx)
|
||||
.expect("Cannot find package directory");
|
||||
log::debug!("Package directory: {}", cwd.display());
|
||||
|
||||
log::info!("Starting binary package build...");
|
||||
crate::deb::build_binary_package(arch, Some(series), Some(&cwd), cross, None, None, None)
|
||||
.await
|
||||
.expect("Cannot build binary package (deb)");
|
||||
crate::deb::build_binary_package(
|
||||
arch,
|
||||
Some(series),
|
||||
Some(&cwd),
|
||||
cross,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
Some(ctx),
|
||||
)
|
||||
.await
|
||||
.expect("Cannot build binary package (deb)");
|
||||
log::info!("Successfully built binary package");
|
||||
|
||||
// Check that the .deb files are present
|
||||
@@ -274,16 +315,10 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
// Tests below will be marked 'serial'
|
||||
// As builds are using ephemeral contexts, tests running on the same
|
||||
// process could use the ephemeral context of another thread and
|
||||
// interfere with each other.
|
||||
// FIXME: This is not ideal. In the future, we might want to
|
||||
// either explicitely pass context (instead of shared state) or
|
||||
// fork for building?
|
||||
// Tests no longer need to be 'serial' since each test uses its own
|
||||
// explicit context instead of shared global state.
|
||||
#[tokio::test]
|
||||
#[test_log::test]
|
||||
#[serial]
|
||||
async fn test_deb_hello_ubuntu_end_to_end() {
|
||||
test_build_end_to_end("hello", "noble", None, None, false).await;
|
||||
}
|
||||
@@ -292,7 +327,6 @@ mod tests {
|
||||
#[tokio::test]
|
||||
#[test_log::test]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[serial]
|
||||
async fn test_deb_hello_ubuntu_cross_end_to_end() {
|
||||
test_build_end_to_end("hello", "noble", None, Some("riscv64"), true).await;
|
||||
}
|
||||
@@ -302,7 +336,6 @@ mod tests {
|
||||
/// for example.
|
||||
#[tokio::test]
|
||||
#[test_log::test]
|
||||
#[serial]
|
||||
async fn test_deb_hello_debian_sid_end_to_end() {
|
||||
test_build_end_to_end("hello", "sid", None, None, false).await;
|
||||
}
|
||||
@@ -329,7 +362,6 @@ mod tests {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[tokio::test]
|
||||
#[test_log::test]
|
||||
#[serial]
|
||||
async fn test_deb_gcc_debian_end_to_end() {
|
||||
test_build_end_to_end("gcc-15", "sid", None, None, false).await;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user