Unverified Commit 66fd6610 authored by Thiago Kenji Okada's avatar Thiago Kenji Okada Committed by GitHub
Browse files

nixos-rebuild-ng: add --no-reexec flag, deprecate --fast (#377957)

parents 979b8053 79a33d9e
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -17,11 +17,12 @@ nixos-rebuild - reconfigure a NixOS machine

# SYNOPSIS

; document here only non-deprecated flags
_nixos-rebuild_ \[--verbose] [--max-jobs MAX_JOBS] [--cores CORES] [--log-format LOG_FORMAT] [--keep-going] [--keep-failed] [--fallback] [--repair] [--option OPTION OPTION] [--builders BUILDERS]++
	\[--include INCLUDE] [--quiet] [--print-build-logs] [--show-trace] [--accept-flake-config] [--refresh] [--impure] [--offline] [--no-net] [--recreate-lock-file]++
	\[--no-update-lock-file] [--no-write-lock-file] [--no-registries] [--commit-lock-file] [--update-input UPDATE_INPUT] [--override-input OVERRIDE_INPUT OVERRIDE_INPUT]++
	\[--no-build-output] [--use-substitutes] [--help] [--file FILE] [--attr ATTR] [--flake [FLAKE]] [--no-flake] [--install-bootloader] [--profile-name PROFILE_NAME]++
	\[--specialisation SPECIALISATION] [--rollback] [--upgrade] [--upgrade-all] [--json] [--ask-sudo-password] [--sudo] [--fast]++
	\[--specialisation SPECIALISATION] [--rollback] [--upgrade] [--upgrade-all] [--json] [--ask-sudo-password] [--sudo] [--no-reexec]++
	\[--image-variant VARIANT]++
	\[--build-host BUILD_HOST] [--target-host TARGET_HOST]++
	\[{switch,boot,test,build,edit,repl,dry-build,dry-run,dry-activate,build-image,build-vm,build-vm-with-bootloader,list-generations}]
@@ -170,7 +171,7 @@ It must be one of the following:
	Causes the boot loader to be (re)installed on the device specified by
	the relevant configuration options.

*--fast*
*--no-reexec*
	Normally, *nixos-rebuild* first finds and builds itself from the
	_config.system.build.nixos-rebuild_ attribute from the current user
	channel or flake and exec into it. This allows *nixos-rebuild* to run
+20 −15
Original line number Diff line number Diff line
@@ -18,7 +18,7 @@ logger.setLevel(logging.INFO)


def get_parser() -> tuple[argparse.ArgumentParser, dict[str, argparse.ArgumentParser]]:
    common_flags = argparse.ArgumentParser(add_help=False)
    common_flags = argparse.ArgumentParser(add_help=False, allow_abbrev=False)
    common_flags.add_argument(
        "--verbose",
        "-v",
@@ -37,13 +37,13 @@ def get_parser() -> tuple[argparse.ArgumentParser, dict[str, argparse.ArgumentPa
    common_flags.add_argument("--repair", action="store_true")
    common_flags.add_argument("--option", nargs=2, action="append")

    common_build_flags = argparse.ArgumentParser(add_help=False)
    common_build_flags = argparse.ArgumentParser(add_help=False, allow_abbrev=False)
    common_build_flags.add_argument("--builders")
    common_build_flags.add_argument("--include", "-I", action="append")
    common_build_flags.add_argument("--print-build-logs", "-L", action="store_true")
    common_build_flags.add_argument("--show-trace", action="store_true")

    flake_common_flags = argparse.ArgumentParser(add_help=False)
    flake_common_flags = argparse.ArgumentParser(add_help=False, allow_abbrev=False)
    flake_common_flags.add_argument("--accept-flake-config", action="store_true")
    flake_common_flags.add_argument("--refresh", action="store_true")
    flake_common_flags.add_argument("--impure", action="store_true")
@@ -57,10 +57,10 @@ def get_parser() -> tuple[argparse.ArgumentParser, dict[str, argparse.ArgumentPa
    flake_common_flags.add_argument("--update-input", action="append")
    flake_common_flags.add_argument("--override-input", nargs=2, action="append")

    classic_build_flags = argparse.ArgumentParser(add_help=False)
    classic_build_flags = argparse.ArgumentParser(add_help=False, allow_abbrev=False)
    classic_build_flags.add_argument("--no-build-output", "-Q", action="store_true")

    copy_flags = argparse.ArgumentParser(add_help=False)
    copy_flags = argparse.ArgumentParser(add_help=False, allow_abbrev=False)
    copy_flags.add_argument(
        "--use-substitutes",
        "--substitute-on-destination",
@@ -166,10 +166,15 @@ def get_parser() -> tuple[argparse.ArgumentParser, dict[str, argparse.ArgumentPa
        help="Deprecated, use '--sudo' instead",
    )
    main_parser.add_argument("--no-ssh-tty", action="store_true", help="Deprecated")
    main_parser.add_argument(
        "--no-reexec",
        action="store_true",
        help="Do not update nixos-rebuild in-place (also known as re-exec) before build",
    )
    main_parser.add_argument(
        "--fast",
        action="store_true",
        help="Skip possibly expensive operations",
        help="Deprecated, use '--no-reexec' instead",
    )
    main_parser.add_argument("--build-host", help="Specifies host to perform the build")
    main_parser.add_argument(
@@ -223,23 +228,23 @@ def parse_args(
    if args.ask_sudo_password:
        args.sudo = True

    # TODO: use deprecated=True in Python >=3.13
    if args.install_grub:
        parser_warn("--install-grub deprecated, use --install-bootloader instead")
        parser_warn("--install-grub is deprecated, use --install-bootloader instead")
        args.install_bootloader = True

    # TODO: use deprecated=True in Python >=3.13
    if args.use_remote_sudo:
        parser_warn("--use-remote-sudo deprecated, use --sudo instead")
        parser_warn("--use-remote-sudo is deprecated, use --sudo instead")
        args.sudo = True

    # TODO: use deprecated=True in Python >=3.13
    if args.fast:
        parser_warn("--fast is deprecated, use --no-reexec instead")
        args.no_reexec = True

    if args.no_ssh_tty:
        parser_warn("--no-ssh-tty deprecated, SSH's TTY is never used anymore")
        parser_warn("--no-ssh-tty is deprecated, SSH's TTY is never used anymore")

    # TODO: use deprecated=True in Python >=3.13
    if args.no_build_nix:
        parser_warn("--no-build-nix deprecated, we do not build nix anymore")
        parser_warn("--no-build-nix is deprecated, we do not build nix anymore")

    if args.action == Action.EDIT.value and (args.file or args.attr):
        parser.error("--file and --attr are not supported with 'edit'")
@@ -351,7 +356,7 @@ def execute(argv: list[str]) -> None:
    if (
        WITH_REEXEC
        and can_run
        and not args.fast
        and not args.no_reexec
        and not os.environ.get("_NIXOS_REBUILD_REEXEC")
    ):
        reexec(argv, args, build_flags, flake_build_flags)
+9 −9
Original line number Diff line number Diff line
@@ -144,7 +144,7 @@ def test_execute_nix_boot(mock_run: Any, tmp_path: Path) -> None:

    mock_run.side_effect = run_side_effect

    nr.execute(["nixos-rebuild", "boot", "--no-flake", "-vvv", "--fast"])
    nr.execute(["nixos-rebuild", "boot", "--no-flake", "-vvv", "--no-reexec"])

    assert mock_run.call_count == 6
    mock_run.assert_has_calls(
@@ -222,7 +222,7 @@ def test_execute_nix_build_vm(mock_run: Any, tmp_path: Path) -> None:
            "nixos-config=./configuration.nix",
            "-I",
            "nixpkgs=$HOME/.nix-defexpr/channels/pinned_nixpkgs",
            "--fast",
            "--no-reexec",
        ]
    )

@@ -340,7 +340,7 @@ def test_execute_nix_switch_flake(mock_run: Any, tmp_path: Path) -> None:
            "--install-bootloader",
            "--sudo",
            "--verbose",
            "--fast",
            "--no-reexec",
            # https://github.com/NixOS/nixpkgs/issues/374050
            "--option",
            "narinfo-cache-negative-ttl",
@@ -418,7 +418,7 @@ def test_execute_nix_switch_flake_target_host(
            "--use-remote-sudo",
            "--target-host",
            "user@localhost",
            "--fast",
            "--no-reexec",
        ]
    )

@@ -508,7 +508,7 @@ def test_execute_nix_switch_flake_build_host(
            "/path/to/config#hostname",
            "--build-host",
            "user@localhost",
            "--fast",
            "--no-reexec",
        ]
    )

@@ -587,7 +587,7 @@ def test_execute_switch_rollback(mock_run: Any, tmp_path: Path) -> None:
    nixpkgs_path.touch()

    nr.execute(
        ["nixos-rebuild", "switch", "--rollback", "--install-bootloader", "--fast"]
        ["nixos-rebuild", "switch", "--rollback", "--install-bootloader", "--no-reexec"]
    )

    assert mock_run.call_count >= 2
@@ -625,7 +625,7 @@ def test_execute_build(mock_run: Any, tmp_path: Path) -> None:
        CompletedProcess([], 0, str(config_path)),
    ]

    nr.execute(["nixos-rebuild", "build", "--no-flake", "--fast"])
    nr.execute(["nixos-rebuild", "build", "--no-flake", "--no-reexec"])

    assert mock_run.call_count == 1
    mock_run.assert_has_calls(
@@ -659,7 +659,7 @@ def test_execute_test_flake(mock_run: Any, tmp_path: Path) -> None:
    mock_run.side_effect = run_side_effect

    nr.execute(
        ["nixos-rebuild", "test", "--flake", "github:user/repo#hostname", "--fast"]
        ["nixos-rebuild", "test", "--flake", "github:user/repo#hostname", "--no-reexec"]
    )

    assert mock_run.call_count == 2
@@ -712,7 +712,7 @@ def test_execute_test_rollback(
    mock_run.side_effect = run_side_effect

    nr.execute(
        ["nixos-rebuild", "test", "--rollback", "--profile-name", "foo", "--fast"]
        ["nixos-rebuild", "test", "--rollback", "--profile-name", "foo", "--no-reexec"]
    )

    assert mock_run.call_count == 2
+12 −12
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@ from .helpers import get_qualified_name
    autospec=True,
    return_value=CompletedProcess([], 0, stdout=" \n/path/to/file\n "),
)
def test_build(mock_run: Any, monkeypatch: Any) -> None:
def test_build(mock_run: Any) -> None:
    assert n.build(
        "config.system.build.attr",
        m.BuildAttr("<nixpkgs/nixos>", None),
@@ -79,7 +79,7 @@ def test_build_flake(mock_run: Any, monkeypatch: MonkeyPatch, tmpdir: Path) -> N

@patch(get_qualified_name(n.run_wrapper, n), autospec=True)
@patch(get_qualified_name(n.uuid4, n), autospec=True)
def test_build_remote(mock_uuid4: Any, mock_run: Any, monkeypatch: Any) -> None:
def test_build_remote(mock_uuid4: Any, mock_run: Any, monkeypatch: MonkeyPatch) -> None:
    build_host = m.Remote("user@host", [], None)
    monkeypatch.setenv("NIX_SSHOPTS", "--ssh opts")

@@ -226,7 +226,7 @@ def test_build_remote_flake(
    )


def test_copy_closure(monkeypatch: Any) -> None:
def test_copy_closure(monkeypatch: MonkeyPatch) -> None:
    closure = Path("/path/to/closure")
    with patch(get_qualified_name(n.run_wrapper, n), autospec=True) as mock_run:
        n.copy_closure(closure, None)
@@ -290,7 +290,7 @@ def test_copy_closure(monkeypatch: Any) -> None:


@patch(get_qualified_name(n.run_wrapper, n), autospec=True)
def test_edit(mock_run: Any, monkeypatch: Any, tmpdir: Any) -> None:
def test_edit(mock_run: Any, monkeypatch: MonkeyPatch, tmpdir: Path) -> None:
    # Flake
    flake = m.Flake.parse(f"{tmpdir}#attr")
    n.edit(flake, {"commit_lock_file": True})
@@ -309,8 +309,8 @@ def test_edit(mock_run: Any, monkeypatch: Any, tmpdir: Any) -> None:

    # Classic
    with monkeypatch.context() as mp:
        default_nix = tmpdir.join("default.nix")
        default_nix.write("{}")
        default_nix = tmpdir / "default.nix"
        default_nix.write_text("{}", encoding="utf-8")

        mp.setenv("NIXOS_CONFIG", str(tmpdir))
        mp.setenv("EDITOR", "editor")
@@ -333,7 +333,7 @@ def test_edit(mock_run: Any, monkeypatch: Any, tmpdir: Any) -> None:
        """,
    ),
)
def test_get_build_image_variants(mock_run: Any) -> None:
def test_get_build_image_variants(mock_run: Any, tmp_path: Path) -> None:
    build_attr = m.BuildAttr("<nixpkgs/nixos>", None)
    assert n.get_build_image_variants(build_attr) == {
        "azure": "nixos-image-azure-25.05.20250102.6df2492-x86_64-linux.vhd",
@@ -357,7 +357,7 @@ def test_get_build_image_variants(mock_run: Any) -> None:
        stdout=PIPE,
    )

    build_attr = m.BuildAttr(Path("/tmp"), "preAttr")
    build_attr = m.BuildAttr(Path(tmp_path), "preAttr")
    assert n.get_build_image_variants(build_attr, {"inst_flag": True}) == {
        "azure": "nixos-image-azure-25.05.20250102.6df2492-x86_64-linux.vhd",
        "vmware": "nixos-image-vmware-25.05.20250102.6df2492-x86_64-linux.vmdk",
@@ -369,10 +369,10 @@ def test_get_build_image_variants(mock_run: Any) -> None:
            "--strict",
            "--json",
            "--expr",
            textwrap.dedent("""
            textwrap.dedent(f"""
            let
              value = import "/tmp";
              set = if builtins.isFunction value then value {} else value;
              value = import "{tmp_path}";
              set = if builtins.isFunction value then value {{}} else value;
            in
              builtins.mapAttrs (n: v: v.passthru.filePath) set.preAttr.config.system.build.images
            """),
@@ -687,7 +687,7 @@ def test_set_profile(mock_run: Any) -> None:


@patch(get_qualified_name(n.run_wrapper, n), autospec=True)
def test_switch_to_configuration(mock_run: Any, monkeypatch: Any) -> None:
def test_switch_to_configuration(mock_run: Any, monkeypatch: MonkeyPatch) -> None:
    profile_path = Path("/path/to/profile")
    config_path = Path("/path/to/config")

+3 −1
Original line number Diff line number Diff line
from typing import Any
from unittest.mock import patch

from pytest import MonkeyPatch

import nixos_rebuild.models as m
import nixos_rebuild.process as p

@@ -94,7 +96,7 @@ def test_run(mock_run: Any) -> None:
    )


def test_remote_from_name(monkeypatch: Any) -> None:
def test_remote_from_name(monkeypatch: MonkeyPatch) -> None:
    monkeypatch.setenv("NIX_SSHOPTS", "")
    assert m.Remote.from_arg("user@localhost", None, False) == m.Remote(
        "user@localhost",