staging-nixos merge for 2025-10-12 (#451326)
This commit is contained in:
@@ -36,6 +36,24 @@ in
|
||||
|
||||
options = {
|
||||
|
||||
environment.shell.enable = lib.mkEnableOption "" // {
|
||||
default = true;
|
||||
internal = true;
|
||||
description = ''
|
||||
Whether to enable the shell environment.
|
||||
|
||||
This does NOT necessarily disable all shells on your system. Instead it
|
||||
just disables the shell environment that configures user shells (i.e.
|
||||
those in `environment.shells`).
|
||||
|
||||
System services might still depend on and use shells even if this
|
||||
option is set to false.
|
||||
|
||||
Only set this option if you're sure that you can recover from potential
|
||||
issues.
|
||||
'';
|
||||
};
|
||||
|
||||
environment.variables = lib.mkOption {
|
||||
default = { };
|
||||
example = {
|
||||
@@ -175,10 +193,10 @@ in
|
||||
};
|
||||
|
||||
environment.binsh = lib.mkOption {
|
||||
default = "${config.system.build.binsh}/bin/sh";
|
||||
defaultText = lib.literalExpression ''"''${config.system.build.binsh}/bin/sh"'';
|
||||
default = null;
|
||||
defaultText = lib.literalExpression ''"''${pkgs.bashInteractive}/bin/sh"'';
|
||||
example = lib.literalExpression ''"''${pkgs.dash}/bin/dash"'';
|
||||
type = lib.types.path;
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
visible = false;
|
||||
description = ''
|
||||
The shell executable that is linked system-wide to
|
||||
@@ -201,9 +219,10 @@ in
|
||||
|
||||
};
|
||||
|
||||
config = {
|
||||
config = lib.mkIf cfg.shell.enable {
|
||||
|
||||
system.build.binsh = pkgs.bashInteractive;
|
||||
# Set this here so its enabled only when shell support is enabled
|
||||
environment.binsh = lib.mkDefault "${pkgs.bashInteractive}/bin/sh";
|
||||
|
||||
# Set session variables in the shell as well. This is usually
|
||||
# unnecessary, but it allows changes to session variables to take
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
{ lib, ... }:
|
||||
|
||||
{
|
||||
|
||||
# Bashless builds on perlless
|
||||
imports = [ ./perlless.nix ];
|
||||
|
||||
# Remove bash from activation
|
||||
system.nixos-init.enable = lib.mkDefault true;
|
||||
system.activatable = lib.mkDefault false;
|
||||
environment.shell.enable = lib.mkDefault false;
|
||||
programs.bash.enable = lib.mkDefault false;
|
||||
|
||||
# Random bash remnants
|
||||
environment.corePackages = lib.mkForce [ ];
|
||||
# Contains bash completions
|
||||
nix.enable = lib.mkDefault false;
|
||||
# The fuse{,3} package contains a runtime dependency on bash.
|
||||
programs.fuse.enable = lib.mkDefault false;
|
||||
documentation.man.man-db.enable = lib.mkDefault false;
|
||||
# autovt depends on bash
|
||||
console.enable = lib.mkDefault false;
|
||||
# dhcpcd and openresolv depend on bash
|
||||
networking.useNetworkd = lib.mkDefault true;
|
||||
# bcache tools depend on bash.
|
||||
boot.bcache.enable = lib.mkDefault false;
|
||||
# iptables depends on bash and nixos-firewall-tool is a bash script
|
||||
networking.firewall.enable = lib.mkDefault false;
|
||||
# the wrapper script is in bash
|
||||
security.enableWrappers = lib.mkDefault false;
|
||||
# kexec script is written in bash
|
||||
boot.kexec.enable = lib.mkDefault false;
|
||||
# Relies on bash scripts
|
||||
powerManagement.enable = lib.mkDefault false;
|
||||
# Has some bash inside
|
||||
systemd.shutdownRamfs.enable = lib.mkDefault false;
|
||||
# Relies on the gzip command which depends on bash
|
||||
services.logrotate.enable = lib.mkDefault false;
|
||||
# Service relies on bash scripts
|
||||
services.timesyncd.enable = lib.mkDefault false;
|
||||
|
||||
# Check that the system does not contain a Nix store path that contains the
|
||||
# string "bash".
|
||||
system.forbiddenDependenciesRegexes = [ "bash" ];
|
||||
|
||||
}
|
||||
@@ -158,6 +158,8 @@ in
|
||||
This must not be a store path, since the path is
|
||||
used outside the store (in particular in /etc/passwd).
|
||||
'';
|
||||
# /bin/sh is also the compiled in default of the shadow package.
|
||||
default = "/bin/sh";
|
||||
example = lib.literalExpression "pkgs.zsh";
|
||||
type = lib.types.either lib.types.path lib.types.shellPackage;
|
||||
};
|
||||
|
||||
@@ -376,7 +376,9 @@ in
|
||||
);
|
||||
# End if legacy environment variables
|
||||
|
||||
preSwitchCheck = config.system.preSwitchChecksScript;
|
||||
preSwitchCheck = lib.mkIf (
|
||||
config.system.preSwitchChecks != { }
|
||||
) config.system.preSwitchChecksScript;
|
||||
|
||||
# Not actually used in the builder. `passedChecks` is just here to create
|
||||
# the build dependencies. Checks are similar to build dependencies in the
|
||||
|
||||
@@ -325,6 +325,22 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
shell.enable = lib.mkEnableOption "" // {
|
||||
default = config.environment.shell.enable;
|
||||
internal = true;
|
||||
description = ''
|
||||
Whether to enable a shell in the initrd.
|
||||
|
||||
In contrast to `environment.shell.enable`, this option actually
|
||||
strictly disables all shells in the initrd because they're not copied
|
||||
into it anymore. Paths that use a shell (e.g. via the `script` option),
|
||||
will break if this option is set.
|
||||
|
||||
Only set this option if you're sure that you can recover from potential
|
||||
issues.
|
||||
'';
|
||||
};
|
||||
|
||||
units = mkOption {
|
||||
description = "Definition of systemd units.";
|
||||
default = { };
|
||||
@@ -460,13 +476,15 @@ in
|
||||
++ lib.optional (config.boot.initrd.systemd.root == "gpt-auto") "rw";
|
||||
|
||||
boot.initrd.systemd = {
|
||||
# bashInteractive is easier to use and also required by debug-shell.service
|
||||
initrdBin = [
|
||||
pkgs.bashInteractive
|
||||
pkgs.coreutils
|
||||
cfg.package
|
||||
]
|
||||
++ lib.optional (config.system.build.kernel.config.isYes "MODULES") cfg.package.kmod;
|
||||
++ lib.optional (config.system.build.kernel.config.isYes "MODULES") cfg.package.kmod
|
||||
++ lib.optionals cfg.shell.enable [
|
||||
# bashInteractive is easier to use and also required by debug-shell.service
|
||||
pkgs.bashInteractive
|
||||
];
|
||||
extraBin = {
|
||||
less = "${pkgs.less}/bin/less";
|
||||
mount = "${cfg.package.util-linux}/bin/mount";
|
||||
@@ -550,11 +568,6 @@ in
|
||||
"${cfg.package.util-linux}/bin/umount"
|
||||
"${cfg.package.util-linux}/bin/sulogin"
|
||||
|
||||
# required for services generated with writeShellScript and friends
|
||||
pkgs.runtimeShell
|
||||
# some tools like xfs still want the sh symlink
|
||||
"${pkgs.bashNonInteractive}/bin"
|
||||
|
||||
# so NSS can look up usernames
|
||||
"${pkgs.glibc}/lib/libnss_files.so.2"
|
||||
|
||||
@@ -566,6 +579,12 @@ in
|
||||
++ lib.optionals config.system.nixos-init.enable [
|
||||
"${config.system.nixos-init.package}/bin/initrd-init"
|
||||
]
|
||||
++ lib.optionals cfg.shell.enable [
|
||||
# required for services generated with writeShellScript and friends
|
||||
pkgs.runtimeShell
|
||||
# some tools like xfs still want the sh symlink
|
||||
"${pkgs.bashNonInteractive}/bin"
|
||||
]
|
||||
++ jobScripts
|
||||
++ map (c: builtins.removeAttrs c [ "text" ]) (builtins.attrValues cfg.contents);
|
||||
|
||||
|
||||
@@ -85,6 +85,9 @@ in
|
||||
{
|
||||
|
||||
options.testing = {
|
||||
backdoor = lib.mkEnableOption "backdoor service in stage 2" // {
|
||||
default = true;
|
||||
};
|
||||
|
||||
initrdBackdoor = lib.mkEnableOption ''
|
||||
backdoor.service in initrd. Requires
|
||||
@@ -107,12 +110,14 @@ in
|
||||
}
|
||||
];
|
||||
|
||||
systemd.services.backdoor = lib.mkMerge [
|
||||
backdoorService
|
||||
{
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
}
|
||||
];
|
||||
systemd.services.backdoor = lib.mkIf cfg.backdoor (
|
||||
lib.mkMerge [
|
||||
backdoorService
|
||||
{
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
}
|
||||
]
|
||||
);
|
||||
|
||||
boot.initrd.systemd = lib.mkMerge [
|
||||
{
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
{
|
||||
nixos,
|
||||
stdenvNoCC,
|
||||
jq,
|
||||
zstd,
|
||||
cpio,
|
||||
}:
|
||||
|
||||
let
|
||||
machine = nixos (
|
||||
{ lib, modulesPath, ... }:
|
||||
{
|
||||
imports = [ "${modulesPath}/profiles/bashless.nix" ];
|
||||
|
||||
fileSystems."/" = {
|
||||
device = "/dev/disk/by-partlabel/root";
|
||||
fsType = "ext4";
|
||||
};
|
||||
|
||||
system.stateVersion = lib.trivial.release;
|
||||
}
|
||||
);
|
||||
in
|
||||
{
|
||||
# Keep this around for easier debugging, e.g. with nix why-depends.
|
||||
inherit (machine) toplevel;
|
||||
|
||||
machine = stdenvNoCC.mkDerivation {
|
||||
name = "bashless-closure-machine";
|
||||
|
||||
__structuredAttrs = true;
|
||||
|
||||
exportReferencesGraph.closure = [ machine.toplevel ];
|
||||
|
||||
preferLocalBuild = true;
|
||||
|
||||
nativeBuildInputs = [
|
||||
jq
|
||||
];
|
||||
|
||||
buildCommand = ''
|
||||
set +e
|
||||
jq -r '.closure[].path' < "$NIX_ATTRS_JSON_FILE" | grep bash
|
||||
|
||||
exit_code=$?
|
||||
if [ $exit_code -eq 0 ]; then
|
||||
echo "Error: toplevel contains bash"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
touch $out
|
||||
'';
|
||||
};
|
||||
|
||||
initrd = stdenvNoCC.mkDerivation {
|
||||
name = "bashless-closure-initrd";
|
||||
|
||||
preferLocalBuild = true;
|
||||
|
||||
nativeBuildInputs = [
|
||||
zstd
|
||||
cpio
|
||||
];
|
||||
|
||||
buildCommand = ''
|
||||
set +e
|
||||
zstd -dfc ${machine.toplevel}/initrd | cpio --quiet -t | grep bash
|
||||
|
||||
exit_code=$?
|
||||
if [ $exit_code -eq 0 ]; then
|
||||
echo "Error: initrd contains bash"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
touch $out
|
||||
'';
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
# Tests a bashless image. The forbiddenDependenciesRegexes from the bashless
|
||||
# profile ensures that the closure doesn't contain any bash.
|
||||
|
||||
{ lib, ... }:
|
||||
|
||||
let
|
||||
storePartitionLabel = "root";
|
||||
in
|
||||
{
|
||||
|
||||
name = "activation-bashless-image";
|
||||
|
||||
meta.maintainers = with lib.maintainers; [ nikstur ];
|
||||
|
||||
nodes.machine =
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
modulesPath,
|
||||
...
|
||||
}:
|
||||
{
|
||||
imports = [
|
||||
"${modulesPath}/image/repart.nix"
|
||||
"${modulesPath}/profiles/bashless.nix"
|
||||
];
|
||||
|
||||
# Backdoor uses bash
|
||||
testing.backdoor = false;
|
||||
|
||||
virtualisation = {
|
||||
directBoot.enable = false;
|
||||
mountHostNixStore = false;
|
||||
useEFIBoot = true;
|
||||
};
|
||||
|
||||
boot.loader.grub.enable = false;
|
||||
|
||||
virtualisation.fileSystems = lib.mkForce {
|
||||
"/" = {
|
||||
fsType = "tmpfs";
|
||||
options = [ "mode=0755" ];
|
||||
};
|
||||
|
||||
"/nix/store" = {
|
||||
device = "/dev/disk/by-partlabel/${storePartitionLabel}";
|
||||
fsType = "erofs"; # Saves ~250MiB over ext4
|
||||
};
|
||||
};
|
||||
|
||||
image.repart = {
|
||||
name = "bashless-image";
|
||||
mkfsOptions = {
|
||||
erofs = [ "-z lz4" ]; # Saves ~150MiB over no compression
|
||||
};
|
||||
partitions = {
|
||||
"esp" = {
|
||||
contents = {
|
||||
"/EFI/BOOT/BOOT${lib.toUpper config.nixpkgs.hostPlatform.efiArch}.EFI".source =
|
||||
"${config.system.build.uki}/${config.system.boot.loader.ukiFile}";
|
||||
};
|
||||
repartConfig = {
|
||||
Type = "esp";
|
||||
Format = "vfat";
|
||||
SizeMinBytes = if config.nixpkgs.hostPlatform.isx86_64 then "64M" else "96M";
|
||||
};
|
||||
};
|
||||
"root" = {
|
||||
storePaths = [ config.system.build.toplevel ];
|
||||
nixStorePrefix = "/";
|
||||
repartConfig = {
|
||||
Type = "linux-generic";
|
||||
Format = config.fileSystems."/nix/store".fsType;
|
||||
Label = storePartitionLabel;
|
||||
Minimize = "best";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript =
|
||||
{ nodes, ... }:
|
||||
''
|
||||
import os
|
||||
import subprocess
|
||||
import tempfile
|
||||
|
||||
tmp_disk_image = tempfile.NamedTemporaryFile()
|
||||
|
||||
subprocess.run([
|
||||
"${nodes.machine.virtualisation.qemu.package}/bin/qemu-img",
|
||||
"create",
|
||||
"-f",
|
||||
"qcow2",
|
||||
"-b",
|
||||
"${nodes.machine.system.build.image}/${nodes.machine.image.fileName}",
|
||||
"-F",
|
||||
"raw",
|
||||
tmp_disk_image.name,
|
||||
])
|
||||
|
||||
# Set NIX_DISK_IMAGE so that the qemu script finds the right disk image.
|
||||
os.environ['NIX_DISK_IMAGE'] = tmp_disk_image.name
|
||||
|
||||
machine.start()
|
||||
machine.wait_for_console_text("Startup finished.")
|
||||
'';
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
# This is a smoke test that tests that basic functionality is still available
|
||||
# with the bashless profile. For this, however, we have to re-enable bash.
|
||||
|
||||
{ lib, ... }:
|
||||
|
||||
{
|
||||
|
||||
name = "activation-bashless";
|
||||
|
||||
meta.maintainers = with lib.maintainers; [ nikstur ];
|
||||
|
||||
nodes.machine =
|
||||
{ pkgs, modulesPath, ... }:
|
||||
{
|
||||
imports = [ "${modulesPath}/profiles/bashless.nix" ];
|
||||
|
||||
# Forcibly re-set options that would normally be set by the bashless
|
||||
# profile but that we have to re-enable to make the test instrumentation
|
||||
# work.
|
||||
environment.binsh = lib.mkForce null;
|
||||
boot.initrd.systemd.shell.enable = false;
|
||||
|
||||
# This ensures that we only have the store paths of our closure in the
|
||||
# in the guest. This is necessary so we can grep in the store.
|
||||
virtualisation.mountHostNixStore = false;
|
||||
virtualisation.useNixStoreImage = true;
|
||||
|
||||
# Re-enable just enough of a normal NixOS system to be able to run tests
|
||||
programs.bash.enable = true;
|
||||
environment.shell.enable = true;
|
||||
environment.systemPackages = [
|
||||
pkgs.coreutils
|
||||
pkgs.gnugrep
|
||||
];
|
||||
|
||||
# Unset the regex because the tests instrumentation needs bash.
|
||||
system.forbiddenDependenciesRegexes = lib.mkForce [ ];
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
machine.wait_for_unit("multi-user.target")
|
||||
|
||||
with subtest("/bin/sh doesn't exist"):
|
||||
machine.fail("stat /bin/sh")
|
||||
|
||||
bash_store_paths = machine.succeed("ls /nix/store | grep bash || true")
|
||||
print(bash_store_paths)
|
||||
'';
|
||||
|
||||
}
|
||||
@@ -186,6 +186,9 @@ in
|
||||
acme = import ./acme/default.nix { inherit runTest; };
|
||||
acme-dns = runTest ./acme-dns.nix;
|
||||
activation = pkgs.callPackage ../modules/system/activation/test.nix { };
|
||||
activation-bashless = runTest ./activation/bashless.nix;
|
||||
activation-bashless-closure = pkgs.callPackage ./activation/bashless-closure.nix { };
|
||||
activation-bashless-image = runTest ./activation/bashless-image.nix;
|
||||
activation-etc-overlay-immutable = runTest ./activation/etc-overlay-immutable.nix;
|
||||
activation-etc-overlay-mutable = runTest ./activation/etc-overlay-mutable.nix;
|
||||
activation-lib = pkgs.callPackage ../modules/system/activation/lib/test.nix { };
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
from subprocess import CalledProcessError, run
|
||||
from typing import Final, assert_never
|
||||
@@ -290,12 +289,7 @@ def execute(argv: list[str]) -> None:
|
||||
|
||||
# Re-exec to a newer version of the script before building to ensure we get
|
||||
# the latest fixes
|
||||
if (
|
||||
WITH_REEXEC
|
||||
and can_run
|
||||
and not args.no_reexec
|
||||
and not os.environ.get("_NIXOS_REBUILD_REEXEC")
|
||||
):
|
||||
if WITH_REEXEC and can_run and not args.no_reexec:
|
||||
services.reexec(argv, args, build_flags, flake_build_flags)
|
||||
|
||||
profile = Profile.from_arg(args.profile_name)
|
||||
|
||||
@@ -4,7 +4,6 @@ import logging
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from subprocess import CalledProcessError
|
||||
from typing import Final
|
||||
|
||||
from . import nix, tmpdir
|
||||
@@ -14,6 +13,7 @@ from .process import Remote, cleanup_ssh
|
||||
from .utils import Args, tabulate
|
||||
|
||||
NIXOS_REBUILD_ATTR: Final = "config.system.build.nixos-rebuild"
|
||||
NIXOS_REBUILD_REEXEC_ENV: Final = "_NIXOS_REBUILD_REEXEC"
|
||||
|
||||
logger: Final = logging.getLogger(__name__)
|
||||
logger.setLevel(logging.INFO)
|
||||
@@ -25,27 +25,26 @@ def reexec(
|
||||
build_flags: Args,
|
||||
flake_build_flags: Args,
|
||||
) -> None:
|
||||
if os.environ.get(NIXOS_REBUILD_REEXEC_ENV):
|
||||
return
|
||||
|
||||
drv = None
|
||||
try:
|
||||
# Parsing the args here but ignore ask_sudo_password since it is not
|
||||
# needed and we would end up asking sudo password twice
|
||||
if flake := Flake.from_arg(args.flake, Remote.from_arg(args.target_host, None)):
|
||||
drv = nix.build_flake(
|
||||
NIXOS_REBUILD_ATTR,
|
||||
flake,
|
||||
flake_build_flags | {"no_link": True},
|
||||
)
|
||||
else:
|
||||
build_attr = BuildAttr.from_arg(args.attr, args.file)
|
||||
drv = nix.build(
|
||||
NIXOS_REBUILD_ATTR,
|
||||
build_attr,
|
||||
build_flags | {"no_out_link": True},
|
||||
)
|
||||
except CalledProcessError:
|
||||
logger.warning(
|
||||
"could not build a newer version of nixos-rebuild, using current version",
|
||||
exc_info=logger.isEnabledFor(logging.DEBUG),
|
||||
# Parsing the args here but ignore ask_sudo_password since it is not
|
||||
# needed and we would end up asking sudo password twice
|
||||
if flake := Flake.from_arg(
|
||||
args.flake, Remote.from_arg(args.target_host, ask_sudo_password=None)
|
||||
):
|
||||
drv = nix.build_flake(
|
||||
NIXOS_REBUILD_ATTR,
|
||||
flake,
|
||||
flake_build_flags | {"no_link": True},
|
||||
)
|
||||
else:
|
||||
build_attr = BuildAttr.from_arg(args.attr, args.file)
|
||||
drv = nix.build(
|
||||
NIXOS_REBUILD_ATTR,
|
||||
build_attr,
|
||||
build_flags | {"no_out_link": True},
|
||||
)
|
||||
|
||||
if drv:
|
||||
@@ -62,7 +61,7 @@ def reexec(
|
||||
cleanup_ssh()
|
||||
tmpdir.TMPDIR.cleanup()
|
||||
try:
|
||||
os.execve(new, argv, os.environ | {"_NIXOS_REBUILD_REEXEC": "1"})
|
||||
os.execve(new, argv, os.environ | {NIXOS_REBUILD_REEXEC_ENV: "1"})
|
||||
except Exception:
|
||||
# Possible errors that we can have here:
|
||||
# - Missing the binary
|
||||
@@ -74,7 +73,7 @@ def reexec(
|
||||
)
|
||||
# We already run clean-up, let's re-exec in the current version
|
||||
# to avoid issues
|
||||
os.execve(current, argv, os.environ | {"_NIXOS_REBUILD_REEXEC": "1"})
|
||||
os.execve(current, argv, os.environ | {NIXOS_REBUILD_REEXEC_ENV: "1"})
|
||||
|
||||
|
||||
def _validate_image_variant(image_variant: str, variants: ImageVariants) -> None:
|
||||
|
||||
@@ -39,7 +39,7 @@ def test_reexec(mock_build: Mock, mock_execve: Mock, monkeypatch: MonkeyPatch) -
|
||||
mock_execve.assert_called_once_with(
|
||||
Path("/path/new/bin/nixos-rebuild-ng"),
|
||||
["/path/bin/nixos-rebuild-ng", "switch", "--no-flake"],
|
||||
{"_NIXOS_REBUILD_REEXEC": "1"},
|
||||
{s.NIXOS_REBUILD_REEXEC_ENV: "1"},
|
||||
)
|
||||
|
||||
mock_execve.reset_mock()
|
||||
@@ -50,7 +50,7 @@ def test_reexec(mock_build: Mock, mock_execve: Mock, monkeypatch: MonkeyPatch) -
|
||||
mock_execve.assert_any_call(
|
||||
Path("/path/bin/nixos-rebuild-ng"),
|
||||
["/path/bin/nixos-rebuild-ng", "switch", "--no-flake"],
|
||||
{"_NIXOS_REBUILD_REEXEC": "1"},
|
||||
{s.NIXOS_REBUILD_REEXEC_ENV: "1"},
|
||||
)
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ def test_reexec_flake(
|
||||
mock_execve.assert_called_once_with(
|
||||
Path("/path/new/bin/nixos-rebuild-ng"),
|
||||
["/path/bin/nixos-rebuild-ng", "switch", "--flake"],
|
||||
{"_NIXOS_REBUILD_REEXEC": "1"},
|
||||
{s.NIXOS_REBUILD_REEXEC_ENV: "1"},
|
||||
)
|
||||
|
||||
mock_execve.reset_mock()
|
||||
@@ -92,5 +92,18 @@ def test_reexec_flake(
|
||||
mock_execve.assert_any_call(
|
||||
Path("/path/bin/nixos-rebuild-ng"),
|
||||
["/path/bin/nixos-rebuild-ng", "switch", "--flake"],
|
||||
{"_NIXOS_REBUILD_REEXEC": "1"},
|
||||
{s.NIXOS_REBUILD_REEXEC_ENV: "1"},
|
||||
)
|
||||
|
||||
|
||||
@patch.dict(os.environ, {s.NIXOS_REBUILD_REEXEC_ENV: "1"}, clear=True)
|
||||
@patch("os.execve", autospec=True)
|
||||
@patch(get_qualified_name(s.nix.build_flake), autospec=True)
|
||||
def test_reexec_skip_if_already_reexec(mock_build: Mock, mock_execve: Mock) -> None:
|
||||
argv = ["/path/bin/nixos-rebuild-ng", "switch", "--flake"]
|
||||
args, _ = n.parse_args(argv)
|
||||
mock_build.return_value = Path("/path")
|
||||
|
||||
s.reexec(argv, args, {"build": True}, {"flake": True})
|
||||
mock_build.assert_not_called()
|
||||
mock_execve.assert_not_called()
|
||||
|
||||
@@ -16,18 +16,18 @@
|
||||
|
||||
rustPlatform.buildRustPackage (finalAttrs: {
|
||||
pname = "ruff";
|
||||
version = "0.13.1";
|
||||
version = "0.14.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "astral-sh";
|
||||
repo = "ruff";
|
||||
tag = finalAttrs.version;
|
||||
hash = "sha256-dCxCpJLG2qjfrMxDJOL4rCwdVYfrz3P+4kDQ9d9Mbus=";
|
||||
hash = "sha256-Vueccz5lkUTdgqqZl/+PB0kVYezvPKIVxee8EJYcz4g=";
|
||||
};
|
||||
|
||||
cargoBuildFlags = [ "--package=ruff" ];
|
||||
|
||||
cargoHash = "sha256-WtRryq8bmKfL3EL2kRFFokmG2f0lnS6zRMbUzGeYLDM=";
|
||||
cargoHash = "sha256-bnSTiQzlZrS2tqQiRHr6gNDq40Naqxrxcyc8zcVlt7A=";
|
||||
|
||||
nativeBuildInputs = [ installShellFiles ];
|
||||
|
||||
|
||||
@@ -25,23 +25,23 @@
|
||||
"lts": true
|
||||
},
|
||||
"6.6": {
|
||||
"version": "6.6.110",
|
||||
"hash": "sha256:07gv37ralrhf709plqj1hzk1adwilh6znmay6agpbf23anphvwhv",
|
||||
"version": "6.6.111",
|
||||
"hash": "sha256:1is6nrm5x54bw8zn8l5akp8ign185i19biks442yynfn63hp1i04",
|
||||
"lts": true
|
||||
},
|
||||
"6.12": {
|
||||
"version": "6.12.51",
|
||||
"hash": "sha256:08bj3b6a6jwvrpjl5sxvmzwwnc00clq98rjwb61fznd7khaasm9d",
|
||||
"version": "6.12.52",
|
||||
"hash": "sha256:1ccyd9h9i3xia1gqq0mggis5yv04c9ys44xp707wfcm0f3v0r1dl",
|
||||
"lts": true
|
||||
},
|
||||
"6.16": {
|
||||
"version": "6.16.11",
|
||||
"hash": "sha256:0yxsinhly689327jbvwm2nfr6cx7ynj9sd87a9var1rx8l64yc2z",
|
||||
"version": "6.16.12",
|
||||
"hash": "sha256:0vm257d76hmimnac8hzg66gd1mdg330sai39lywfn4m9bjydx93w",
|
||||
"lts": false
|
||||
},
|
||||
"6.17": {
|
||||
"version": "6.17.1",
|
||||
"hash": "sha256:182d9xf7j0n4cn61rsqs87al9xc83rawri8p3yk246a984zvwgd5",
|
||||
"version": "6.17.2",
|
||||
"hash": "sha256:0zzmcjkmxmcn45y20g8hz7dxs355rmczp9k8vjwc3xb5a03cpszx",
|
||||
"lts": false
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user