staging-nixos merge for 2026-02-26 (#494525)

This commit is contained in:
zowoq
2026-02-27 00:21:24 +00:00
committed by GitHub
23 changed files with 402 additions and 148 deletions
+25
View File
@@ -807,6 +807,31 @@ in
# Don't bother with certain units in containers.
systemd.services.systemd-remount-fs.unitConfig.ConditionVirtualization = "!container";
# When using the classic /etc mechanism, we set certain paths in /etc to
# /etc/static so that systemd cannot change them (as they are symlinks to
# the read-only Nix Store). This is only done so that these services cannot
# change the values. All other parts of systemd should read them from their
# canonical locations.
#
# If you use the overlay mechanism to manage /etc, this is unnecessary
# because either the overlay is mutable (and users can legitimately change
# values without them being overridden) or it is immutable and systemd will
# suggest to only make runtime changes.
systemd.services."systemd-localed".environment = lib.mkIf (!config.system.etc.overlay.enable) {
SYSTEMD_ETC_LOCALE_CONF = "/etc/static/locale.conf";
SYSTEMD_ETC_VCONSOLE_CONF = "/etc/static/vconsole.conf";
};
systemd.services."systemd-timedated".environment =
lib.mkIf (!config.system.etc.overlay.enable && config.time.timeZone != null)
{
SYSTEMD_ETC_LOCALTIME = "/etc/static/localtime";
SYSTEMD_ETC_ADJTIME = "/etc/static/adjtime";
};
systemd.services."systemd-hostnamed".environment = lib.mkIf (!config.system.etc.overlay.enable) {
SYSTEMD_ETC_HOSTNAME = "/etc/static/hostname";
SYSTEMD_ETC_MACHINE_INFO = "/etc/static/machine-info";
};
# Increase numeric PID range (set directly instead of copying a one-line file from systemd)
# https://github.com/systemd/systemd/pull/12226
boot.kernel.sysctl."kernel.pid_max" = mkIf pkgs.stdenv.hostPlatform.is64bit (lib.mkDefault 4194304);
+2 -2
View File
@@ -109,10 +109,10 @@
machine.wait_for_unit("first-boot-complete.target")
machine.succeed(
"journalctl --system -o cat --grep 'systemd ${lib.escapeRegex pkgs.systemd.version} running'"
"journalctl --system -o cat --grep 'systemd ${lib.escapeRegex nodes.machine.systemd.package.version} running'"
)
assert "systemd ${lib.versions.major pkgs.systemd.version} (${pkgs.systemd.version})" in machine.succeed(
assert "systemd ${lib.versions.major nodes.machine.systemd.package.version} (${nodes.machine.systemd.package.version})" in machine.succeed(
"systemctl --version"
)
+2 -2
View File
@@ -21,11 +21,11 @@
stdenv.mkDerivation (finalAttrs: {
pname = "btrfs-progs";
version = "6.17.1";
version = "6.19";
src = fetchurl {
url = "mirror://kernel/linux/kernel/people/kdave/btrfs-progs/btrfs-progs-v${finalAttrs.version}.tar.xz";
hash = "sha256-pL4Kbrs8R2Qn+12Xss8CewzNtrDFX/FjIzIMHoy3dlg=";
hash = "sha256-rWt5GmDrVj0zFLwY48R/awU6AyY5SItbCbnV55Id5rY=";
};
nativeBuildInputs = [
@@ -265,22 +265,21 @@ def parse_args(
if args.no_build_nix:
parser_warn("--no-build-nix is deprecated, we do not build nix anymore")
if args.diff and args.action not in (
# case for calling build_and_activate_system
# except excluding DRY_BUILD and DRY_ACTIVATE,
# in which --diff is uniquely a no-op
Action.SWITCH.value,
Action.BOOT.value,
Action.TEST.value,
Action.BUILD.value,
Action.BUILD_IMAGE.value,
Action.BUILD_VM.value,
Action.BUILD_VM_WITH_BOOTLOADER.value,
if (
args.action
in (
Action.DRY_BUILD.value, # --diff breaks dry-build
Action.EDIT.value,
Action.LIST_GENERATIONS.value,
Action.REPL.value,
)
and args.diff
):
parser_warn(f"--diff is a no-op with '{args.action}'")
args.diff = False
if args.action == Action.EDIT.value and (args.file or args.attr):
parser.error("--file and --attr are not supported with 'edit'")
parser.error(f"--file and --attr are not supported with '{args.action}'")
if (args.target_host or args.build_host) and args.action not in (
Action.SWITCH.value,
@@ -63,20 +63,6 @@ class BuildAttr:
return cls(Path(file or "default.nix"), attr)
def _get_hostname(target_host: Remote | None) -> str | None:
if target_host:
try:
return run_wrapper(
["uname", "-n"],
capture_output=True,
remote=target_host,
).stdout.strip()
except (AttributeError, subprocess.CalledProcessError):
return None
else:
return platform.node()
@dataclass(frozen=True)
class Flake:
path: str
@@ -95,9 +81,7 @@ class Flake:
m = cls._re.match(flake_str)
assert m is not None, f"got no matches for {flake_str}"
attr = m.group("attr")
nixos_attr = (
f'nixosConfigurations."{attr or _get_hostname(target_host) or "default"}"'
)
nixos_attr = f'nixosConfigurations."{attr or cls._get_hostname(target_host) or "default"}"'
path = m.group("path")
return cls(path, nixos_attr)
@@ -126,6 +110,20 @@ class Flake:
except FileNotFoundError:
return self.path
@staticmethod
def _get_hostname(target_host: Remote | None) -> str | None:
if target_host:
try:
return run_wrapper(
["uname", "-n"],
capture_output=True,
remote=target_host,
).stdout.strip()
except (AttributeError, subprocess.CalledProcessError):
return None
else:
return platform.node()
@dataclass(frozen=True)
class Generation:
@@ -25,7 +25,7 @@ from .models import (
Profile,
Remote,
)
from .process import SSH_DEFAULT_OPTS, run_wrapper
from .process import PRESERVE_ENV, SSH_DEFAULT_OPTS, run_wrapper
from .utils import Args, dict_to_flags
FLAKE_FLAGS: Final = ["--extra-experimental-features", "nix-command flakes"]
@@ -192,9 +192,7 @@ def copy_closure(
Also supports copying a closure from a remote to another remote."""
sshopts = os.getenv("NIX_SSHOPTS", "")
extra_env = {
"NIX_SSHOPTS": " ".join(filter(lambda x: x, [sshopts, *SSH_DEFAULT_OPTS]))
}
env = {"NIX_SSHOPTS": " ".join(filter(lambda x: x, [sshopts, *SSH_DEFAULT_OPTS]))}
def nix_copy_closure(host: Remote, to: bool) -> None:
run_wrapper(
@@ -205,7 +203,7 @@ def copy_closure(
host.host,
closure,
],
extra_env=extra_env,
env=env,
)
def nix_copy(to_host: Remote, from_host: Remote) -> None:
@@ -221,7 +219,7 @@ def copy_closure(
f"ssh://{to_host.host}",
closure,
],
extra_env=extra_env,
env=env,
)
match (to_host, from_host):
@@ -703,7 +701,11 @@ def switch_to_configuration(
run_wrapper(
[*cmd, path_to_config / "bin/switch-to-configuration", str(action)],
extra_env={"NIXOS_INSTALL_BOOTLOADER": "1" if install_bootloader else "0"},
env={
"LOCALE_ARCHIVE": PRESERVE_ENV,
"NIXOS_NO_CHECK": PRESERVE_ENV,
"NIXOS_INSTALL_BOOTLOADER": "1" if install_bootloader else "0",
},
remote=target_host,
sudo=sudo,
)
@@ -5,10 +5,11 @@ import os
import re
import shlex
import subprocess
from collections.abc import Sequence
from collections.abc import Mapping, Sequence
from dataclasses import dataclass
from enum import Enum
from ipaddress import AddressValueError, IPv6Address
from typing import Final, Self, TextIO, TypedDict, Unpack
from typing import Final, Literal, Self, TextIO, TypedDict, Unpack, override
from . import tmpdir
@@ -23,7 +24,30 @@ SSH_DEFAULT_OPTS: Final = [
"ControlPersist=60",
]
type Args = Sequence[str | bytes | os.PathLike[str] | os.PathLike[bytes]]
class _Env(Enum):
PRESERVE_ENV = "PRESERVE"
@override
def __repr__(self) -> str:
return self.value
PRESERVE_ENV: Final = _Env.PRESERVE_ENV
type Arg = str | bytes | os.PathLike[str] | os.PathLike[bytes]
type Args = Sequence[Arg]
type EnvValue = str | Literal[_Env.PRESERVE_ENV]
@dataclass(frozen=True)
class _RawShellArg:
value: str
@override
def __str__(self) -> str:
return self.value
@dataclass(frozen=True)
@@ -106,70 +130,84 @@ def run_wrapper(
args: Args,
*,
check: bool = True,
extra_env: dict[str, str] | None = None,
env: Mapping[str, EnvValue] | None = None,
remote: Remote | None = None,
sudo: bool = False,
**kwargs: Unpack[RunKwargs],
) -> subprocess.CompletedProcess[str]:
"Wrapper around `subprocess.run` that supports extra functionality."
env = None
process_input = None
run_args = args
run_args: list[Arg] = list(args)
final_args: list[Arg]
normalized_env = _normalize_env(env)
resolved_env = _resolve_env_local(normalized_env)
if remote:
if extra_env:
extra_env_args = [f"{env}={value}" for env, value in extra_env.items()]
args = ["env", *extra_env_args, *args]
# Apply env for the *remote command* (not for ssh itself)
remote_run_args: list[Arg | _RawShellArg] = []
remote_run_args.extend(run_args)
if normalized_env:
remote_run_args = _prefix_env_cmd_remote(run_args, normalized_env)
if sudo:
sudo_args = shlex.split(os.getenv("NIX_SUDOOPTS", ""))
if remote.sudo_password:
args = ["sudo", "--prompt=", "--stdin", *args]
remote_run_args = [
"sudo",
"--prompt=",
"--stdin",
*sudo_args,
*remote_run_args,
]
process_input = remote.sudo_password + "\n"
else:
args = ["sudo", *args]
run_args = [
remote_run_args = ["sudo", *sudo_args, *remote_run_args]
ssh_args: list[Arg] = [
"ssh",
*remote.opts,
*SSH_DEFAULT_OPTS,
remote.ssh_host(),
"--",
# SSH will join the parameters here and pass it to the shell, so we
# need to quote it to avoid issues.
# We can't use `shlex.join`, otherwise we will hit MAX_ARG_STRLEN
# limits when the command becomes too big.
*[shlex.quote(str(a)) for a in args],
*[_quote_remote_arg(a) for a in remote_run_args],
]
final_args = ssh_args
popen_env = None # keep ssh's environment normal
else:
if extra_env:
env = os.environ | extra_env
if sudo:
# subprocess.run(env=...) would affect sudo, but sudo may drop env
# for the target command.
# So we inject env via `sudo env ... cmd`.
if env is not None and resolved_env:
run_args = _prefix_env_cmd(run_args, resolved_env)
sudo_args = shlex.split(os.getenv("NIX_SUDOOPTS", ""))
# Using --preserve-env is less than ideal since it will cause
# the following warn during usage:
# > warning: $HOME ('/home/<user>') is not owned by you,
# > falling back to the one defined in the 'passwd' file ('/root')
# However, right now it is the only way to guarantee the semantics
# expected for the commands, e.g. activation with systemd-run
# expects access to environment variables like LOCALE_ARCHIVE,
# NIXOS_NO_CHECK.
# For now, for anyone that the above warn bothers you, please
# use `sudo nixos-rebuild` instead of `--sudo` flag.
run_args = ["sudo", "--preserve-env", *sudo_args, *run_args]
final_args = ["sudo", *sudo_args, *run_args]
# No need to pass env to subprocess.run; keep sudo's own env
# default.
popen_env = None
else:
# Non-sudo local: we can fully control the environment with
# subprocess.run(env=...)
final_args = run_args
popen_env = None if env is None else resolved_env
logger.debug(
"calling run with args=%r, kwargs=%r, extra_env=%r",
run_args,
"calling run with args=%r, kwargs=%r, env=%r",
_sanitize_env_run_args(remote_run_args if remote else run_args),
kwargs,
extra_env,
env,
)
try:
r = subprocess.run(
run_args,
final_args,
check=check,
env=env,
env=popen_env,
input=process_input,
# Hope nobody is using NixOS with non-UTF8 encodings, but
# "surrogateescape" should still work in those systems.
text=True,
errors="surrogateescape",
**kwargs,
@@ -195,13 +233,95 @@ def run_wrapper(
raise
# SSH does not send the signals to the process when running without usage of
# pseudo-TTY (that causes a whole other can of worms), so if the process is
# long running (e.g.: a build) this will result in the underlying process
# staying alive.
# See: https://stackoverflow.com/a/44354466
# Issue: https://github.com/NixOS/nixpkgs/issues/403269
def _resolve_env(env: Mapping[str, EnvValue] | None) -> dict[str, str]:
normalized = _normalize_env(env)
return _resolve_env_local(normalized)
def _normalize_env(env: Mapping[str, EnvValue] | None) -> dict[str, EnvValue]:
"""
Normalize env mapping, but preserve some environment variables by default.
"""
return {"PATH": PRESERVE_ENV, **(env or {})}
def _resolve_env_local(env: dict[str, EnvValue]) -> dict[str, str]:
"""
Resolve env mapping where values can be:
- PRESERVE_ENV: copy from current os.environ (if present)
- str: explicit value
"""
result: dict[str, str] = {}
for k, v in env.items():
if v == PRESERVE_ENV:
cur = os.environ.get(k)
if cur is not None:
result[k] = cur
else:
result[k] = v
return result
def _prefix_env_cmd(cmd: Sequence[Arg], resolved_env: dict[str, str]) -> list[Arg]:
"""
Prefix a command with `env -i K=V ... -- <cmd...>` to set vars for the
command.
"""
if not resolved_env:
return list(cmd)
assigns = [f"{k}={v}" for k, v in resolved_env.items()]
return ["env", "-i", *assigns, *cmd]
def _prefix_env_cmd_remote(
cmd: Args,
env: dict[str, EnvValue],
) -> list[Arg | _RawShellArg]:
"""
Prefix remote commands with env assignments. Preserve markers are expanded
by the remote shell at execution time.
"""
assigns: list[str | _RawShellArg] = []
for k, v in env.items():
if v is PRESERVE_ENV:
assigns.append(_RawShellArg(f"{k}=${{{k}-}}"))
else:
assigns.append(f"{k}={v}")
return ["env", "-i", *assigns, *cmd]
def _quote_remote_arg(arg: Arg | _RawShellArg) -> str:
if isinstance(arg, _RawShellArg):
return str(arg)
return shlex.quote(str(arg))
def _sanitize_env_run_args(run_args: list[Arg] | list[Arg | _RawShellArg]) -> list[Arg]:
"""
Sanitize long or sensitive environment variables from logs.
"""
sanitized: list[Arg] = []
for value in run_args:
if isinstance(value, str) and value.startswith("PATH="):
sanitized.append("PATH=<PATH>")
elif isinstance(value, str | bytes | os.PathLike):
sanitized.append(value)
else:
sanitized.append(str(value))
return sanitized
def _kill_long_running_ssh_process(args: Args, remote: Remote) -> None:
"""
SSH does not send the signals to the process when running without usage of
pseudo-TTY (that causes a whole other can of worms), so if the process is
long running (e.g.: a build) this will result in the underlying process
staying alive.
See: https://stackoverflow.com/a/44354466
Issue: https://github.com/NixOS/nixpkgs/issues/403269
"""
logger.info("cleaning-up remote process, please wait...")
# We need to escape both the shell and regex here (since pkill interprets
@@ -103,8 +103,7 @@ def _get_system_attr(
case Action.BUILD_IMAGE if flake:
variants = nix.get_build_image_variants_flake(
flake,
eval_flags=grouped_nix_args.flake_build_flags
| grouped_nix_args.flake_eval_flags,
eval_flags=grouped_nix_args.flake_eval_flags,
)
_validate_image_variant(args.image_variant, variants)
attr = f"config.system.build.images.{args.image_variant}"
@@ -264,8 +263,7 @@ def _activate_system(
image_name = nix.get_build_image_name_flake(
flake,
args.image_variant,
eval_flags=grouped_nix_args.flake_build_flags
| grouped_nix_args.flake_eval_flags,
eval_flags=grouped_nix_args.flake_eval_flags,
)
else:
image_name = nix.get_build_image_name(
@@ -248,7 +248,6 @@ def test_execute_nix_boot(mock_run: Mock, tmp_path: Path) -> None:
| {
"env": {
"NIXOS_INSTALL_BOOTLOADER": "0",
"NIXOS_REBUILD_I_UNDERSTAND_THE_CONSEQUENCES_PLEASE_BREAK_MY_SYSTEM": "1",
}
}
),
@@ -487,7 +486,6 @@ def test_execute_nix_switch_flake(mock_run: Mock, tmp_path: Path) -> None:
call(
[
"sudo",
"--preserve-env",
"nix-env",
"-p",
Path("/nix/var/nix/profiles/system"),
@@ -505,21 +503,15 @@ def test_execute_nix_switch_flake(mock_run: Mock, tmp_path: Path) -> None:
call(
[
"sudo",
"--preserve-env",
"env",
"-i",
"NIXOS_INSTALL_BOOTLOADER=1",
*nr.nix.SWITCH_TO_CONFIGURATION_CMD_PREFIX,
config_path / "bin/switch-to-configuration",
"switch",
],
check=True,
**(
DEFAULT_RUN_KWARGS
| {
"env": {
"NIXOS_INSTALL_BOOTLOADER": "1",
"NIXOS_REBUILD_I_UNDERSTAND_THE_CONSEQUENCES_PLEASE_BREAK_MY_SYSTEM": "1",
}
}
),
**DEFAULT_RUN_KWARGS,
),
]
)
@@ -625,6 +617,9 @@ def test_execute_nix_switch_build_target_host(
*nr.process.SSH_DEFAULT_OPTS,
"user@build-host",
"--",
"env",
"-i",
"PATH=${PATH-}",
"mktemp",
"-d",
"-t",
@@ -640,6 +635,9 @@ def test_execute_nix_switch_build_target_host(
*nr.process.SSH_DEFAULT_OPTS,
"user@build-host",
"--",
"env",
"-i",
"PATH=${PATH-}",
"nix-store",
"--realise",
str(config_path),
@@ -656,6 +654,9 @@ def test_execute_nix_switch_build_target_host(
*nr.process.SSH_DEFAULT_OPTS,
"user@build-host",
"--",
"env",
"-i",
"PATH=${PATH-}",
"readlink",
"-f",
"/tmp/tmpdir/config",
@@ -670,6 +671,9 @@ def test_execute_nix_switch_build_target_host(
*nr.process.SSH_DEFAULT_OPTS,
"user@build-host",
"--",
"env",
"-i",
"PATH=${PATH-}",
"rm",
"-rf",
"/tmp/tmpdir",
@@ -699,6 +703,9 @@ def test_execute_nix_switch_build_target_host(
"user@target-host",
"--",
"sudo",
"env",
"-i",
"PATH=${PATH-}",
"nix-env",
"-p",
"/nix/var/nix/profiles/system",
@@ -714,6 +721,9 @@ def test_execute_nix_switch_build_target_host(
*nr.process.SSH_DEFAULT_OPTS,
"user@target-host",
"--",
"env",
"-i",
"PATH=${PATH-}",
"test",
"-d",
"/run/systemd/system",
@@ -729,6 +739,10 @@ def test_execute_nix_switch_build_target_host(
"--",
"sudo",
"env",
"-i",
"PATH=${PATH-}",
"LOCALE_ARCHIVE=${LOCALE_ARCHIVE-}",
"NIXOS_NO_CHECK=${NIXOS_NO_CHECK-}",
"NIXOS_INSTALL_BOOTLOADER=0",
*nr.nix.SWITCH_TO_CONFIGURATION_CMD_PREFIX,
str(config_path / "bin/switch-to-configuration"),
@@ -806,6 +820,9 @@ def test_execute_nix_switch_flake_target_host(
"user@localhost",
"--",
"sudo",
"env",
"-i",
"PATH=${PATH-}",
"nix-env",
"-p",
"/nix/var/nix/profiles/system",
@@ -821,6 +838,9 @@ def test_execute_nix_switch_flake_target_host(
*nr.process.SSH_DEFAULT_OPTS,
"user@localhost",
"--",
"env",
"-i",
"PATH=${PATH-}",
"test",
"-d",
"/run/systemd/system",
@@ -836,6 +856,10 @@ def test_execute_nix_switch_flake_target_host(
"--",
"sudo",
"env",
"-i",
"PATH=${PATH-}",
"LOCALE_ARCHIVE=${LOCALE_ARCHIVE-}",
"NIXOS_NO_CHECK=${NIXOS_NO_CHECK-}",
"NIXOS_INSTALL_BOOTLOADER=0",
*nr.nix.SWITCH_TO_CONFIGURATION_CMD_PREFIX,
str(config_path / "bin/switch-to-configuration"),
@@ -912,6 +936,9 @@ def test_execute_nix_switch_flake_build_host(
*nr.process.SSH_DEFAULT_OPTS,
"user@localhost",
"--",
"env",
"-i",
"PATH=${PATH-}",
"nix",
"--extra-experimental-features",
"'nix-command flakes'",
@@ -1121,6 +1148,9 @@ def test_execute_build_dry_run_build_and_target_remote(
*nr.process.SSH_DEFAULT_OPTS,
"user@build-host",
"--",
"env",
"-i",
"PATH=${PATH-}",
"nix",
"--extra-experimental-features",
"'nix-command flakes'",
@@ -1304,7 +1334,6 @@ def test_execute_switch_store_path(mock_run: Mock, tmp_path: Path) -> None:
| {
"env": {
"NIXOS_INSTALL_BOOTLOADER": "0",
"NIXOS_REBUILD_I_UNDERSTAND_THE_CONSEQUENCES_PLEASE_BREAK_MY_SYSTEM": "1",
}
}
),
@@ -1354,6 +1383,9 @@ def test_execute_switch_store_path_target_host(
*nr.process.SSH_DEFAULT_OPTS,
"user@remote-host",
"--",
"env",
"-i",
"PATH=${PATH-}",
"test",
"-f",
str(config_path / "nixos-version"),
@@ -1368,6 +1400,9 @@ def test_execute_switch_store_path_target_host(
"user@remote-host",
"--",
"sudo",
"env",
"-i",
"PATH=${PATH-}",
"nix-env",
"-p",
"/nix/var/nix/profiles/system",
@@ -1383,6 +1418,9 @@ def test_execute_switch_store_path_target_host(
*nr.process.SSH_DEFAULT_OPTS,
"user@remote-host",
"--",
"env",
"-i",
"PATH=${PATH-}",
"test",
"-d",
"/run/systemd/system",
@@ -1398,6 +1436,10 @@ def test_execute_switch_store_path_target_host(
"--",
"sudo",
"env",
"-i",
"PATH=${PATH-}",
"LOCALE_ARCHIVE=${LOCALE_ARCHIVE-}",
"NIXOS_NO_CHECK=${NIXOS_NO_CHECK-}",
"NIXOS_INSTALL_BOOTLOADER=0",
*nr.nix.SWITCH_TO_CONFIGURATION_CMD_PREFIX,
str(config_path / "bin/switch-to-configuration"),
@@ -134,9 +134,7 @@ def test_build_remote(
"user@host",
Path("/path/to/file"),
],
extra_env={
"NIX_SSHOPTS": " ".join(["--ssh opts", *p.SSH_DEFAULT_OPTS])
},
env={"NIX_SSHOPTS": " ".join(["--ssh opts", *p.SSH_DEFAULT_OPTS])},
),
call(
["mktemp", "-d", "-t", "nixos-rebuild.XXXXX"],
@@ -208,9 +206,7 @@ def test_build_remote_flake(
"user@host",
Path("/path/to/file"),
],
extra_env={
"NIX_SSHOPTS": " ".join(["--ssh opts", *p.SSH_DEFAULT_OPTS])
},
env={"NIX_SSHOPTS": " ".join(["--ssh opts", *p.SSH_DEFAULT_OPTS])},
),
call(
[
@@ -241,7 +237,7 @@ def test_copy_closure(monkeypatch: MonkeyPatch) -> None:
n.copy_closure(closure, target_host)
mock_run.assert_called_with(
["nix-copy-closure", "--to", "user@target.host", closure],
extra_env={"NIX_SSHOPTS": " ".join(p.SSH_DEFAULT_OPTS)},
env={"NIX_SSHOPTS": " ".join(p.SSH_DEFAULT_OPTS)},
)
monkeypatch.setenv("NIX_SSHOPTS", "--ssh build-opt")
@@ -249,15 +245,11 @@ def test_copy_closure(monkeypatch: MonkeyPatch) -> None:
n.copy_closure(closure, None, build_host, {"copy_flag": True})
mock_run.assert_called_with(
["nix-copy-closure", "--copy-flag", "--from", "user@build.host", closure],
extra_env={
"NIX_SSHOPTS": " ".join(["--ssh build-opt", *p.SSH_DEFAULT_OPTS])
},
env={"NIX_SSHOPTS": " ".join(["--ssh build-opt", *p.SSH_DEFAULT_OPTS])},
)
monkeypatch.setenv("NIX_SSHOPTS", "--ssh build-target-opt")
extra_env = {
"NIX_SSHOPTS": " ".join(["--ssh build-target-opt", *p.SSH_DEFAULT_OPTS])
}
env = {"NIX_SSHOPTS": " ".join(["--ssh build-target-opt", *p.SSH_DEFAULT_OPTS])}
with patch(get_qualified_name(n.run_wrapper, n), autospec=True) as mock_run:
n.copy_closure(closure, target_host, build_host, {"copy_flag": True})
mock_run.assert_called_with(
@@ -273,7 +265,7 @@ def test_copy_closure(monkeypatch: MonkeyPatch) -> None:
"ssh://user@target.host",
closure,
],
extra_env=extra_env,
env=env,
)
@@ -723,7 +715,11 @@ def test_switch_to_configuration_without_systemd_run(
)
mock_run.assert_called_with(
[profile_path / "bin/switch-to-configuration", "switch"],
extra_env={"NIXOS_INSTALL_BOOTLOADER": "0"},
env={
"LOCALE_ARCHIVE": p.PRESERVE_ENV,
"NIXOS_NO_CHECK": p.PRESERVE_ENV,
"NIXOS_INSTALL_BOOTLOADER": "0",
},
sudo=False,
remote=None,
)
@@ -760,7 +756,11 @@ def test_switch_to_configuration_without_systemd_run(
config_path / "specialisation/special/bin/switch-to-configuration",
"test",
],
extra_env={"NIXOS_INSTALL_BOOTLOADER": "1"},
env={
"LOCALE_ARCHIVE": p.PRESERVE_ENV,
"NIXOS_NO_CHECK": p.PRESERVE_ENV,
"NIXOS_INSTALL_BOOTLOADER": "1",
},
sudo=True,
remote=target_host,
)
@@ -791,7 +791,11 @@ def test_switch_to_configuration_with_systemd_run(
profile_path / "bin/switch-to-configuration",
"switch",
],
extra_env={"NIXOS_INSTALL_BOOTLOADER": "0"},
env={
"LOCALE_ARCHIVE": p.PRESERVE_ENV,
"NIXOS_NO_CHECK": p.PRESERVE_ENV,
"NIXOS_INSTALL_BOOTLOADER": "0",
},
sudo=False,
remote=None,
)
@@ -816,7 +820,11 @@ def test_switch_to_configuration_with_systemd_run(
config_path / "specialisation/special/bin/switch-to-configuration",
"test",
],
extra_env={"NIXOS_INSTALL_BOOTLOADER": "1"},
env={
"LOCALE_ARCHIVE": p.PRESERVE_ENV,
"NIXOS_NO_CHECK": p.PRESERVE_ENV,
"NIXOS_INSTALL_BOOTLOADER": "1",
},
sudo=True,
remote=target_host,
)
@@ -7,6 +7,7 @@ import nixos_rebuild.models as m
import nixos_rebuild.process as p
@patch.dict(p.os.environ, {"PATH": "/path/to/bin"}, clear=True)
@patch("subprocess.run", autospec=True)
def test_run(mock_run: Any) -> None:
p.run_wrapper(["test", "--with", "flags"], check=True)
@@ -19,22 +20,27 @@ def test_run(mock_run: Any) -> None:
input=None,
)
with patch.dict(p.os.environ, {"PATH": "/path/to/bin"}, clear=True):
p.run_wrapper(
["test", "--with", "flags"],
check=False,
sudo=True,
extra_env={"FOO": "bar"},
)
p.run_wrapper(
["test", "--with", "flags"],
check=False,
sudo=True,
env={"FOO": "bar"},
)
mock_run.assert_called_with(
["sudo", "--preserve-env", "test", "--with", "flags"],
[
"sudo",
"env",
"-i",
"PATH=/path/to/bin",
"FOO=bar",
"test",
"--with",
"flags",
],
check=False,
text=True,
errors="surrogateescape",
env={
"PATH": "/path/to/bin",
"FOO": "bar",
},
env=None,
input=None,
)
@@ -51,6 +57,9 @@ def test_run(mock_run: Any) -> None:
*p.SSH_DEFAULT_OPTS,
"user@localhost",
"--",
"env",
"-i",
"PATH=${PATH-}",
"test",
"--with",
"'some flags'",
@@ -66,7 +75,7 @@ def test_run(mock_run: Any) -> None:
["test", "--with", "flags"],
check=True,
sudo=True,
extra_env={"FOO": "bar"},
env={"FOO": "bar"},
remote=m.Remote("user@localhost", ["--ssh", "opt"], "password"),
)
mock_run.assert_called_with(
@@ -81,6 +90,8 @@ def test_run(mock_run: Any) -> None:
"--prompt=",
"--stdin",
"env",
"-i",
"PATH=${PATH-}",
"FOO=bar",
"test",
"--with",
@@ -164,14 +175,57 @@ def test_ssh_host() -> None:
@patch("subprocess.run", autospec=True)
def test_custom_sudo_args(mock_run: Any) -> None:
with patch.dict(p.os.environ, {"NIX_SUDOOPTS": "--custom foo --args"}):
with patch.dict(
p.os.environ,
{"NIX_SUDOOPTS": "--custom foo --args", "PATH": "/path/to/bin"},
clear=True,
):
p.run_wrapper(
["test"],
check=False,
sudo=True,
)
mock_run.assert_called_with(
["sudo", "--preserve-env", "--custom", "foo", "--args", "test"],
[
"sudo",
"--custom",
"foo",
"--args",
"test",
],
check=False,
env=None,
input=None,
text=True,
errors="surrogateescape",
)
with patch.dict(
p.os.environ,
{"NIX_SUDOOPTS": "--custom foo --args", "PATH": "/path/to/bin"},
clear=True,
):
p.run_wrapper(
["test"],
check=False,
sudo=True,
remote=m.Remote("user@localhost", [], None),
)
mock_run.assert_called_with(
[
"ssh",
*p.SSH_DEFAULT_OPTS,
"user@localhost",
"--",
"sudo",
"--custom",
"foo",
"--args",
"env",
"-i",
"PATH=${PATH-}",
"test",
],
check=False,
env=None,
input=None,
+3 -3
View File
@@ -16,18 +16,18 @@
rustPlatform.buildRustPackage (finalAttrs: {
pname = "ruff";
version = "0.15.1";
version = "0.15.3";
src = fetchFromGitHub {
owner = "astral-sh";
repo = "ruff";
tag = finalAttrs.version;
hash = "sha256-Bj4ATRVYrKqigISNiDvgjUw4MLMwfgdID8MqaiVxz0g=";
hash = "sha256-xeZk044anJ21uQwV3VN1QOvav+soYVdArpEw/rr8Xsw=";
};
cargoBuildFlags = [ "--package=ruff" ];
cargoHash = "sha256-IF60aGv56Kh+wDYyN7XzLBywepvAxv2HMqSOz+Su2b4=";
cargoHash = "sha256-16Ao1y0pFWxGjHkGi4VCIA9msvA5Tka8wvok8o3g6rc=";
nativeBuildInputs = [ installShellFiles ];
@@ -9,6 +9,5 @@ For more information on what happens during a switch, see [what-happens-during-a
```
cd ./pkgs/by-name/sw/switch-to-configuration-ng
nix-shell ../../../.. -A switch-to-configuration-ng
cd ./src
cargo build
```
@@ -12,9 +12,9 @@ rustPlatform.buildRustPackage {
pname = "switch-to-configuration";
version = "0.1.0";
src = ./src;
src = builtins.filterSource (name: _: !(lib.hasSuffix ".nix" name)) ./.;
cargoLock.lockFile = ./src/Cargo.lock;
cargoLock.lockFile = ./Cargo.lock;
nativeBuildInputs = [ pkg-config ];
buildInputs = [ dbus ];
+2 -2
View File
@@ -11,14 +11,14 @@
}:
stdenv.mkDerivation (finalAttrs: {
version = "5.6.5";
version = "5.6.6";
pname = "whois";
src = fetchFromGitHub {
owner = "rfc1036";
repo = "whois";
rev = "v${finalAttrs.version}";
hash = "sha256-zCaM3fMittoEzuMRELqc1ES8QPgZRXVjyHUfMsS5tJA=";
hash = "sha256-RKiXQJoyy3wd/KXphhgjikdmIHl8nmjEzibjk5FKpBQ=";
};
patches = [
@@ -20,7 +20,7 @@ buildPythonPackage {
# Do not rely on path lookup at runtime to find the ruff binary.
# Use the propagated binary instead.
''
substituteInPlace python/ruff/__main__.py \
substituteInPlace python/ruff/_find_ruff.py \
--replace-fail \
'ruff_exe = "ruff" + sysconfig.get_config_var("EXE")' \
'return "${lib.getExe ruff}"'
@@ -30,13 +30,13 @@
"lts": true
},
"6.18": {
"version": "6.18.13",
"hash": "sha256:0zv8qml075jpk2i58cxp61hm3yb74mpkbkjg15n87riqzmakqb7d",
"lts": false
"version": "6.18.14",
"hash": "sha256:1f3wv9vdg43cy1lnqd60zqgki6px67mdhfkfnpk1npqq5akk86cd",
"lts": true
},
"6.19": {
"version": "6.19.3",
"hash": "sha256:1glf369wfr66lmv9wmijin6idlfgijfsh0gx2qly7gpwmml4jiqf",
"version": "6.19.4",
"hash": "sha256:1b68i7z91fbs1zayzzzf71g9ilfk0wi2fr8nralha60xq723p6r7",
"lts": false
}
}
+10 -1
View File
@@ -596,7 +596,10 @@ stdenv.mkDerivation rec {
echo 'echo "Compile grub2 with { kbdcompSupport = true; } to enable support for this command."' >> util/grub-kbdcomp.in
'';
depsBuildBuild = [ buildPackages.stdenv.cc ];
depsBuildBuild = [
buildPackages.stdenv.cc
pkg-config
];
nativeBuildInputs = [
bison
flex
@@ -661,6 +664,12 @@ stdenv.mkDerivation rec {
./bootstrap --no-git --gnulib-srcdir=${gnulib}
substituteInPlace ./configure --replace '/usr/share/fonts/unifont' '${unifont}/share/fonts'
''
# build-grub-mkfont is built & run during build, need to find freetype for buildPlatform
+ lib.optionalString (!lib.systems.equals stdenv.buildPlatform stdenv.hostPlatform) ''
configureFlagsArray+=(
"BUILD_PKG_CONFIG=$PKG_CONFIG_FOR_BUILD"
)
'';
postConfigure = ''