diff options
| author | Hermes Agent <hermes@localhost> | 2026-08-12 07:14:29 +0000 |
|---|---|---|
| committer | Hermes Agent <hermes@localhost> | 2026-08-12 07:14:29 +0000 |
| commit | e5338d823d5e9b2042bbba482c0f629762bbe163 (patch) | |
| tree | 73f516a6007e46f43a74c2936685b3c59151e334 | |
| parent | e09ee680abd286d25604c2242fa3e128fbdeed69 (diff) | |
Clean workspace after initramfs failure
| -rw-r--r-- | src/build.rs | 15 | ||||
| -rw-r--r-- | tests/build.rs | 27 |
2 files changed, 41 insertions, 1 deletions
diff --git a/src/build.rs b/src/build.rs index 305c059..e6ddf14 100644 --- a/src/build.rs +++ b/src/build.rs @@ -77,7 +77,14 @@ impl<I: PackageInstaller, B: InitramfsBuilder> BuildExecutor<I, B> { ) .apply(&rootfs)?; - let initrd = self.initramfs_builder.build(&InitramfsRequest::discover(&rootfs)?)?; + let initramfs_request = match InitramfsRequest::discover(&rootfs) { + Ok(request) => request, + Err(error) => return Self::fail_and_remove_workspace(workspace, error), + }; + let initrd = match self.initramfs_builder.build(&initramfs_request) { + Ok(initrd) => initrd, + Err(error) => return Self::fail_and_remove_workspace(workspace, error), + }; std::fs::create_dir_all(parent) .with_context(|| format!("create artifact directory {}", parent.display()))?; self.tar_writer.write(&rootfs, artifact)?; @@ -98,6 +105,12 @@ impl<I: PackageInstaller, B: InitramfsBuilder> BuildExecutor<I, B> { initrd: Some(initrd), }) } + + fn fail_and_remove_workspace<T>(workspace: &Path, error: anyhow::Error) -> Result<T> { + std::fs::remove_dir_all(workspace) + .with_context(|| format!("remove failed workspace {}", workspace.display()))?; + Err(error) + } } #[derive(Debug, Clone, PartialEq, Eq)] diff --git a/tests/build.rs b/tests/build.rs index dc9443c..987811a 100644 --- a/tests/build.rs +++ b/tests/build.rs @@ -31,6 +31,14 @@ impl PackageInstaller for FailingInstaller { } } +struct FailingInitramfsBuilder; + +impl InitramfsBuilder for FailingInitramfsBuilder { + fn build(&mut self, _request: &InitramfsRequest) -> anyhow::Result<InitramfsResult> { + anyhow::bail!("simulated initramfs build failure") + } +} + #[derive(Default)] struct FixtureInitramfsBuilder; @@ -181,3 +189,22 @@ fn removes_the_new_workspace_when_package_installation_fails() { assert!(!workspace.exists(), "failed build must not leave a workspace"); assert!(!artifact.exists()); } + +#[test] +fn removes_the_new_workspace_when_initramfs_build_fails() { + let fixture = tempdir().expect("fixture directory"); + let spec = ImageSpec::load(std::path::Path::new("profiles/alt-controller.toml")) + .expect("load controller spec"); + let plan = BuildPlan::compile(spec).expect("compile build plan"); + let mut executor = BuildExecutor::new(FixtureInstaller::default(), FailingInitramfsBuilder); + let workspace = fixture.path().join("work"); + let artifact = fixture.path().join("image.tar"); + + let error = executor + .execute(&plan, &workspace, "profiles/apt.conf", &artifact) + .expect_err("failed initramfs build must fail the build"); + + assert!(error.to_string().contains("simulated initramfs build failure")); + assert!(!workspace.exists(), "failed build must not leave a workspace"); + assert!(!artifact.exists()); +} |