From 21ac6ba754296000823869e3f025fbe6225e256f Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Wed, 12 Aug 2026 08:26:30 +0000 Subject: Clean partial outputs after manifest write failure --- tests/build.rs | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'tests') diff --git a/tests/build.rs b/tests/build.rs index c9cc59f..c31f0c2 100644 --- a/tests/build.rs +++ b/tests/build.rs @@ -87,6 +87,25 @@ impl InitramfsBuilder for MutatingInitrdBuilder { } } +struct ManifestFailingInitramfsBuilder { + manifest: std::path::PathBuf, +} + +impl InitramfsBuilder for ManifestFailingInitramfsBuilder { + fn build(&mut self, request: &InitramfsRequest) -> anyhow::Result { + fs::write( + request + .rootfs() + .join(format!("boot/initrd-{}.img", request.kernel().as_str())), + "initrd", + )?; + let parent = self.manifest.parent().expect("manifest parent"); + fs::create_dir_all(parent)?; + fs::create_dir(&self.manifest)?; + InitramfsResult::from_rootfs(request.rootfs(), request.kernel()) + } +} + #[derive(Default)] struct FixtureInitramfsBuilder; @@ -404,3 +423,38 @@ fn removes_the_new_workspace_and_artifact_when_manifest_collection_fails() { "failed manifest collection must not leave a companion manifest" ); } + +#[test] +fn removes_the_partial_artifact_when_manifest_writing_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 workspace = fixture.path().join("work"); + let artifact = fixture.path().join("out/image.tar"); + let manifest = ArtifactManifest::path_beside(&artifact).expect("manifest path"); + let mut executor = BuildExecutor::new( + FixtureInstaller::default(), + ManifestFailingInitramfsBuilder { + manifest: manifest.clone(), + }, + ); + + let error = executor + .execute(&plan, &workspace, "profiles/apt.conf", &artifact) + .expect_err("manifest write failure must fail the build"); + + assert!(error.to_string().contains("create artifact manifest")); + assert!( + !workspace.exists(), + "failed build must not leave a workspace" + ); + assert!( + !artifact.exists(), + "failed build must not leave an artifact" + ); + assert!( + !manifest.exists(), + "failed build must remove a manifest path created during execution" + ); +} -- cgit v1.2.3