From a0c12d922df51c132d4f47810cdd06753dc39eb9 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Fri, 5 Apr 2024 19:17:23 +0200 Subject: [PATCH 1/4] Add flake-parts module Signed-off-by: Sefa Eyeoglu --- flake.nix | 2 + nix/flake-module.nix | 106 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 nix/flake-module.nix diff --git a/flake.nix b/flake.nix index 9f34a9e..4cd6bd1 100644 --- a/flake.nix +++ b/flake.nix @@ -17,6 +17,8 @@ outputs = { self, nixpkgs, utils, ... }@inputs: rec { + flakeModule = ./nix/flake-module.nix; + overlay = final: prev: let system = final.stdenv.hostPlatform.system; darwinOptions = final.lib.optionalAttrs final.stdenv.isDarwin { diff --git a/nix/flake-module.nix b/nix/flake-module.nix new file mode 100644 index 0000000..1f72f64 --- /dev/null +++ b/nix/flake-module.nix @@ -0,0 +1,106 @@ +# SPDX-FileCopyrightText: 2024 Sefa Eyeoglu +# +# SPDX-License-Identifier: MPL-2.0 + +{lib, ...}: let + inherit (lib) mkOption types; + genericSettings = { + options = { + sshUser = mkOption { + type = with types; nullOr str; + default = null; + }; + user = mkOption { + type = with types; nullOr str; + default = null; + }; + sshOpts = mkOption { + type = with types; listOf str; + default = []; + }; + fastConnection = mkOption { + type = with types; nullOr bool; + default = null; + }; + autoRollback = mkOption { + type = with types; nullOr bool; + default = null; + }; + confirmTimeout = mkOption { + type = with types; nullOr int; + default = null; + }; + activationTimeout = mkOption { + type = with types; nullOr int; + default = null; + }; + tempPath = mkOption { + type = with types; nullOr str; + default = null; + }; + magicRollback = mkOption { + type = with types; nullOr bool; + default = null; + }; + sudo = mkOption { + type = with types; nullOr str; + default = null; + }; + remoteBuild = mkOption { + type = with types; nullOr bool; + default = null; + }; + interactiveSudo = mkOption { + type = with types; nullOr bool; + default = null; + }; + }; + }; + profileSettings = { + options = { + path = mkOption { + type = types.package; + }; + profilePath = mkOption { + type = with types; nullOr str; + default = null; + }; + }; + }; + nodeSettings = { + options = { + hostname = mkOption { + type = types.str; + }; + profilesOrder = mkOption { + type = with types; listOf str; + default = []; + }; + profiles = mkOption { + type = types.attrsOf profileModule; + }; + }; + }; + + nodesSettings = { + options.nodes = mkOption { + type = types.attrsOf nodeModule; + }; + }; + + profileModule = types.submoduleWith { + modules = [genericSettings profileSettings]; + }; + + nodeModule = types.submoduleWith { + modules = [genericSettings nodeSettings]; + }; + + rootModule = types.submoduleWith { + modules = [genericSettings nodesSettings]; + }; +in { + options.flake.deploy = mkOption { + type = rootModule; + }; +} From 13bf9cec4f4a51b63e2034f00f0abe1292ec8de2 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Fri, 5 Apr 2024 19:48:02 +0200 Subject: [PATCH 2/4] Add simple flake-parts module test Signed-off-by: Sefa Eyeoglu --- flake.lock | 37 ++++++++++++++++ flake.nix | 1 + nix/tests/default.nix | 48 +++++++++++++-------- nix/tests/parts-flake.nix | 89 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 158 insertions(+), 17 deletions(-) create mode 100644 nix/tests/parts-flake.nix diff --git a/flake.lock b/flake.lock index 4f59bdc..95a4c06 100644 --- a/flake.lock +++ b/flake.lock @@ -16,6 +16,24 @@ "type": "github" } }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1712014858, + "narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "9126214d0a59633752a136528f5f3b9aa8565b7d", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, "nixpkgs": { "locked": { "lastModified": 1702272962, @@ -32,9 +50,28 @@ "type": "github" } }, + "nixpkgs-lib": { + "locked": { + "dir": "lib", + "lastModified": 1711703276, + "narHash": "sha256-iMUFArF0WCatKK6RzfUJknjem0H9m4KgorO/p3Dopkk=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "d8fe5e6c92d0d190646fb9f1056741a229980089", + "type": "github" + }, + "original": { + "dir": "lib", + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, "root": { "inputs": { "flake-compat": "flake-compat", + "flake-parts": "flake-parts", "nixpkgs": "nixpkgs", "utils": "utils" } diff --git a/flake.nix b/flake.nix index 4cd6bd1..e4095e6 100644 --- a/flake.nix +++ b/flake.nix @@ -13,6 +13,7 @@ url = "github:edolstra/flake-compat"; flake = false; }; + flake-parts.url = "github:hercules-ci/flake-parts"; }; outputs = { self, nixpkgs, utils, ... }@inputs: diff --git a/nix/tests/default.nix b/nix/tests/default.nix index b38e99d..75ef858 100644 --- a/nix/tests/default.nix +++ b/nix/tests/default.nix @@ -20,7 +20,27 @@ let done <$refs ''; - mkTest = { name ? "", user ? "root", isLocal ? true, deployArgs }: let + flakeInputs = '' + deploy-rs.url = "${../..}"; + deploy-rs.inputs.utils.follows = "utils"; + deploy-rs.inputs.flake-compat.follows = "flake-compat"; + + nixpkgs.url = "${inputs.nixpkgs}"; + utils.url = "${inputs.utils}"; + utils.inputs.systems.follows = "systems"; + flake-parts.url = "${inputs.flake-parts}"; + flake-parts.inputs.nixpkgs-lib.follows = "nixpkgs"; + systems.url = "${inputs.utils.inputs.systems}"; + flake-compat.url = "${inputs.flake-compat}"; + flake-compat.flake = false; + ''; + + deployFlake = builtins.toFile "flake.nix" + (lib.replaceStrings [ "##inputs##" ] [ flakeInputs ] (builtins.readFile ./deploy-flake.nix)); + partsFlake = builtins.toFile "flake.nix" + (lib.replaceStrings [ "##inputs##" ] [ flakeInputs ] (builtins.readFile ./parts-flake.nix)); + + mkTest = { name ? "", user ? "root", isLocal ? true, deployArgs, flake }: let nodes = { server = { nodes, ... }: { imports = [ @@ -45,22 +65,6 @@ let }; }; - flakeInputs = '' - deploy-rs.url = "${../..}"; - deploy-rs.inputs.utils.follows = "utils"; - deploy-rs.inputs.flake-compat.follows = "flake-compat"; - - nixpkgs.url = "${inputs.nixpkgs}"; - utils.url = "${inputs.utils}"; - utils.inputs.systems.follows = "systems"; - systems.url = "${inputs.utils.inputs.systems}"; - flake-compat.url = "${inputs.flake-compat}"; - flake-compat.flake = false; - ''; - - flake = builtins.toFile "flake.nix" - (lib.replaceStrings [ "##inputs##" ] [ flakeInputs ] (builtins.readFile ./deploy-flake.nix)); - in pkgs.nixosTest { inherit nodes name; @@ -107,12 +111,14 @@ in { local-build = mkTest { name = "local-build"; deployArgs = "-s .#server -- --offline"; + flake = deployFlake; }; # Deployment with server-side build remote-build = mkTest { name = "remote-build"; isLocal = false; deployArgs = "-s .#server --remote-build -- --offline"; + flake = deployFlake; }; # Deployment with overridden options options-overriding = mkTest { @@ -124,11 +130,19 @@ in { " --confirm-timeout 30 --activation-timeout 30" " -- --offline" ]; + flake = deployFlake; }; # User profile deployment profile = mkTest { name = "profile"; user = "deploy"; deployArgs = "-s .#profile -- --offline"; + flake = deployFlake; + }; + # Deployment with client-side build + local-build-parts = mkTest { + name = "local-build"; + deployArgs = "-s .#server -- --offline"; + flake = partsFlake; }; } diff --git a/nix/tests/parts-flake.nix b/nix/tests/parts-flake.nix new file mode 100644 index 0000000..d43fc6b --- /dev/null +++ b/nix/tests/parts-flake.nix @@ -0,0 +1,89 @@ +# SPDX-FileCopyrightText: 2024 Serokell +# SPDX-FileCopyrightText: 2024 Sefa Eyeoglu +# +# SPDX-License-Identifier: MPL-2.0 + +{ + inputs = { + # real inputs are substituted in ./default.nix + ##inputs## + }; + + outputs = inputs@{ deploy-rs, flake-parts, nixpkgs, self, ... }: + flake-parts.lib.mkFlake { inherit inputs; } { + systems = nixpkgs.lib.systems.flakeExposed; + imports = [ deploy-rs.flakeModule ]; + flake = + let + system = "x86_64-linux"; + pkgs = nixpkgs.legacyPackages.${system}; + user = "deploy"; + in + { + nixosConfigurations.server = nixpkgs.lib.nixosSystem { + inherit system pkgs; + specialArgs = { inherit inputs; }; + modules = [ + ./server.nix + ./common.nix + # Import the base config used by nixos tests + (pkgs.path + "/nixos/lib/testing/nixos-test-base.nix") + # Deployment breaks the network settings, so we need to restore them + (pkgs.lib.importJSON ./network.json) + # Deploy packages + { environment.systemPackages = [ pkgs.figlet pkgs.hello ]; } + ]; + }; + + deploy.nodes = { + server = { + hostname = "server"; + sshUser = "root"; + sshOpts = [ + "-o" + "StrictHostKeyChecking=no" + "-o" + "StrictHostKeyChecking=no" + ]; + profiles.system.path = deploy-rs.lib."${system}".activate.nixos + self.nixosConfigurations.server; + }; + server-override = { + hostname = "override"; + sshUser = "override"; + user = "override"; + sudo = "override"; + sshOpts = [ ]; + confirmTimeout = 0; + activationTimeout = 0; + profiles.system.path = deploy-rs.lib."${system}".activate.nixos + self.nixosConfigurations.server; + }; + profile = { + hostname = "server"; + sshUser = "${user}"; + sshOpts = [ + "-o" + "UserKnownHostsFile=/dev/null" + "-o" + "StrictHostKeyChecking=no" + ]; + profiles = { + "hello-world".path = + let + activateProfile = pkgs.writeShellScriptBin "activate" '' + set -euo pipefail + mkdir -p /home/${user}/.nix-profile/bin + rm -f -- /home/${user}/.nix-profile/bin/hello /home/${user}/.nix-profile/bin/figlet + ln -s ${pkgs.hello}/bin/hello /home/${user}/.nix-profile/bin/hello + ln -s ${pkgs.figlet}/bin/figlet /home/${user}/.nix-profile/bin/figlet + ''; + in + deploy-rs.lib.${system}.activate.custom activateProfile + "$PROFILE/bin/activate"; + }; + }; + }; + }; + }; +} From 6bdb34723a52ddb4baf5547d87110d183f356b42 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Fri, 5 Apr 2024 19:59:08 +0200 Subject: [PATCH 3/4] Add flake-parts example Signed-off-by: Sefa Eyeoglu --- examples/simple-flake-parts/flake.lock | 150 +++++++++++++++++++++++++ examples/simple-flake-parts/flake.nix | 30 +++++ 2 files changed, 180 insertions(+) create mode 100644 examples/simple-flake-parts/flake.lock create mode 100644 examples/simple-flake-parts/flake.nix diff --git a/examples/simple-flake-parts/flake.lock b/examples/simple-flake-parts/flake.lock new file mode 100644 index 0000000..90c6fd2 --- /dev/null +++ b/examples/simple-flake-parts/flake.lock @@ -0,0 +1,150 @@ +{ + "nodes": { + "deploy-rs": { + "inputs": { + "flake-compat": "flake-compat", + "nixpkgs": "nixpkgs", + "utils": "utils" + }, + "locked": { + "lastModified": 1711973905, + "narHash": "sha256-UFKME/N1pbUtn+2Aqnk+agUt8CekbpuqwzljivfIme8=", + "owner": "serokell", + "repo": "deploy-rs", + "rev": "88b3059b020da69cbe16526b8d639bd5e0b51c8b", + "type": "github" + }, + "original": { + "owner": "serokell", + "repo": "deploy-rs", + "type": "github" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1712014858, + "narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "9126214d0a59633752a136528f5f3b9aa8565b7d", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1702272962, + "narHash": "sha256-D+zHwkwPc6oYQ4G3A1HuadopqRwUY/JkMwHz1YF7j4Q=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e97b3e4186bcadf0ef1b6be22b8558eab1cdeb5d", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-lib": { + "locked": { + "dir": "lib", + "lastModified": 1711703276, + "narHash": "sha256-iMUFArF0WCatKK6RzfUJknjem0H9m4KgorO/p3Dopkk=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "d8fe5e6c92d0d190646fb9f1056741a229980089", + "type": "github" + }, + "original": { + "dir": "lib", + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1712163089, + "narHash": "sha256-Um+8kTIrC19vD4/lUCN9/cU9kcOsD1O1m+axJqQPyMM=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "fd281bd6b7d3e32ddfa399853946f782553163b5", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "deploy-rs": "deploy-rs", + "flake-parts": "flake-parts", + "nixpkgs": "nixpkgs_2" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1701680307, + "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "4022d587cbbfd70fe950c1e2083a02621806a725", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/examples/simple-flake-parts/flake.nix b/examples/simple-flake-parts/flake.nix new file mode 100644 index 0000000..a02ee12 --- /dev/null +++ b/examples/simple-flake-parts/flake.nix @@ -0,0 +1,30 @@ +# SPDX-FileCopyrightText: 2024 Sefa Eyeoglu +# +# SPDX-License-Identifier: MPL-2.0 + +{ + description = "Deploy GNU hello to localhost"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + flake-parts.url = "github:hercules-ci/flake-parts"; + deploy-rs.url = "github:serokell/deploy-rs"; + }; + + outputs = inputs@{ flake-parts, ... }: + flake-parts.lib.mkFlake { inherit inputs; } { + imports = [inputs.deploy-rs.flakeModule]; + + flake.deploy.nodes.example = { + hostname = "localhost"; + profiles.hello = { + user = "balsoft"; + path = inputs.deploy-rs.lib.x86_64-linux.setActivate inputs.nixpkgs.legacyPackages.x86_64-linux.hello "./bin/hello"; + }; + }; + systems = [ + # systems for which you want to build the `perSystem` attributes + "x86_64-linux" + ]; + }; +} From 89e90f9c7fb358ed73281e9fa5b78e48f33231f7 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Fri, 5 Apr 2024 20:13:29 +0200 Subject: [PATCH 4/4] Add checks output to flake module Signed-off-by: Sefa Eyeoglu --- nix/flake-module.nix | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/nix/flake-module.nix b/nix/flake-module.nix index 1f72f64..4d648bf 100644 --- a/nix/flake-module.nix +++ b/nix/flake-module.nix @@ -2,8 +2,12 @@ # # SPDX-License-Identifier: MPL-2.0 -{lib, ...}: let +{config, inputs, lib, ...}: let inherit (lib) mkOption types; + inherit (inputs) deploy-rs; + + cfg = config.flake.deploy; + genericSettings = { options = { sshUser = mkOption { @@ -103,4 +107,9 @@ in { options.flake.deploy = mkOption { type = rootModule; }; + config = { + perSystem = {system, ...}: { + checks = lib.mkIf (deploy-rs.lib ? ${system}) (deploy-rs.lib.${system}.deployChecks cfg); + }; + }; }