diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 91f766c..99d51f8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,31 +9,12 @@ permissions: contents: read jobs: - check: + flake-check: name: Flake check runs-on: ubuntu-latest + timeout-minutes: 20 steps: - uses: actions/checkout@v4 - - uses: DeterminateSystems/nix-installer-action@v17 - - uses: DeterminateSystems/magic-nix-cache-action@v8 + - uses: DeterminateSystems/nix-installer-action@v22 + - uses: DeterminateSystems/magic-nix-cache-action@v13 - run: nix flake check - - examples: - name: "Example: ${{ matrix.example }}" - runs-on: ubuntu-latest - strategy: - matrix: - example: - - example-minimal - - example-single-service - - example-full - steps: - - uses: actions/checkout@v4 - - uses: DeterminateSystems/nix-installer-action@v17 - - uses: DeterminateSystems/magic-nix-cache-action@v8 - - - name: Evaluate NixOS configuration - run: nix eval .#nixosConfigurations.${{ matrix.example }}.config.system.build.toplevel.drvPath - - - name: Build NixOS configuration (dry-run) - run: nix build .#nixosConfigurations.${{ matrix.example }}.config.system.build.toplevel --dry-run diff --git a/flake.nix b/flake.nix index c49fd91..28914a4 100644 --- a/flake.nix +++ b/flake.nix @@ -83,16 +83,48 @@ let pkgs = import nixpkgs { inherit system; }; hooks = self.lib.mkGitHooks { }; + + # Build a minimal NixOS system with a single omnix module to + # verify it evaluates and builds without errors in isolation + evalModule = + module: extraModules: + (nixpkgs.lib.nixosSystem { + inherit system; + modules = [ + module + { + boot.loader.grub.device = "nodev"; + fileSystems."/" = { + device = "none"; + fsType = "tmpfs"; + }; + nixpkgs.hostPlatform = system; + } + ] + ++ extraModules; + }).config.system.build.toplevel; in { packages.disko = disko.packages.${system}.default or (throw "disko package not available for ${system}"); packages.ragenix = ragenix.packages.${system}.default; - checks.git-hooks = git-hooks.lib.${system}.run { - inherit hooks; - src = self; - }; + checks = { + git-hooks = git-hooks.lib.${system}.run { + inherit hooks; + src = self; + }; + } + // (nixpkgs.lib.optionalAttrs pkgs.stdenv.isLinux { + eval-base = evalModule self.nixosModules.base [ ]; + eval-firewall = evalModule self.nixosModules.firewall [ ]; + eval-storage = evalModule self.nixosModules.storage [ ]; + eval-digitalocean = evalModule self.nixosModules.digitalocean [ ]; + eval-services = evalModule self.nixosModules.services [ ]; + eval-disko = evalModule self.nixosModules.disko [ + disko.nixosModules.disko + ]; + }); formatter = pkgs.nixfmt; diff --git a/modules/base.nix b/modules/base.nix index f5a57df..92580cc 100644 --- a/modules/base.nix +++ b/modules/base.nix @@ -7,6 +7,9 @@ let cfg = config.omnix.base; + shellCfg = cfg.shell; + isNushell = shellCfg.defaultShell == "nushell"; + isZsh = shellCfg.defaultShell == "zsh"; in { options.omnix.base = { @@ -27,6 +30,44 @@ in type = lib.types.str; description = "NixOS state version"; }; + + shell = { + defaultShell = lib.mkOption { + type = lib.types.enum [ + "bash" + "zsh" + "nushell" + ]; + default = "bash"; + description = '' + Default interactive shell. Ensures the corresponding shell program + is enabled at the system level. Use `shellPackage` to set as a + user's login shell. + ''; + }; + + shellPackage = lib.mkOption { + type = lib.types.package; + readOnly = true; + description = "The package for the selected default shell, for use in users.users..shell"; + }; + + bash.viMode = lib.mkOption { + type = lib.types.bool; + default = true; + description = "Enable vi keybindings for interactive bash sessions"; + }; + + nushell.manageConfig = lib.mkOption { + type = lib.types.bool; + default = true; + description = '' + Whether omnix manages nushell configuration via + environment.etc. Set to false to manage nushell config + via home-manager or manually. + ''; + }; + }; }; config = lib.mkIf cfg.enable { @@ -57,9 +98,17 @@ in }; }; - programs.bash.interactiveShellInit = "set -o vi"; + omnix.base.shell.shellPackage = + if isNushell then + pkgs.nushell + else if isZsh then + pkgs.zsh + else + pkgs.bashInteractive; - system.activationScripts.per-service-profiles.text = "mkdir -p /nix/var/nix/profiles/per-service"; + programs.bash.interactiveShellInit = lib.mkIf shellCfg.bash.viMode "set -o vi"; + + programs.zsh.enable = lib.mkDefault isZsh; environment.systemPackages = with pkgs; @@ -70,8 +119,28 @@ in rage zellij ] + ++ lib.optional isNushell pkgs.nushell ++ cfg.extraPackages; + environment.shells = lib.mkIf isNushell [ pkgs.nushell ]; + + environment.variables = lib.mkIf (isNushell && shellCfg.nushell.manageConfig) { + NU_VENDOR_AUTOLOAD_DIR = "/etc/nushell"; + }; + + environment.etc = lib.mkIf (isNushell && shellCfg.nushell.manageConfig) { + "nushell/config.nu".text = '' + $env.config = { + show_banner: false + } + ''; + "nushell/env.nu".text = '' + # omnix managed nushell environment + ''; + }; + + system.activationScripts.per-service-profiles.text = "mkdir -p /nix/var/nix/profiles/per-service"; + system.stateVersion = cfg.stateVersion; }; }