diff --git a/integration-tests/apply-fail/default.nix b/integration-tests/apply-fail/default.nix new file mode 100644 index 0000000..9f3e5b1 --- /dev/null +++ b/integration-tests/apply-fail/default.nix @@ -0,0 +1,18 @@ +let + tools = import ../tools.nix {}; +in tools.makeTest { + name = "colmena-apply-fail"; + + bundle = ./.; + + testScript = '' + beta.block() + + # HACK: copy stderr to both stdout and stderr + # (stdout is what's returned, and only stderr appears on screen during the build) + logs = deployer.fail("cd /tmp/bundle && ${tools.colmenaExec} apply -v --eval-node-limit 4 --on @target 2> >(tee /dev/stderr)") + + alpha.succeed("grep SUCCESS /etc/deployment") + gamma.succeed("grep SUCCESS /etc/deployment") + ''; +} diff --git a/integration-tests/apply-fail/hive.nix b/integration-tests/apply-fail/hive.nix new file mode 100644 index 0000000..f86a35f --- /dev/null +++ b/integration-tests/apply-fail/hive.nix @@ -0,0 +1,23 @@ +let + tools = import ./tools.nix { insideVm = true; }; + + testPkg = let + text = builtins.trace "must appear during evaluation" '' + echo "must appear during build" + mkdir -p $out + ''; + in tools.pkgs.runCommand "test-package" {} text; +in { + meta = { + nixpkgs = tools.pkgs; + }; + + defaults = { + environment.etc."deployment".text = "SUCCESS"; + }; + + deployer = tools.getStandaloneConfigFor "deployer"; + alpha = tools.getStandaloneConfigFor "alpha"; + beta = tools.getStandaloneConfigFor "beta"; + gamma = tools.getStandaloneConfigFor "gamma"; +} diff --git a/integration-tests/default.nix b/integration-tests/default.nix index ddc0e49..54c607e 100644 --- a/integration-tests/default.nix +++ b/integration-tests/default.nix @@ -1,5 +1,6 @@ { apply = import ./apply; + apply-fail = import ./apply-fail; apply-local = import ./apply-local; exec = import ./exec; } diff --git a/src/nix/deployment/mod.rs b/src/nix/deployment/mod.rs index a2514a3..9b113f8 100644 --- a/src/nix/deployment/mod.rs +++ b/src/nix/deployment/mod.rs @@ -226,11 +226,16 @@ impl Deployment { return Ok(()); } + let mut futures = Vec::new(); + for (name, profile) in profiles.iter() { let target = chunk.remove(name).unwrap(); - self.clone().deploy_node(parent.clone(), target, profile.clone()).await?; + futures.push(self.clone().deploy_node(parent.clone(), target, profile.clone())); } + let result: NixResult> = join_all(futures).await.into_iter().collect(); + result?; + // Create GC root if self.options.create_gc_roots { let job = parent.create_job(JobType::CreateGcRoots, nodes.clone())?;