summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@noreply.codeberg.org>2023-09-02 06:44:42 +0000
committerLars Wirzenius <liw@noreply.codeberg.org>2023-09-02 06:44:42 +0000
commitdcf990d1f1871c3f6d0f7be8eeab7e48570d9196 (patch)
tree6e8a3b81c383a7cb397cd300f4192a457b10213f
parentf89bcc3784c86e719ee2118a9d4f8aece4f4bdc2 (diff)
parent17eb20a3ed9f11e302a7af41dcd02655f51e80ec (diff)
downloadambient-run-dcf990d1f1871c3f6d0f7be8eeab7e48570d9196.tar.gz
Merge pull request 'Allow project to specify where build puts artifacts it produces' (#5) from artifact-output into main
Reviewed-on: https://codeberg.org/ambient/ambient-run/pulls/5
-rw-r--r--ambient-run.md90
-rw-r--r--src/bin/ambient-run.rs4
-rw-r--r--src/project.rs18
-rw-r--r--src/qemu.rs28
4 files changed, 137 insertions, 3 deletions
diff --git a/ambient-run.md b/ambient-run.md
index 1690cce..82eccab 100644
--- a/ambient-run.md
+++ b/ambient-run.md
@@ -165,6 +165,8 @@ source: .
shell: |
cargo test
image: /my/image.qcow2
+artifact: null
+artifact_max_size: null
~~~
### Show per-build configuration
@@ -226,6 +228,94 @@ shell: |
image: image.qcow2
~~~
+### Build produces an artifact
+
+_Requirement:_ The build can produce an artifact.
+
+_Justification:_ Without this a build can't produce something that can
+be used after the build has finished.
+
+_Stakeholder:_ Lars.
+
+~~~scenario
+given an installed ambient-run
+given file 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 artifact-project.yaml --log foo.log
+then file foo.tar exists
+when I run tar tf foo.tar
+then stdout contains "README.md"
+~~~
+
+
+~~~{#artifact-project.yaml .file .yaml}
+source: foo
+shell: |
+ #!/bin/bash
+ tar -cf /dev/vdc .
+image: image.qcow2
+artifact: foo.tar
+~~~
+
+### Fail build that tries to produce an unwanted artifact
+
+_Requirement:_ If an artifact output is not specified for the project,
+fail a build that tries to make one.
+
+_Justification:_ If a build tries to create an artifact, but one isn't
+wanted, the build should fail.
+
+_Stakeholder:_ Lars.
+
+~~~scenario
+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
+then file foo.log contains "EXIT CODE: 2"
+~~~
+
+
+~~~{#no-artifact-project.yaml .file .yaml}
+source: foo
+shell: |
+ #!/bin/bash
+ tar -cf /dev/vdc .
+image: image.qcow2
+~~~
+
+### Fail build that tries to produce an oversize artifact
+
+_Requirement:_ If a build produces an artifact that is too large, the
+build should fail.
+
+_Justification:_ Without a limit, a malicious build could fill all
+available storage space, which is a denial-of-service attack.
+
+_Stakeholder:_ Lars.
+
+~~~scenario
+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
+then file foo.log contains "EXIT CODE: 2"
+~~~
+
+
+~~~{#small-artifact-project.yaml .file .yaml}
+source: foo
+shell: |
+ #!/bin/bash
+ tar -cf /dev/vdc .
+image: image.qcow2
+artifact: foo.tar
+artifact_max_size: 1
+~~~
+
### Build is given dependencies
### Cache is persistent between builds
### Build gets the resources is demands
diff --git a/src/bin/ambient-run.rs b/src/bin/ambient-run.rs
index e1f1b16..37054c2 100644
--- a/src/bin/ambient-run.rs
+++ b/src/bin/ambient-run.rs
@@ -215,7 +215,9 @@ impl BuildCommand {
let project = Project::load(&self.filename, config)?;
let mut qemu = Qemu::new(&project.image())
.with_shell(project.shell())
- .with_source(&project.source());
+ .with_source(&project.source())
+ .with_artifact(project.artifact())
+ .with_artifact_max_size(project.artifact_max_size());
if let Some(log) = &self.log {
qemu = qemu.with_log(log);
}
diff --git a/src/project.rs b/src/project.rs
index 8a182bc..76f42dc 100644
--- a/src/project.rs
+++ b/src/project.rs
@@ -12,6 +12,8 @@ pub struct Project {
source: PathBuf,
shell: String,
image: PathBuf,
+ artifact: Option<PathBuf>,
+ artifact_max_size: Option<u64>,
}
impl Project {
@@ -43,6 +45,8 @@ impl Project {
source: PathBuf::from("."),
shell: "".into(),
image,
+ artifact: None,
+ artifact_max_size: None,
};
project.add_from(filename)?;
if project.shell.is_empty() {
@@ -68,6 +72,8 @@ impl Project {
if let Some(x) = snippet.image {
self.image = x;
}
+ self.artifact = snippet.artifact;
+ self.artifact_max_size = snippet.artifact_max_size;
Ok(())
}
@@ -90,6 +96,16 @@ impl Project {
pub fn shell(&self) -> &str {
self.shell.as_ref()
}
+
+ /// Artifact file.
+ pub fn artifact(&self) -> &Option<PathBuf> {
+ &self.artifact
+ }
+
+ /// Artifact file max size.
+ pub fn artifact_max_size(&self) -> Option<u64> {
+ self.artifact_max_size.clone()
+ }
}
#[derive(Debug, Deserialize)]
@@ -98,6 +114,8 @@ struct ProjectSnippet {
source: Option<PathBuf>,
shell: Option<String>,
image: Option<PathBuf>,
+ artifact: Option<PathBuf>,
+ artifact_max_size: Option<u64>,
}
/// Possible errors from configuration file handling.
diff --git a/src/qemu.rs b/src/qemu.rs
index c48213f..4c6efff 100644
--- a/src/qemu.rs
+++ b/src/qemu.rs
@@ -18,6 +18,8 @@ pub struct Qemu {
log: Option<PathBuf>,
source: PathBuf,
shell: Option<String>,
+ artifact: Option<PathBuf>,
+ artifact_max_xize: u64,
}
impl Qemu {
@@ -26,6 +28,7 @@ impl Qemu {
Self {
image: image.into(),
source: PathBuf::from("."),
+ artifact_max_xize: MAX_OUTPUT_SIZE,
..Default::default()
}
}
@@ -48,6 +51,18 @@ impl Qemu {
self
}
+ /// Set output artifact filename.
+ pub fn with_artifact(mut self, artifact: &Option<PathBuf>) -> Self {
+ self.artifact = artifact.clone();
+ self
+ }
+
+ /// Set maximum length of output artifact.
+ pub fn with_artifact_max_size(mut self, size: Option<u64>) -> Self {
+ self.artifact_max_xize = size.unwrap_or(MAX_OUTPUT_SIZE);
+ self
+ }
+
/// Run QEMU in the specified way.
pub fn run(&self) -> Result<(), QemuError> {
eprintln!("qemu run");
@@ -62,8 +77,17 @@ impl Qemu {
copy(OVMF_FD, &vars).map_err(|e| QemuError::Copy(OVMF_FD.into(), e))?;
eprintln!("output drive");
- let output_drive =
- Self::create_tar_with_size(tmp.path().join("output"), empty.path(), MAX_OUTPUT_SIZE)?;
+ let output_drive = if let Some(filename) = &self.artifact {
+ eprintln!("output to {}", filename.display());
+ Self::create_tar_with_size(
+ filename.to_path_buf(),
+ empty.path(),
+ self.artifact_max_xize,
+ )?
+ } else {
+ eprintln!("empty output drive");
+ Self::create_tar_with_size(tmp.path().join("output"), empty.path(), 0)?
+ };
eprintln!("cache drive");
let cache_drive =