From 2f95d2edf2cd4c77a105f6ffc68e1252266b5af9 Mon Sep 17 00:00:00 2001 From: Michael Hoang Date: Fri, 25 Apr 2025 11:11:51 +1000 Subject: [PATCH 1/2] cli: fallback to bundled Nixpkgs --- pkgs/clan-cli/clan_cli/flake.py | 17 +++++++++++++++-- pkgs/clan-cli/default.nix | 1 + 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/pkgs/clan-cli/clan_cli/flake.py b/pkgs/clan-cli/clan_cli/flake.py index b25ef5170..58d16ec99 100644 --- a/pkgs/clan-cli/clan_cli/flake.py +++ b/pkgs/clan-cli/clan_cli/flake.py @@ -8,7 +8,7 @@ from tempfile import NamedTemporaryFile from typing import Any from clan_cli.cmd import Log, RunOpts, run -from clan_cli.dirs import select_source, user_cache_dir +from clan_cli.dirs import nixpkgs_source, select_source, user_cache_dir from clan_cli.errors import ClanError from clan_cli.nix import ( nix_build, @@ -701,6 +701,18 @@ class Flake: config = nix_config() + # these hashes should be filled in by `nix build` + # if we run this Python code directly then we use a fallback + # method to getting the NAR hash + fallback_nixpkgs_hash = "@fallback_nixpkgs_hash@" + if not fallback_nixpkgs_hash.startswith("sha256-"): + fallback_nixpkgs = Flake(str(nixpkgs_source())) + fallback_nixpkgs.invalidate_cache() + assert fallback_nixpkgs.hash is not None, ( + "this should be impossible as invalidate_cache() should always set `hash`" + ) + fallback_nixpkgs_hash = fallback_nixpkgs.hash + select_hash = "@select_hash@" if not select_hash.startswith("sha256-"): select_flake = Flake(str(select_source())) @@ -714,8 +726,9 @@ class Flake: let flake = builtins.getFlake "path:{self.store_path}?narHash={self.hash}"; selectLib = (builtins.getFlake "{select_source()}?narHash={select_hash}").lib; + nixpkgs = flake.inputs.nixpkgs or (builtins.getFlake "{nixpkgs_source()}?narHash={fallback_nixpkgs_hash}"); in - flake.inputs.nixpkgs.legacyPackages.{config["system"]}.writeText "clan-flake-select" ( + nixpkgs.legacyPackages.{config["system"]}.writeText "clan-flake-select" ( builtins.toJSON [ {" ".join([f"(selectLib.applySelectors (builtins.fromJSON ''{attr}'') flake)" for attr in str_selectors])} ] ) """ diff --git a/pkgs/clan-cli/default.nix b/pkgs/clan-cli/default.nix index 409a94cd7..8e01461e4 100644 --- a/pkgs/clan-cli/default.nix +++ b/pkgs/clan-cli/default.nix @@ -66,6 +66,7 @@ let rm -f $out/clan_cli/nixpkgs substituteInPlace $out/clan_cli/flake.py \ + --replace-fail '@fallback_nixpkgs_hash@' "$(jq -r '.nodes.nixpkgs.locked.narHash' ${nixpkgs'}/flake.lock)" \ --replace-fail '@select_hash@' "$(jq -r '.nodes."nix-select".locked.narHash' ${../../flake.lock})" ln -sf ${nixpkgs'} $out/clan_cli/nixpkgs ln -sf ${nix-select} $out/clan_cli/select From 87e3e59ba0ac38b2c0a9d62f49cda9507ad4edd4 Mon Sep 17 00:00:00 2001 From: Michael Hoang Date: Fri, 25 Apr 2025 11:11:51 +1000 Subject: [PATCH 2/2] cli: don't depend on the entire `clan-core` --- pkgs/clan-cli/clan_cli/dirs.py | 19 ++++++++--- pkgs/clan-cli/clan_cli/templates.py | 15 ++------ pkgs/clan-cli/default.nix | 5 --- templates/flake-module.nix | 40 ++-------------------- templates/flake.nix | 53 +++++++++++++++++++---------- 5 files changed, 54 insertions(+), 78 deletions(-) diff --git a/pkgs/clan-cli/clan_cli/dirs.py b/pkgs/clan-cli/clan_cli/dirs.py index 7aed170db..defe64fe5 100644 --- a/pkgs/clan-cli/clan_cli/dirs.py +++ b/pkgs/clan-cli/clan_cli/dirs.py @@ -47,18 +47,27 @@ def find_toplevel(top_level_files: list[str]) -> Path | None: class TemplateType(Enum): CLAN = "clan" DISK = "disk" + MACHINE = "machine" -def clan_templates(template_type: TemplateType) -> Path: - template_path = ( - module_root().parent.parent.parent / "templates" / template_type.value - ) +def clan_templates(template_type: TemplateType | None = None) -> Path: + template_path = module_root().parent.parent.parent / "templates" + + if template_type is not None: + template_path /= template_type.value + if template_path.exists(): return template_path - template_path = module_root() / "templates" / template_type.value + + template_path = module_root() / "templates" + + if template_type is not None: + template_path /= template_type.value + if not template_path.exists(): msg = f"BUG! clan core not found at {template_path}. This is an issue with packaging the cli" raise ClanError(msg) + return template_path diff --git a/pkgs/clan-cli/clan_cli/templates.py b/pkgs/clan-cli/clan_cli/templates.py index 956e2f1dd..ee6afcf39 100644 --- a/pkgs/clan-cli/clan_cli/templates.py +++ b/pkgs/clan-cli/clan_cli/templates.py @@ -1,10 +1,10 @@ import logging -import os from dataclasses import dataclass, field from pathlib import Path from typing import Any, Literal, NewType, TypedDict, cast from clan_cli.cmd import run +from clan_cli.dirs import clan_templates from clan_cli.errors import ClanCmdError, ClanError from clan_cli.flake import Flake @@ -83,13 +83,8 @@ def get_clan_nix_attrset(clan_dir: Flake | None = None) -> ClanExports: Get the clan nix attrset from a flake, with fallback structure applied. Path inside the attrsets have NOT YET been realized in the nix store. """ - # Check if the clan directory is provided, otherwise use the environment variable if not clan_dir: - clan_core_path = os.environ.get("CLAN_CORE_PATH") - if not clan_core_path: - msg = "Environment var CLAN_CORE_PATH is not set, this shouldn't happen" - raise ClanError(msg) - clan_dir = Flake(clan_core_path) + clan_dir = Flake(str(clan_templates())) log.debug(f"Evaluating flake {clan_dir} for Clan attrsets") @@ -231,11 +226,7 @@ def get_template( """ if not clan_dir: - clan_core_path = os.environ.get("CLAN_CORE_PATH") - if not clan_core_path: - msg = "Environment var CLAN_CORE_PATH is not set, this shouldn't happen" - raise ClanError(msg) - clan_dir = Flake(clan_core_path) + clan_dir = Flake(str(clan_templates())) log.info(f"Get template in {clan_dir}") diff --git a/pkgs/clan-cli/default.nix b/pkgs/clan-cli/default.nix index 8e01461e4..6d2a77795 100644 --- a/pkgs/clan-cli/default.nix +++ b/pkgs/clan-cli/default.nix @@ -115,11 +115,6 @@ pythonRuntime.pkgs.buildPythonApplication { ":" (lib.makeBinPath (lib.attrValues bundledRuntimeDependenciesMap)) - # We need this for templates to work - "--set" - "CLAN_CORE_PATH" - clan-core-path - "--set" "CLAN_PROVIDED_PACKAGES" (lib.concatStringsSep ":" (lib.attrNames bundledRuntimeDependenciesMap)) diff --git a/templates/flake-module.nix b/templates/flake-module.nix index 2cf940d6a..366fd7ef7 100644 --- a/templates/flake-module.nix +++ b/templates/flake-module.nix @@ -1,43 +1,7 @@ { self, inputs, ... }: { - clan.templates = { - disko = { - single-disk = { - description = "A simple ext4 disk with a single partition"; - path = ./disk/single-disk; - }; - }; - - machine = { - flash-installer = { - description = "Initialize a new flash-installer machine"; - path = ./machine/flash-installer; - }; - - new-machine = { - description = "Initialize a new machine"; - path = ./machine/new-machine; - }; - }; - - clan = { - default = { - description = "Initialize a new clan flake"; - path = ./clan/new-clan; - }; - minimal = { - description = "for clans managed via (G)UI"; - path = ./clan/minimal; - }; - flake-parts = { - description = "Flake-parts"; - path = ./clan/flake-parts; - }; - minimal-flake-parts = { - description = "Minimal flake-parts clan template"; - path = ./clan/minimal-flake-parts; - }; - }; + clan = { + inherit (((import ./flake.nix).outputs { }).clan) templates; }; flake = { diff --git a/templates/flake.nix b/templates/flake.nix index c11539f49..e349af18b 100644 --- a/templates/flake.nix +++ b/templates/flake.nix @@ -2,26 +2,43 @@ outputs = { ... }: { - templates = { - default = { - description = "Initialize a new clan flake"; - path = ./clan/new-clan; + clan.templates = { + disko = { + single-disk = { + description = "A simple ext4 disk with a single partition"; + path = ./disk/single-disk; + }; }; - minimal = { - description = "for clans managed via (G)UI"; - path = ./clan/minimal; + + machine = { + flash-installer = { + description = "Initialize a new flash-installer machine"; + path = ./machine/flash-installer; + }; + + new-machine = { + description = "Initialize a new machine"; + path = ./machine/new-machine; + }; }; - flake-parts = { - description = "Flake-parts"; - path = ./clan/flake-parts; - }; - minimal-flake-parts = { - description = "Minimal flake-parts clan template"; - path = ./clan/minimal-flake-parts; - }; - machineTemplates = { - description = "Machine templates"; - path = ./machine; + + clan = { + default = { + description = "Initialize a new clan flake"; + path = ./clan/new-clan; + }; + minimal = { + description = "for clans managed via (G)UI"; + path = ./clan/minimal; + }; + flake-parts = { + description = "Flake-parts"; + path = ./clan/flake-parts; + }; + minimal-flake-parts = { + description = "Minimal flake-parts clan template"; + path = ./clan/minimal-flake-parts; + }; }; }; };