From ea7cfc350a6e6d0e0e3cb522051726e1524f11cc Mon Sep 17 00:00:00 2001 From: Jonathan Thiessen Date: Mon, 24 Mar 2025 11:22:20 -0700 Subject: [PATCH] Add dependent vars generator dynamic validation test --- pkgs/clan-cli/tests/test_vars.py | 72 ++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/pkgs/clan-cli/tests/test_vars.py b/pkgs/clan-cli/tests/test_vars.py index 12123e8ab..f084b7af6 100644 --- a/pkgs/clan-cli/tests/test_vars.py +++ b/pkgs/clan-cli/tests/test_vars.py @@ -919,3 +919,75 @@ def test_invalidation( str(machine.flake.path), machine.name, "my_generator/my_value" ).printable_value assert value2 == value2_new + + +@pytest.mark.with_core +def test_dynamic_invalidation( + monkeypatch: pytest.MonkeyPatch, + flake: ClanFlake, +) -> None: + gen_prefix = "config.clan.core.vars.generators" + + machine = Machine(name="my_machine", flake=Flake(str(flake.path))) + + config = flake.machines[machine.name] + config["nixpkgs"]["hostPlatform"] = "x86_64-linux" + + my_generator = config["clan"]["core"]["vars"]["generators"]["my_generator"] + my_generator["files"]["my_value"]["secret"] = False + my_generator["script"] = "echo -n $RANDOM > $out/my_value" + + dependent_generator = config["clan"]["core"]["vars"]["generators"][ + "dependent_generator" + ] + dependent_generator["files"]["my_value"]["secret"] = False + dependent_generator["dependencies"] = ["my_generator"] + dependent_generator["script"] = "echo -n $RANDOM > $out/my_value" + + flake.refresh() + + # this is an abuse + custom_nix = flake.path / "machines" / machine.name / "hardware-configuration.nix" + custom_nix.write_text(""" + { config, ... }: let + p = config.clan.core.vars.generators.my_generator.files.my_value.path; + in { + clan.core.vars.generators.dependent_generator.validation = if builtins.pathExists p then builtins.readFile p else null; + } + """) + + flake.refresh() + machine.flush_caches() + monkeypatch.chdir(flake.path) + + # before generating, dependent generator validation should be empty; see bogus hardware-configuration.nix above + # we have to avoid `*.files.value` in this initial select because the generators haven't been run yet + generators_0 = machine.eval_nix(f"{gen_prefix}.*.{{validationHash}}") + assert generators_0["dependent_generator"]["validationHash"] is None + + # generate both my_generator and (the dependent) dependent_generator + cli.run(["vars", "generate", "--flake", str(flake.path), machine.name]) + machine.flush_caches() + + # after generating once, dependent generator validation should be set + generators_1 = machine.eval_nix(gen_prefix) + assert generators_1["dependent_generator"]["validationHash"] is not None + + # after generating once, neither generator should want to run again because `clan vars generate` should have re-evaluated the dependent generator's validationHash after executing the parent generator but before executing the dependent generator + # this ensures that validation can depend on parent generators while still only requiring a single pass + cli.run(["vars", "generate", "--flake", str(flake.path), machine.name]) + machine.flush_caches() + + generators_2 = machine.eval_nix(gen_prefix) + assert ( + generators_1["dependent_generator"]["validationHash"] + == generators_2["dependent_generator"]["validationHash"] + ) + assert ( + generators_1["my_generator"]["files"]["my_value"]["value"] + == generators_2["my_generator"]["files"]["my_value"]["value"] + ) + assert ( + generators_1["dependent_generator"]["files"]["my_value"]["value"] + == generators_2["dependent_generator"]["files"]["my_value"]["value"] + )