summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/build.rs42
-rw-r--r--tests/build.rs45
2 files changed, 69 insertions, 18 deletions
diff --git a/src/build.rs b/src/build.rs
index 7fd3989..8b6ebb0 100644
--- a/src/build.rs
+++ b/src/build.rs
@@ -109,25 +109,31 @@ impl<I: PackageInstaller, B: InitramfsBuilder> BuildExecutor<I, B> {
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)?;
- let manifest = ArtifactManifest::collect(
- &rootfs,
- Vec::new(),
- Some(InitrdRecord::new(
- initrd.initrd_path().display().to_string(),
- initrd.sha256(),
- )),
- artifact,
- )?;
- let manifest_path = manifest.write_beside(artifact)?;
+ let result = (|| {
+ std::fs::create_dir_all(parent)
+ .with_context(|| format!("create artifact directory {}", parent.display()))?;
+ self.tar_writer.write(&rootfs, artifact)?;
+ let manifest = ArtifactManifest::collect(
+ &rootfs,
+ Vec::new(),
+ Some(InitrdRecord::new(
+ initrd.initrd_path().display().to_string(),
+ initrd.sha256(),
+ )),
+ artifact,
+ )?;
+ let manifest_path = manifest.write_beside(artifact)?;
- Ok(BuildResult {
- artifact: artifact.to_path_buf(),
- manifest: manifest_path,
- initrd: Some(initrd),
- })
+ Ok(BuildResult {
+ artifact: artifact.to_path_buf(),
+ manifest: manifest_path,
+ initrd: Some(initrd),
+ })
+ })();
+ match result {
+ Ok(result) => Ok(result),
+ Err(error) => Self::fail_and_remove_workspace(workspace, error),
+ }
}
fn fail_and_remove_workspace<T>(workspace: &Path, error: anyhow::Error) -> Result<T> {
diff --git a/tests/build.rs b/tests/build.rs
index 7d67b29..2fcd1bf 100644
--- a/tests/build.rs
+++ b/tests/build.rs
@@ -59,6 +59,20 @@ impl InitramfsBuilder for FailingInitramfsBuilder {
}
}
+struct ArchiveFailingInstaller;
+
+impl PackageInstaller for ArchiveFailingInstaller {
+ fn install(&self, request: &PackageRequest) -> anyhow::Result<()> {
+ let rootfs = request.workdir().join("chroot");
+ fs::create_dir_all(rootfs.join("boot"))?;
+ fs::write(rootfs.join("boot/vmlinuz-6.12.0-rt1"), "kernel")?;
+ std::os::unix::net::UnixListener::bind(rootfs.join("unsupported.socket"))
+ .expect("create unsupported socket fixture")
+ .set_nonblocking(true)?;
+ Ok(())
+ }
+}
+
#[derive(Default)]
struct FixtureInitramfsBuilder;
@@ -310,3 +324,34 @@ fn removes_the_new_workspace_when_initramfs_build_fails() {
);
assert!(!artifact.exists());
}
+
+#[test]
+fn removes_the_new_workspace_and_partial_artifact_when_packaging_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(ArchiveFailingInstaller, FixtureInitramfsBuilder);
+ let workspace = fixture.path().join("work");
+ let artifact = fixture.path().join("out/image.tar");
+
+ let error = executor
+ .execute(&plan, &workspace, "profiles/apt.conf", &artifact)
+ .expect_err("unsupported rootfs entry must fail packaging");
+
+ assert!(error.to_string().contains("unsupported rootfs entry type"));
+ assert!(
+ !workspace.exists(),
+ "failed build must not leave a workspace"
+ );
+ assert!(
+ !artifact.exists(),
+ "failed packaging must not leave an artifact"
+ );
+ assert!(
+ !ArtifactManifest::path_beside(&artifact)
+ .expect("manifest path")
+ .exists(),
+ "failed packaging must not leave a companion manifest"
+ );
+}