summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@noreply.codeberg.org>2023-11-03 17:10:41 +0000
committerLars Wirzenius <liw@noreply.codeberg.org>2023-11-03 17:10:41 +0000
commitdc9d960985afb21f86656639ecee3138ca50f7fc (patch)
tree026d79f0c56b310253e1e2c7d81082502b2f00f4
parentabc6c7aa30ce179c5b5d43598bfa612491a89faa (diff)
parentb6e91f0579a32ab466e2f5126d15775022918137 (diff)
downloadambient-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.md8
-rw-r--r--src/bin/ambient-run.rs9
-rw-r--r--src/error.rs3
-rw-r--r--src/qemu.rs51
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)]