mirror of
https://github.com/NixOS/nixpkgs.git
synced 2026-07-06 17:13:24 -05:00
nixos/activation: avoid build failure with large activation script
Two improvements:
* use `writeShellApplication` (which uses `passAsFile` instead of
passing the activation script as an env var into the derivation.
We disable shellcheck and the bash options that this builder
usually adds to avoid issues with out-of-tree activation scripts.
* use `sed` instead of `substituteInPlace`, since the substitute
functions load the file content into a shell variable
This avoids issues when the activation is too long to fit in a shell variable.
Before this commit, a very large activation script, would cause build
failures because of different limits on the file content size, e.g.
```
➜ nix build -f . nixosTests.restartByActivationScript.nodes.machine.system.build.toplevel -vL
this derivation will be built:
/nix/store/xw6anpfjyamnycjg58cmj01sz3ididyl-nixos-system-machine-test.drv
building '/nix/store/xw6anpfjyamnycjg58cmj01sz3ididyl-nixos-system-machine-test.drv'...
nixos-system-machine-test> error: executing '/nix/store/rlq03x4cwf8zn73hxaxnx0zn5q9kifls-bash-5.3p3/bin/bash': Argument list too long
error: builder for '/nix/store/xw6anpfjyamnycjg58cmj01sz3ididyl-nixos-system-machine-test.drv' failed with exit code 1;
last 1 log lines:
> error: executing '/nix/store/rlq03x4cwf8zn73hxaxnx0zn5q9kifls-bash-5.3p3/bin/bash': Argument list too long
For full logs, run:
nix log /nix/store/xw6anpfjyamnycjg58cmj01sz3ididyl-nixos-system-machine-test.drv
```
This commit is contained in:
parent
d8ed39998c
commit
9bfd0d688d
3 changed files with 50 additions and 35 deletions
|
|
@ -11,12 +11,6 @@ let
|
|||
mkOption
|
||||
types
|
||||
;
|
||||
|
||||
systemBuilderArgs = {
|
||||
activationScript = config.system.activationScripts.script;
|
||||
dryActivationScript = config.system.dryActivationScript;
|
||||
};
|
||||
|
||||
in
|
||||
{
|
||||
options = {
|
||||
|
|
@ -52,36 +46,51 @@ in
|
|||
'';
|
||||
};
|
||||
};
|
||||
config = {
|
||||
system.activatableSystemBuilderCommands = ''
|
||||
echo "$activationScript" > $out/activate
|
||||
echo "$dryActivationScript" > $out/dry-activate
|
||||
substituteInPlace $out/activate --subst-var-by out ''${!toplevelVar}
|
||||
substituteInPlace $out/dry-activate --subst-var-by out ''${!toplevelVar}
|
||||
chmod u+x $out/activate $out/dry-activate
|
||||
unset activationScript dryActivationScript
|
||||
'';
|
||||
config =
|
||||
let
|
||||
activationScript = lib.getExe (
|
||||
pkgs.writeShellApplication {
|
||||
name = "activate";
|
||||
text = config.system.activationScripts.script;
|
||||
checkPhase = "";
|
||||
bashOptions = [ ];
|
||||
}
|
||||
);
|
||||
dryActivationScript = lib.getExe (
|
||||
pkgs.writeShellApplication {
|
||||
name = "dry-activate";
|
||||
text = config.system.dryActivationScript;
|
||||
checkPhase = "";
|
||||
bashOptions = [ ];
|
||||
}
|
||||
);
|
||||
in
|
||||
{
|
||||
system.activatableSystemBuilderCommands =
|
||||
# We use sed here instead of substitute(InPlace), because the substitute
|
||||
# functions load the content of the file into a bash variable, which fails
|
||||
# for very large activation scripts.
|
||||
# bash
|
||||
''
|
||||
cp ${activationScript} $out/activate
|
||||
cp ${dryActivationScript} $out/dry-activate
|
||||
${lib.getExe pkgs.gnused} --in-place --expression "s|@out@|''${!toplevelVar}|g" $out/activate $out/dry-activate
|
||||
'';
|
||||
|
||||
system.systemBuilderCommands = lib.mkIf config.system.activatable config.system.activatableSystemBuilderCommands;
|
||||
system.systemBuilderArgs = lib.mkIf config.system.activatable (
|
||||
systemBuilderArgs
|
||||
// {
|
||||
system.systemBuilderCommands = lib.mkIf config.system.activatable config.system.activatableSystemBuilderCommands;
|
||||
system.systemBuilderArgs = lib.mkIf config.system.activatable {
|
||||
toplevelVar = "out";
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
system.build.separateActivationScript =
|
||||
pkgs.runCommand "separate-activation-script"
|
||||
(
|
||||
systemBuilderArgs
|
||||
// {
|
||||
system.build.separateActivationScript =
|
||||
pkgs.runCommand "separate-activation-script"
|
||||
{
|
||||
toplevelVar = "toplevel";
|
||||
toplevel = config.system.build.toplevel;
|
||||
}
|
||||
)
|
||||
''
|
||||
mkdir $out
|
||||
${config.system.activatableSystemBuilderCommands}
|
||||
'';
|
||||
};
|
||||
''
|
||||
mkdir $out
|
||||
${config.system.activatableSystemBuilderCommands}
|
||||
'';
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,8 +50,6 @@ let
|
|||
) withHeadlines;
|
||||
in
|
||||
''
|
||||
#!${pkgs.runtimeShell}
|
||||
|
||||
source ${./lib/lib.sh}
|
||||
|
||||
systemConfig='@out@'
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
};
|
||||
|
||||
nodes.machine =
|
||||
{ pkgs, ... }:
|
||||
{ pkgs, lib, ... }:
|
||||
{
|
||||
imports = [ ../modules/profiles/minimal.nix ];
|
||||
|
||||
|
|
@ -46,6 +46,14 @@
|
|||
fi
|
||||
'';
|
||||
};
|
||||
|
||||
# Make sure we don't crash on long activation scripts
|
||||
specialisation.longscript.configuration = {
|
||||
system.activationScripts.long = {
|
||||
supportsDryActivation = true;
|
||||
text = lib.concatStringsSep "\n" (lib.genList (i: ''# line number ${toString i}'') 1000000);
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = # python
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue