aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pkgs/krops/default.nix54
-rw-r--r--tests/scenarios.nix60
2 files changed, 74 insertions, 40 deletions
diff --git a/pkgs/krops/default.nix b/pkgs/krops/default.nix
index 3aa68cf..ac2d9a2 100644
--- a/pkgs/krops/default.nix
+++ b/pkgs/krops/default.nix
@@ -8,22 +8,41 @@ in
flake ? null,
useNixOutputMonitor
}:
- args: target:
+ args: target: let
+ # The flake's directory in the target directory, and the name of the
+ # NixOS configuration with its #, if any.
+ flakeDir = lib.head (lib.splitString "#" flake);
+ flakeAttr = lib.removePrefix flakeDir flake;
+ in
runShell target {}
(withNixOutputMonitor target useNixOutputMonitor /* sh */ ''
- ${lib.optionalString (flake != null)
- (lib.shell.requireFlakes "deploying a flake")}
+ ${lib.optionalString (flake != null) /* sh */ ''
+ ${lib.shell.requireFlakes "deploying a flake"}
+ ${lib.shell.urlPath}
+ # A Git work tree gets deployed as such. Anything else gets
+ # deployed as path:, not just by its path, which Nix takes for the
+ # enclosing Git work tree, if any. Nix refuses URLs with symlinks
+ # on the way, which the target directory may be, or the source.
+ flake=$(readlink -f ${lib.escapeShellArg "${target.path}/${flakeDir}"})
+ if test -e "$flake"/.git; then
+ if test -e "$flake"/.gitmodules; then
+ flake=git+file:$(url_path "$flake")?submodules=1
+ else
+ flake=git+file:$(url_path "$flake")
+ fi
+ else
+ flake=path:$(url_path "$flake")
+ fi
+ ''}
NIX_PATH=${lib.escapeShellArg target.path} \
- nixos-rebuild ${lib.escapeShellArgs (args ++ lib.optionals (flake != null) [
- "--flake"
- # Generated flakes as path:, not just their paths, which Nix takes
- # for the enclosing Git work tree, if any.
- (lib.optionalString (lib.hasPrefix ".populate/flakes/" flake) "path:" +
- "${target.path}/${flake}")
- ])} ${lib.optionalString (flake == null)
- # nixos-rebuild deploys /etc/nixos/flake.nix if it exists. Any
- # nixos-rebuild doing so supports --no-flake.
- "$(test -e /etc/nixos/flake.nix && echo --no-flake)"}
+ nixos-rebuild ${lib.escapeShellArgs args} ${
+ if flake != null then
+ ''--flake "$flake"${lib.escapeShellArg flakeAttr}''
+ else
+ # nixos-rebuild deploys /etc/nixos/flake.nix if it exists. Any
+ # nixos-rebuild doing so supports --no-flake.
+ "$(test -e /etc/nixos/flake.nix && echo --no-flake)"
+ }
'');
runShell = target: {
@@ -117,6 +136,11 @@ in
then target'
else lib.mkTarget buildTarget;
target' = lib.mkTarget target;
+ # A host as nixos-rebuild takes it. Without a user, ssh decides.
+ userHost = target:
+ lib.optionalString (target.user != null && target.user != "")
+ "${target.user}@" +
+ target.host;
# The source's generated flake, if it draws inputs from other sources.
flake' = let
name = lib.head (lib.splitString "#" flake);
@@ -140,8 +164,8 @@ in
] ++ lib.optionals crossDeploy [
"--no-build-nix"
] ++ lib.optionals (buildTarget' != target') [
- "--build-host" "${buildTarget'.user}@${buildTarget'.host}"
- "--target-host" "${target'.user}@${target'.host}"
+ "--build-host" (userHost buildTarget')
+ "--target-host" (userHost target')
] ++ lib.optionals (buildTarget' != target' && target'.sudo) [
# nixos-rebuild runs on the target itself via sudo otherwise.
"--use-remote-sudo"
diff --git a/tests/scenarios.nix b/tests/scenarios.nix
index 849d3e3..a7dff66 100644
--- a/tests/scenarios.nix
+++ b/tests/scenarios.nix
@@ -585,29 +585,33 @@ assert !(krops.isLocalTarget (targets.remote "/"));
});
# writeDeploy's arguments to nixos-rebuild, which a stand-in records.
+ # flake is what gets deployed: nothing, or a flake from a file, git, or
+ # flake source, or one whose inputs get drawn from a source, by rewriting
+ # its lock file or through a generated flake.
deploy = matrix "deploy" {
- flake = [ "none" "source" "rewrite" "generated" ];
+ flake = [ "none" "file" "git" "source" "rewrite" "generated" ];
etcFlake = [ false true ];
buildTarget = [ false true ];
} (flags: ctx: let
target = targets.${ctx.targetKind} ctx.path;
buildTarget = targets.local "${ctx.path}-build";
build = if flags.buildTarget then buildTarget else target;
+ # Without a user, ssh decides.
+ userHost = target:
+ optionalString (target.user != null && target.user != "") "${target.user}@" +
+ target.host;
expected = [ "switch" ]
++ optionals flags.buildTarget [
- "--build-host" "${buildTarget.user}@${buildTarget.host}"
- "--target-host" "${target.user}@${target.host}"
+ "--build-host" (userHost buildTarget)
+ "--target-host" (userHost target)
]
- ++ optional (flags.buildTarget && target.sudo) "--use-remote-sudo"
- ++ {
- none = [];
- source = [ "--flake" "${build.path}/x" ];
- rewrite = [ "--flake" "${build.path}/x" ];
- # Generated flakes as path:, which an enclosing Git work tree doesn't
- # capture.
- generated = [ "--flake" "path:${build.path}/.populate/flakes/x" ];
- }.${flags.flake}
- ++ optional (flags.etcFlake && flags.flake == "none") "--no-flake";
+ ++ optional (flags.buildTarget && target.sudo) "--use-remote-sudo";
+ # The flake's directory, which gets deployed by its resolved path, as
+ # path:, so no enclosing Git work tree captures it, or as the Git work
+ # tree it is.
+ flakeDir =
+ if flags.flake == "generated" then ".populate/flakes/x" else "x";
+ scheme = if flags.flake == "git" then "git+file" else "path";
in
# The local target can't have another build target.
if flags.buildTarget && ctx.targetKind == "local" then null else {
@@ -623,17 +627,18 @@ assert !(krops.isLocalTarget (targets.remote "/"));
''}
'';
phases = twice {
- sources =
- if flags.flake == "none" then {
- x.file = "/fixtures/alt";
- } else alt // {
- x.flake = {
- url = "/fixtures/top";
- fetchOnTarget = ctx.targetKind == "sudo";
- } // drawInputs (if flags.flake == "source" then "none" else flags.flake) {
- dep.follows = "alt";
- };
+ sources = {
+ none.x.file = "/fixtures/alt";
+ file.x.file = "/fixtures/alt";
+ git.x.git = { url = gitUrl; ref = gitHead; };
+ }.${flags.flake} or (alt // {
+ x.flake = {
+ url = "/fixtures/top";
+ fetchOnTarget = ctx.targetKind == "sudo";
+ } // drawInputs (if flags.flake == "source" then "none" else flags.flake) {
+ dep.follows = "alt";
};
+ });
deploy = {
flake = if flags.flake == "none" then null else "x";
} // optionalAttrs flags.buildTarget {
@@ -642,8 +647,13 @@ assert !(krops.isLocalTarget (targets.remote "/"));
check = ''
expect_eq user "$(sed -n 1p /tmp/nixos-rebuild.log)" 0
expect_eq NIX_PATH "$(sed -n 2p /tmp/nixos-rebuild.log)" ${build.path}
- expect_eq arguments "$(sed -n 3p /tmp/nixos-rebuild.log)" \
- ${lib.escapeShellArg (concatStringsSep " " expected)}
+ expected=${lib.escapeShellArg (concatStringsSep " " expected)}
+ ${if flags.flake == "none" then optionalString flags.etcFlake ''
+ expected="$expected --no-flake"
+ '' else ''
+ expected="$expected --flake ${scheme}:$(readlink -f ${build.path}/${flakeDir})"
+ ''}
+ expect_eq arguments "$(sed -n 3p /tmp/nixos-rebuild.log)" "$expected"
'';
};
});