From 0a43721a4592f24aa117d06badb875a69d4953a4 Mon Sep 17 00:00:00 2001 From: a-kenji Date: Sat, 26 Jul 2025 15:03:41 +0200 Subject: [PATCH 1/2] pkgs/clan/lib: Fix clan template creation when already in a flake Fix clan template creation when already in a flake. Currently we already fail with very clear and descriptive error when trying to evaluate the template of the flake we are in: ``` Failed to select template 'flake-parts' from flake '/tmp/superclan' (via attribute path: /tmp/superclan#clanInternals.templates.clan."flake-parts") ``` This is undesired behavior. When we are trying to create a clan with `clan flakes create`. We can't rely on the fact that the flake we are currently in exports flake templates. Now we *try* to evaluate the flake we are in upon creation. If there are no clan templates available, we now will fall back to builtin templates. Closes: #4472 --- .../clan_cli/tests/test_create_flake.py | 20 ++++++++++++++++++- pkgs/clan-cli/clan_lib/templates/handler.py | 18 ++++++++++++++--- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/pkgs/clan-cli/clan_cli/tests/test_create_flake.py b/pkgs/clan-cli/clan_cli/tests/test_create_flake.py index 145484eff..6e32beab3 100644 --- a/pkgs/clan-cli/clan_cli/tests/test_create_flake.py +++ b/pkgs/clan-cli/clan_cli/tests/test_create_flake.py @@ -3,7 +3,7 @@ import logging from pathlib import Path import pytest -from clan_cli.tests.fixtures_flakes import substitute +from clan_cli.tests.fixtures_flakes import FlakeForTest, substitute from clan_cli.tests.helpers import cli from clan_cli.tests.stdout import CaptureOutput from clan_lib.cmd import run @@ -132,3 +132,21 @@ def test_ui_template( flake_outputs["nixosConfigurations"]["machine1"] except KeyError: pytest.fail("nixosConfigurations.machine1 not found in flake outputs") + + +@pytest.mark.with_core +def test_create_flake_fallback_from_non_clan_directory( + monkeypatch: pytest.MonkeyPatch, + temporary_home: Path, + test_flake: FlakeForTest, +) -> None: + """Test that clan flakes create falls back to builtin templates from non-clan flake.""" + monkeypatch.chdir(test_flake.path) + new_clan_dir = temporary_home / "new-clan" + monkeypatch.setenv("LOGNAME", "testuser") + + cli.run( + ["flakes", "create", str(new_clan_dir), "--template=default", "--no-update"] + ) + + assert (new_clan_dir / "flake.nix").exists() diff --git a/pkgs/clan-cli/clan_lib/templates/handler.py b/pkgs/clan-cli/clan_lib/templates/handler.py index 514a08bea..b379b4336 100644 --- a/pkgs/clan-cli/clan_lib/templates/handler.py +++ b/pkgs/clan-cli/clan_lib/templates/handler.py @@ -4,7 +4,7 @@ from collections.abc import Callable, Iterator from contextlib import contextmanager from pathlib import Path -from clan_lib.dirs import specific_machine_dir +from clan_lib.dirs import clan_templates, specific_machine_dir from clan_lib.errors import ClanError from clan_lib.flake import Flake from clan_lib.machines.actions import list_machines @@ -138,8 +138,20 @@ def clan_template( try: template = template_flake.select(template_selector) except ClanError as e: - msg = f"Failed to select template '{template_ident}' from flake '{flake_ref}' (via attribute path: {printable_template_ref})" - raise ClanError(msg) from e + try: + log.info( + f"Template '{template_ident}' not found in {flake_ref}, trying builtin template" + ) + builtin_flake = Flake(str(clan_templates())) + [_, builtin_selector] = transform_url( + "clan", template_ident, flake=builtin_flake + ) + template = builtin_flake.select(builtin_selector) + template_flake = builtin_flake + printable_template_ref = f"{clan_templates()}#{builtin_selector}" + except ClanError: + msg = f"Failed to select template '{template_ident}' from flake '{flake_ref}' (via attribute path: {printable_template_ref})" + raise ClanError(msg) from e src = template.get("path") if not src: From 3ef6b2f715e34633eb824cdc300c5d6692c06dc7 Mon Sep 17 00:00:00 2001 From: a-kenji Date: Tue, 29 Jul 2025 12:48:26 +0200 Subject: [PATCH 2/2] pkgs/clan/cli: Add test for builtin flakeref --- .../clan_cli/tests/test_create_flake.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/pkgs/clan-cli/clan_cli/tests/test_create_flake.py b/pkgs/clan-cli/clan_cli/tests/test_create_flake.py index 6e32beab3..43a16e3ff 100644 --- a/pkgs/clan-cli/clan_cli/tests/test_create_flake.py +++ b/pkgs/clan-cli/clan_cli/tests/test_create_flake.py @@ -150,3 +150,21 @@ def test_create_flake_fallback_from_non_clan_directory( ) assert (new_clan_dir / "flake.nix").exists() + + +@pytest.mark.with_core +def test_create_flake_with_local_template_reference( + monkeypatch: pytest.MonkeyPatch, + temporary_home: Path, + test_flake: FlakeForTest, +) -> None: + monkeypatch.chdir(test_flake.path) + new_clan_dir = temporary_home / "new-clan" + monkeypatch.setenv("LOGNAME", "testuser") + + # TODO: should error with: localFlake does not export myLocalTemplate clan template + cli.run( + ["flakes", "create", str(new_clan_dir), "--template=.#default", "--no-update"] + ) + + assert (new_clan_dir / "flake.nix").exists()