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

nixos-rebuild{-ng,}: Don't eval nixos closure before validating image variants. (#395148)

parents 45a7d8f4 ab4f5ac2
Loading
Loading
Loading
Loading
+14 −2
Original line number Diff line number Diff line
@@ -396,7 +396,7 @@ def execute(argv: list[str]) -> None:
                    raise NRError(
                        "please specify one of the following "
                        + "supported image variants via --image-variant:\n"
                        + "\n".join(f"- {v}" for v in variants.keys())
                        + "\n".join(f"- {v}" for v in variants)
                    )

            match action:
@@ -518,7 +518,19 @@ def execute(argv: list[str]) -> None:
                        "Done. The virtual machine can be started by running", vm_path
                    )
                case Action.BUILD_IMAGE:
                    disk_path = path_to_config / variants[args.image_variant]
                    if flake:
                        image_name = nix.get_build_image_name_flake(
                            flake,
                            args.image_variant,
                            eval_flags=flake_common_flags,
                        )
                    else:
                        image_name = nix.get_build_image_name(
                            build_attr,
                            args.image_variant,
                            instantiate_flags=flake_common_flags,
                        )
                    disk_path = path_to_config / image_name
                    print_result("Done. The disk image can be found in", disk_path)

        case Action.EDIT:
+1 −1
Original line number Diff line number Diff line
@@ -8,7 +8,7 @@ from typing import Any, Callable, ClassVar, Self, TypedDict, override

from .process import Remote, run_wrapper

type ImageVariants = dict[str, str]
type ImageVariants = list[str]


class NRError(Exception):
+55 −2
Original line number Diff line number Diff line
@@ -266,6 +266,59 @@ def find_file(file: str, nix_flags: Args | None = None) -> Path | None:
    return Path(r.stdout.strip())


def get_build_image_name(
    build_attr: BuildAttr,
    image_variant: str,
    instantiate_flags: Args | None = None,
) -> str:
    path = (
        f'"{build_attr.path.resolve()}"'
        if isinstance(build_attr.path, Path)
        else build_attr.path
    )
    r = run_wrapper(
        [
            "nix-instantiate",
            "--eval",
            "--strict",
            "--json",
            "--expr",
            textwrap.dedent(f"""
            let
              value = import {path};
              set = if builtins.isFunction value then value {{}} else value;
            in
              set.{build_attr.to_attr("config.system.build.images", image_variant, "passthru", "filePath")}
            """),
            *dict_to_flags(instantiate_flags),
        ],
        stdout=PIPE,
    )
    j: str = json.loads(r.stdout.strip())
    return j


def get_build_image_name_flake(
    flake: Flake,
    image_variant: str,
    eval_flags: Args | None = None,
) -> str:
    r = run_wrapper(
        [
            "nix",
            "eval",
            "--json",
            flake.to_attr(
                "config.system.build.images", image_variant, "passthru", "filePath"
            ),
            *dict_to_flags(eval_flags),
        ],
        stdout=PIPE,
    )
    j: str = json.loads(r.stdout.strip())
    return j


def get_build_image_variants(
    build_attr: BuildAttr,
    instantiate_flags: Args | None = None,
@@ -287,7 +340,7 @@ def get_build_image_variants(
              value = import {path};
              set = if builtins.isFunction value then value {{}} else value;
            in
              builtins.mapAttrs (n: v: v.passthru.filePath) set.{build_attr.to_attr("config.system.build.images")}
              builtins.attrNames set.{build_attr.to_attr("config.system.build.images")}
            """),
            *dict_to_flags(instantiate_flags),
        ],
@@ -308,7 +361,7 @@ def get_build_image_variants_flake(
            "--json",
            flake.to_attr("config.system.build.images"),
            "--apply",
            "builtins.mapAttrs (n: v: v.passthru.filePath)",
            "builtins.attrNames",
            *dict_to_flags(eval_flags),
        ],
        stdout=PIPE,
+14 −8
Original line number Diff line number Diff line
@@ -347,12 +347,7 @@ def test_execute_nix_build_image_flake(mock_run: Mock, tmp_path: Path) -> None:
            return CompletedProcess(
                [],
                0,
                """
                {
                  "azure": "nixos-image-azure-25.05.20250102.6df2492-x86_64-linux.vhd",
                  "vmware": "nixos-image-vmware-25.05.20250102.6df2492-x86_64-linux.vmdk"
                }
                """,
                '"nixos-image-azure-25.05.20250102.6df2492-x86_64-linux.vhd"',
            )
        elif args[0] == "nix":
            return CompletedProcess([], 0, str(config_path))
@@ -372,7 +367,7 @@ def test_execute_nix_build_image_flake(mock_run: Mock, tmp_path: Path) -> None:
        ]
    )

    assert mock_run.call_count == 2
    assert mock_run.call_count == 3
    mock_run.assert_has_calls(
        [
            call(
@@ -382,7 +377,7 @@ def test_execute_nix_build_image_flake(mock_run: Mock, tmp_path: Path) -> None:
                    "--json",
                    "/path/to/config#nixosConfigurations.hostname.config.system.build.images",
                    "--apply",
                    "builtins.mapAttrs (n: v: v.passthru.filePath)",
                    "builtins.attrNames",
                ],
                check=True,
                stdout=PIPE,
@@ -401,6 +396,17 @@ def test_execute_nix_build_image_flake(mock_run: Mock, tmp_path: Path) -> None:
                stdout=PIPE,
                **DEFAULT_RUN_KWARGS,
            ),
            call(
                [
                    "nix",
                    "eval",
                    "--json",
                    "/path/to/config#nixosConfigurations.hostname.config.system.build.images.azure.passthru.filePath",
                ],
                check=True,
                stdout=PIPE,
                **DEFAULT_RUN_KWARGS,
            ),
        ]
    )

+3 −3
Original line number Diff line number Diff line
@@ -353,7 +353,7 @@ def test_get_build_image_variants(mock_run: Mock, tmp_path: Path) -> None:
              value = import <nixpkgs/nixos>;
              set = if builtins.isFunction value then value {} else value;
            in
              builtins.mapAttrs (n: v: v.passthru.filePath) set.config.system.build.images
              builtins.attrNames set.config.system.build.images
            """),
        ],
        stdout=PIPE,
@@ -376,7 +376,7 @@ def test_get_build_image_variants(mock_run: Mock, tmp_path: Path) -> None:
              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
              builtins.attrNames set.preAttr.config.system.build.images
            """),
            "--inst-flag",
        ],
@@ -411,7 +411,7 @@ def test_get_build_image_variants_flake(mock_run: Mock) -> None:
            "--json",
            "flake.nix#myAttr.config.system.build.images",
            "--apply",
            "builtins.mapAttrs (n: v: v.passthru.filePath)",
            "builtins.attrNames",
            "--eval-flag",
        ],
        stdout=PIPE,
Loading