diff options
author | Lars Wirzenius <liw@noreply.codeberg.org> | 2024-01-20 12:10:50 +0000 |
---|---|---|
committer | Lars Wirzenius <liw@noreply.codeberg.org> | 2024-01-20 12:10:50 +0000 |
commit | 4e6d95c453d975305f3a3449a390bf45ab844839 (patch) | |
tree | e0065edb6e8bf6beb1e0659011a8bf5eaa667540 | |
parent | 25aae0aeff4171d6fb6284cb98f23e2adee2dadc (diff) | |
parent | 3064f7e293228981340dec1b5c86788439d1b4d4 (diff) | |
download | ambient-driver-4e6d95c453d975305f3a3449a390bf45ab844839.tar.gz |
Merge pull request 'cache' (#59) from cache into main
Reviewed-on: https://codeberg.org/ambient/ambient-driver/pulls/59
-rw-r--r-- | ambient-driver.md | 45 | ||||
-rw-r--r-- | src/action.rs | 70 | ||||
-rw-r--r-- | src/project.rs | 5 | ||||
-rw-r--r-- | src/run.rs | 7 |
4 files changed, 97 insertions, 30 deletions
diff --git a/ambient-driver.md b/ambient-driver.md index eab1226..5e20085 100644 --- a/ambient-driver.md +++ b/ambient-driver.md @@ -225,3 +225,48 @@ then stdout contains "pre_actions:\n" then stdout contains "\nactions:\n" then stdout contains "\npost_actions:\n" ~~~ +# Cache persists between CI runs + +_Requirement:_ Cache data is persisted between CI runs. + +_Justification:_ This allows incrementally building a project after +changes. + +_Stakeholders:_ Lars + +~~~scenario +given an installed ambient-driver +given file .config/ambient-driver/config.yaml from config.yaml +given an Ambient VM image ambient.qcow2 +given file cache.yaml +given a directory srcdir + +when I run ambient-driver run cache.yaml +then file ambient.log contains "counter is now 1." + +when I run ambient-driver run cache.yaml +then file ambient.log contains "counter is now 2." + +when I run ambient-driver run cache.yaml +then file ambient.log contains "counter is now 3." +~~~ + +~~~{#cache.yaml .file .yaml} +projects: + hello: + image: ambient.qcow2 + source: srcdir + plan: + - action: shell + shell: | + cache=/workspace/cache + counter="$cache/counter" + if [ -e "$counter" ]; then + n="$(expr "$(cat "$counter")" + 1)" + echo "$n" > "$counter" + else + echo 1 > "$counter" + fi + echo "counter is now $(cat "$counter")." + find "$cache" -ls +~~~ diff --git a/src/action.rs b/src/action.rs index 87aa002..c32a94a 100644 --- a/src/action.rs +++ b/src/action.rs @@ -12,6 +12,8 @@ use crate::{ vdrive::{VirtualDriveBuilder, VirtualDriveError}, }; +const RUST_ENVS: &[(&str, &str)] = &[("CARGO_TARGET_DIR", qemu::CACHE_DIR)]; + #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(tag = "action")] #[serde(rename_all = "snake_case")] @@ -138,7 +140,7 @@ impl Action { Self::Mkdir { pathname } => mkdir(pathname), Self::TarCreate { archive, directory } => tar_create(archive, directory), Self::TarExtract { archive, directory } => tar_extract(archive, directory), - Self::Spawn { argv } => spawn(argv), + Self::Spawn { argv } => spawn(argv, &[]), Self::Shell { shell: snippet } => shell(snippet), Self::RustupSetup => rustup_setup(), Self::CargoFmt => cargo_fmt(), @@ -202,7 +204,7 @@ fn tar_extract(archive: &Path, dirname: &Path) -> Result<(), ActionError> { Ok(()) } -fn spawn_in(argv: &[String], cwd: &Path) -> Result<(), ActionError> { +fn spawn_in(argv: &[String], cwd: &Path, extra_env: &[(&str, &str)]) -> Result<(), ActionError> { let argv0 = if let Some(argv0) = argv.first() { argv0 } else { @@ -212,6 +214,7 @@ fn spawn_in(argv: &[String], cwd: &Path) -> Result<(), ActionError> { let mut cmd = Command::new(argv0) .args(&argv[1..]) + .envs(extra_env.iter().copied()) .stdin(Stdio::null()) .current_dir(cwd) .spawn() @@ -233,21 +236,21 @@ fn spawn_in(argv: &[String], cwd: &Path) -> Result<(), ActionError> { fn spawn_str_in(argv: &[&str], cwd: &Path) -> Result<(), ActionError> { let argv: Vec<String> = argv.iter().map(|s| s.to_string()).collect(); - spawn_in(&argv, cwd) + spawn_in(&argv, cwd, &[]) } -fn spawn(argv: &[String]) -> Result<(), ActionError> { - spawn_in(argv, Path::new(qemu::SOURCE_DIR)) +fn spawn(argv: &[String], extra_env: &[(&str, &str)]) -> Result<(), ActionError> { + spawn_in(argv, Path::new(qemu::SOURCE_DIR), extra_env) } fn shell(snippet: &str) -> Result<(), ActionError> { let snippet = format!("set -xeuo pipefail\n{}", snippet); - spawn(&["/bin/bash".into(), "-c".into(), snippet]) + spawn(&["/bin/bash".into(), "-c".into(), snippet], &[]) } -fn spawn_str(argv: &[&str]) -> Result<(), ActionError> { +fn spawn_str(argv: &[&str], extra_env: &[(&str, &str)]) -> Result<(), ActionError> { let argv: Vec<String> = argv.iter().map(|s| s.to_string()).collect(); - spawn(&argv) + spawn(&argv, extra_env) } fn rustup_setup() -> Result<(), ActionError> { @@ -282,37 +285,46 @@ fn rustup_setup() -> Result<(), ActionError> { } fn cargo_fmt() -> Result<(), ActionError> { - spawn_str(&["cargo", "fmt", "--offline", "--workspace", "--all-targets"]) + spawn_str( + &["cargo", "fmt", "--offline", "--workspace", "--all-targets"], + RUST_ENVS, + ) } fn cargo_clippy() -> Result<(), ActionError> { - spawn_str(&["cargo", "clippy", "--all"]) + spawn_str(&["cargo", "clippy", "--all"], RUST_ENVS) } fn cargo_build() -> Result<(), ActionError> { - spawn_str(&[ - "cargo", - "build", - "--offline", - "--workspace", - "--all-targets", - ]) + spawn_str( + &[ + "cargo", + "build", + "--offline", + "--workspace", + "--all-targets", + ], + RUST_ENVS, + ) } fn cargo_test() -> Result<(), ActionError> { - spawn_str(&["cargo", "test", "--offline", "--workspace"]) + spawn_str(&["cargo", "test", "--offline", "--workspace"], RUST_ENVS) } fn cargo_install() -> Result<(), ActionError> { - spawn_str(&[ - "cargo", - "install", - "--offline", - "--bins", - "--path=.", - "--root", - qemu::ARTIFACTS_DIR, - ]) + spawn_str( + &[ + "cargo", + "install", + "--offline", + "--bins", + "--path=.", + "--root", + qemu::ARTIFACTS_DIR, + ], + RUST_ENVS, + ) } fn deb() -> Result<(), ActionError> { @@ -335,7 +347,7 @@ mv ../*_* {} qemu::ARTIFACTS_DIR ); - spawn_str(&["bash", "-c", &shell]) + spawn_str(&["bash", "-c", &shell], RUST_ENVS) } #[derive(Debug, thiserror::Error)] @@ -424,6 +436,6 @@ mod test { // We can't use the Spawn action here, as it expects the // SOURCE_DIR to exist. However, spawn_in does the same thing, // except in a directory of our choosing. - assert!(spawn_in(&["true".into()], Path::new("/")).is_ok()); + assert!(spawn_in(&["true".into()], Path::new("/"), &[]).is_ok()); } } diff --git a/src/project.rs b/src/project.rs index 1ef8fc0..2c5f23d 100644 --- a/src/project.rs +++ b/src/project.rs @@ -183,6 +183,11 @@ impl State { Ok(()) } + /// Return cache directory for project. + pub fn cachedir(&self) -> PathBuf { + self.statedir.join("cache") + } + /// Return latest commit that CI has run on. pub fn latest_commit(&self) -> Option<&str> { self.latest_commit.as_deref() @@ -52,6 +52,11 @@ fn cmd_run(config: &EffectiveConfig, run: &RunCommand) -> Result<(), RunError> { if do_run { info!("{}: running CI on {}", name, project.source().display()); + let cachedir = state.cachedir(); + if !cachedir.exists() { + mkdir(&cachedir)?; + } + debug!("Executing pre-plan steps"); for action in project.pre_plan() { action.execute(project, statedir)?; @@ -96,7 +101,7 @@ fn cmd_run(config: &EffectiveConfig, run: &RunCommand) -> Result<(), RunError> { .with_artifact(&Some(artifact.clone())) .with_artifact_max_size(project.artifact_max_size()) .with_dependencies(&Some(dependencies.clone())) - .with_cache(&None) + .with_cache(&Some(cachedir.clone())) .with_log(log); let exit = qemu.run()?; debug!("QEMU exit code {}", exit); |