diff options
author | Lars Wirzenius <liw@noreply.codeberg.org> | 2023-11-03 17:10:41 +0000 |
---|---|---|
committer | Lars Wirzenius <liw@noreply.codeberg.org> | 2023-11-03 17:10:41 +0000 |
commit | dc9d960985afb21f86656639ecee3138ca50f7fc (patch) | |
tree | 026d79f0c56b310253e1e2c7d81082502b2f00f4 | |
parent | abc6c7aa30ce179c5b5d43598bfa612491a89faa (diff) | |
parent | b6e91f0579a32ab466e2f5126d15775022918137 (diff) | |
download | ambient-run-dc9d960985afb21f86656639ecee3138ca50f7fc.tar.gz |
Merge pull request 'feat: ambient-run extracts run exit code and checks it' (#28) from exit-code into main
Reviewed-on: https://codeberg.org/ambient/ambient-run/pulls/28
-rw-r--r-- | ambient-run.md | 8 | ||||
-rw-r--r-- | src/bin/ambient-run.rs | 9 | ||||
-rw-r--r-- | src/error.rs | 3 | ||||
-rw-r--r-- | src/qemu.rs | 51 |
4 files changed, 61 insertions, 10 deletions
diff --git a/ambient-run.md b/ambient-run.md index 7be3be6..b3cee4a 100644 --- a/ambient-run.md +++ b/ambient-run.md @@ -275,8 +275,9 @@ given an installed ambient-run given file no-artifact-project.yaml given file foo/README.md from foo-project.yaml given image file image.qcow2 specified for test suite -when I run ambient-run build no-artifact-project.yaml --log foo.log +when I try to run ambient-run build no-artifact-project.yaml --log foo.log then file foo.log contains "EXIT CODE: 2" +then exit code is 1 ~~~ @@ -303,8 +304,9 @@ given an installed ambient-run given file small-artifact-project.yaml given file foo/README.md from foo-project.yaml given image file image.qcow2 specified for test suite -when I run ambient-run build small-artifact-project.yaml --log foo.log +when I try to run ambient-run build small-artifact-project.yaml --log foo.log then file foo.log contains "EXIT CODE: 2" +then exit code is 1 ~~~ @@ -461,7 +463,7 @@ then file extracted/README.md contains "my project!" ~~~ ## Errors during build -### Bad per-user configuration +### Bad per-user configuration _Requirement:_ `ambient-run` fails if the per-user configuration is bad. diff --git a/src/bin/ambient-run.rs b/src/bin/ambient-run.rs index 6083286..602e4d6 100644 --- a/src/bin/ambient-run.rs +++ b/src/bin/ambient-run.rs @@ -224,7 +224,12 @@ impl BuildCommand { if let Some(log) = &self.log { qemu = qemu.with_log(log); } - qemu.run()?; - Ok(()) + let exit = qemu.run()?; + eprintln!("ambient-run build exit code {exit}"); + if exit == 0 { + Ok(()) + } else { + Err(AmbientRunError::RunFailed(exit)) + } } } diff --git a/src/error.rs b/src/error.rs index 0958d35..e55dcde 100644 --- a/src/error.rs +++ b/src/error.rs @@ -12,6 +12,9 @@ pub enum AmbientRunError { #[error(transparent)] Qemu(#[from] crate::qemu::QemuError), + #[error("run in VM failed with exit code {0}")] + RunFailed(i32), + #[error(transparent)] VDrive(#[from] crate::vdrive::VirtualDriveError), } diff --git a/src/qemu.rs b/src/qemu.rs index a3e344d..d1b0761 100644 --- a/src/qemu.rs +++ b/src/qemu.rs @@ -5,7 +5,7 @@ use crate::vdrive::{VirtualDrive, VirtualDriveBuilder, VirtualDriveError}; use std::{ fs::{copy, write, File}, path::{Path, PathBuf}, - process::{Command, Stdio}, + process::Command, }; const MAX_OUTPUT_SIZE: u64 = 1024 * 1024 * 1024; @@ -78,7 +78,7 @@ impl Qemu { } /// Run QEMU in the specified way. - pub fn run(&self) -> Result<(), QemuError> { + pub fn run(&self) -> Result<i32, QemuError> { eprintln!("qemu run"); let tmp = tempfile::tempdir().map_err(QemuError::TempDir)?; let empty = tempfile::tempdir().map_err(QemuError::TempDir)?; @@ -156,7 +156,6 @@ impl Qemu { .with_raw(cache_drive.filename(), false) .with_raw(deps_drive.filename(), true) .with_arg("-nodefaults"); - eprintln!("Args: {:#?}", args); eprintln!("spawn qemu"); let child = Command::new("kvm") @@ -180,7 +179,11 @@ impl Qemu { .extract_to(dirname) .map_err(|e| QemuError::ExtractCache(dirname.into(), e))?; } - Ok(()) + eprintln!("reading build log"); + let log = Self::build_log(&build_log)?; + eprintln!("log:\n{}", log); + let exit = Self::exit_code(&log)?; + Ok(exit) } else { let exit = output.status.code().unwrap_or(255); let out = String::from_utf8_lossy(&output.stdout).to_string(); @@ -191,7 +194,7 @@ impl Qemu { "kvm failed: exit={}\nstdout: {:?}\nstderr: {:?}\nVM console: {:?}", exit, out, err, log ); - Err(QemuError::Kvm(exit, err, log)) + Ok(exit) } } @@ -205,6 +208,38 @@ impl Qemu { Ok(filename.into()) } + fn build_log(filename: &Path) -> Result<String, QemuError> { + const BEGIN: &str = "====================== BEGIN ======================"; + const END: &str = "====================== END ======================"; + + let log = std::fs::read(filename).map_err(|e| QemuError::ReadLog(filename.into(), e))?; + let log = String::from_utf8_lossy(&log); + + if let Some((_, log)) = log.split_once(BEGIN) { + if let Some((log, _)) = log.split_once(END) { + return Ok(log.into()); + } + } + + Ok("".into()) + } + + fn exit_code(log: &str) -> Result<i32, QemuError> { + const EXIT: &str = "\nEXIT CODE: "; + if let Some((_, rest)) = log.split_once(EXIT) { + eprintln!("log has {:?}", EXIT); + if let Some((exit, _)) = rest.split_once('\n') { + eprintln!("log has newline after exit: {:?}", exit); + if let Ok(exit) = exit.trim().parse::<i32>() { + eprintln!("log exit coded parses ok: {}", exit); + return Ok(exit); + } + eprintln!("log exit does not parse"); + } + } + Err(QemuError::NoExit) + } + fn create_tar(tar_filename: PathBuf, dirname: &Path) -> Result<VirtualDrive, QemuError> { let tar = VirtualDriveBuilder::default() .filename(&tar_filename) @@ -315,6 +350,9 @@ pub enum QemuError { #[error("failed to write temporary file")] Write(#[source] std::io::Error), + #[error("failed to read log file {0}")] + ReadLog(PathBuf, #[source] std::io::Error), + #[error("failed to open log file for writing")] Log(PathBuf, #[source] std::io::Error), @@ -329,6 +367,9 @@ pub enum QemuError { #[error("failed to read temporary file for logging")] TemporaryLog(#[source] std::io::Error), + + #[error("build log lacks exit code of run")] + NoExit, } #[cfg(test)] |