From dcb87e8c3e09774cf878108ee58156d65abecd1e Mon Sep 17 00:00:00 2001 From: technofab Date: Wed, 31 Dec 2025 18:31:09 +0100 Subject: [PATCH 1/3] feat: switch from flake-parts and devenv to rensa ecosystem --- .envrc | 4 +- .gitignore | 3 - .gitlab-ci.yml | 7 +- .gitlab/renovate.json5 | 25 ++ flake.lock | 359 ++------------------------ flake.nix | 225 +++------------- lib/ansible-core.nix | 92 ------- lib/module.nix | 60 +++-- nix/repo/ci.nix | 45 ++++ nix/repo/devShells.nix | 46 ++++ nix/repo/docs.nix | 64 +++++ nix/repo/flake.lock | 136 ++++++++++ nix/repo/flake.nix | 25 ++ nix/repo/soonix.nix | 39 +++ nix/repo/tests.nix | 10 + tests/cli_test.nix | 4 + tests/fixtures/flake_parts/flake.lock | 77 ++++++ tests/fixtures/flake_parts/flake.nix | 37 +++ tests/flake_parts_test.nix | 39 +++ tests/integration_test.nix | 1 + tests/lib_test.nix | 3 + 21 files changed, 649 insertions(+), 652 deletions(-) create mode 100644 .gitlab/renovate.json5 delete mode 100644 lib/ansible-core.nix create mode 100644 nix/repo/ci.nix create mode 100644 nix/repo/devShells.nix create mode 100644 nix/repo/docs.nix create mode 100644 nix/repo/flake.lock create mode 100644 nix/repo/flake.nix create mode 100644 nix/repo/soonix.nix create mode 100644 nix/repo/tests.nix create mode 100644 tests/fixtures/flake_parts/flake.lock create mode 100644 tests/fixtures/flake_parts/flake.nix create mode 100644 tests/flake_parts_test.nix diff --git a/.envrc b/.envrc index 23c1256..565a52a 100644 --- a/.envrc +++ b/.envrc @@ -1,2 +1,2 @@ -use flake . --impure --accept-flake-config - +source $(fetchurl https://gitlab.com/rensa-nix/direnv/-/raw/v0.3.0/direnvrc "sha256-u7+KEz684NnIZ+Vh5x5qLrt8rKdnUNexewBoeTcEVHQ=") +use ren //repo/devShells/default diff --git a/.gitignore b/.gitignore index d3dedc1..4c8c616 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,2 @@ -.direnv -.devenv result -.pre-commit-config.yaml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index fce2c08..7d70f67 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,5 @@ +# Generated by soonix, DO NOT EDIT include: - - component: gitlab.com/TECHNOFAB/nix-gitlab-ci/nix-gitlab-ci@2.1.0 - inputs: - version: 2.1.0 +- component: gitlab.com/TECHNOFAB/nix-gitlab-ci/nix-gitlab-ci@3.1.2 + inputs: + version: 3.1.2 diff --git a/.gitlab/renovate.json5 b/.gitlab/renovate.json5 new file mode 100644 index 0000000..086f924 --- /dev/null +++ b/.gitlab/renovate.json5 @@ -0,0 +1,25 @@ +{ + "extends": [ + "config:recommended" + ], + "gitlabci": { + "enabled": false + }, + "lockFileMaintenance": { + "branchTopic": "lock-file-maintenance-{{packageFile}}", + "commitMessageExtra": "({{packageFile}})", + "enabled": true, + "extends": [ + "schedule:monthly" + ] + }, + "nix": { + "enabled": true + }, + "postUpgradeTasks": { + "commands": [ + "nix-portable nix run .#soonix:update" + ], + "executionMode": "branch" + } +} diff --git a/flake.lock b/flake.lock index 7f0a07d..ae6c653 100644 --- a/flake.lock +++ b/flake.lock @@ -1,272 +1,28 @@ { "nodes": { - "cachix": { - "inputs": { - "devenv": [ - "devenv" - ], - "flake-compat": [ - "devenv" - ], - "git-hooks": [ - "devenv", - "git-hooks" - ], - "nixpkgs": [ - "devenv", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1748883665, - "narHash": "sha256-R0W7uAg+BLoHjMRMQ8+oiSbTq8nkGz5RDpQ+ZfxxP3A=", - "owner": "cachix", - "repo": "cachix", - "rev": "f707778d902af4d62d8dd92c269f8e70de09acbe", - "type": "github" - }, - "original": { - "owner": "cachix", - "ref": "latest", - "repo": "cachix", - "type": "github" - } - }, - "devenv": { - "inputs": { - "cachix": "cachix", - "flake-compat": "flake-compat", - "git-hooks": "git-hooks", - "nix": "nix", - "nixpkgs": "nixpkgs" - }, - "locked": { - "lastModified": 1752600380, - "narHash": "sha256-3ZLDE0Taf9fqcTK6+fhDvq06WgzudK/E70zdddSc5vA=", - "owner": "cachix", - "repo": "devenv", - "rev": "7441c97330233543ee28d5c4612173f108250536", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "devenv", - "type": "github" - } - }, - "flake-compat": { - "flake": false, - "locked": { - "lastModified": 1747046372, - "narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, - "flake-parts": { - "inputs": { - "nixpkgs-lib": [ - "devenv", - "nix", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1733312601, - "narHash": "sha256-4pDvzqnegAfRkPwO3wmwBhVi/Sye1mzps0zHWYnP88c=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "205b12d8b7cd4802fbcb8e8ef6a0f1408781a4f9", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "flake-parts", - "type": "github" - } - }, - "flake-parts_2": { - "inputs": { - "nixpkgs-lib": "nixpkgs-lib" - }, - "locked": { - "lastModified": 1751413152, - "narHash": "sha256-Tyw1RjYEsp5scoigs1384gIg6e0GoBVjms4aXFfRssQ=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "77826244401ea9de6e3bac47c2db46005e1f30b5", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "flake-parts", - "type": "github" - } - }, - "git-hooks": { - "inputs": { - "flake-compat": [ - "devenv", - "flake-compat" - ], - "gitignore": "gitignore", - "nixpkgs": [ - "devenv", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1750779888, - "narHash": "sha256-wibppH3g/E2lxU43ZQHC5yA/7kIKLGxVEnsnVK1BtRg=", - "owner": "cachix", - "repo": "git-hooks.nix", - "rev": "16ec914f6fb6f599ce988427d9d94efddf25fe6d", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "git-hooks.nix", - "type": "github" - } - }, - "gitignore": { - "inputs": { - "nixpkgs": [ - "devenv", - "git-hooks", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1709087332, - "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", - "type": "github" - } - }, - "mkdocs-material-umami": { - "locked": { - "lastModified": 1745840856, - "narHash": "sha256-1Ad1JTMQMP6YsoIKAA+SBCE15qWrYkGue9/lXOLnu9I=", - "owner": "technofab", - "repo": "mkdocs-material-umami", - "rev": "3ac9b194450f6b779c37b8d16fec640198e5cd0a", - "type": "gitlab" - }, - "original": { - "owner": "technofab", - "repo": "mkdocs-material-umami", - "type": "gitlab" - } - }, - "nix": { - "inputs": { - "flake-compat": [ - "devenv", - "flake-compat" - ], - "flake-parts": "flake-parts", - "git-hooks-nix": [ - "devenv", - "git-hooks" - ], - "nixpkgs": [ - "devenv", - "nixpkgs" - ], - "nixpkgs-23-11": [ - "devenv" - ], - "nixpkgs-regression": [ - "devenv" - ] - }, - "locked": { - "lastModified": 1752251701, - "narHash": "sha256-fkkkwB7jz+14ZdIHAYCCNypO9EZDCKpj7LEQZhV6QJs=", - "owner": "cachix", - "repo": "nix", - "rev": "54df04f09cb084b9e58529c0ae6f53f0e50f1a19", - "type": "github" - }, - "original": { - "owner": "cachix", - "ref": "devenv-2.30", - "repo": "nix", - "type": "github" - } - }, - "nix-gitlab-ci": { - "locked": { - "dir": "lib", - "lastModified": 1752052838, - "narHash": "sha256-EqP4xB8YTVXWPCCchnVtQbuq0bKa79TUEcPF3hjuX/k=", - "owner": "technofab", - "repo": "nix-gitlab-ci", - "rev": "0c6949f585a2c1ea2cf85fc01445496f7c75faae", - "type": "gitlab" - }, - "original": { - "dir": "lib", - "owner": "technofab", - "repo": "nix-gitlab-ci", - "type": "gitlab" - } - }, - "nix-mkdocs": { - "locked": { - "dir": "lib", - "lastModified": 1757055638, - "narHash": "sha256-KHYSkEreFe4meXzSdEbknC/HwaQSNClQkc8vzHlAsMM=", - "owner": "technofab", - "repo": "nixmkdocs", - "rev": "7840a5febdbeaf2da90babf6c94b3d0929d2bf74", - "type": "gitlab" - }, - "original": { - "dir": "lib", - "owner": "technofab", - "repo": "nixmkdocs", - "type": "gitlab" - } - }, "nixpkgs": { "locked": { - "lastModified": 1750441195, - "narHash": "sha256-yke+pm+MdgRb6c0dPt8MgDhv7fcBbdjmv1ZceNTyzKg=", - "owner": "cachix", - "repo": "devenv-nixpkgs", - "rev": "0ceffe312871b443929ff3006960d29b120dc627", + "lastModified": 1766902085, + "narHash": "sha256-coBu0ONtFzlwwVBzmjacUQwj3G+lybcZ1oeNSQkgC0M=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "c0b0e0fddf73fd517c3471e546c0df87a42d53f4", "type": "github" }, "original": { - "owner": "cachix", - "ref": "rolling", - "repo": "devenv-nixpkgs", + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", "type": "github" } }, "nixpkgs-lib": { "locked": { - "lastModified": 1751159883, - "narHash": "sha256-urW/Ylk9FIfvXfliA1ywh75yszAbiTEVgpPeinFyVZo=", + "lastModified": 1754184128, + "narHash": "sha256-AjhoyBL4eSyXf01Bmc6DiuaMrJRNdWopmdnMY0Pa/M0=", "owner": "nix-community", "repo": "nixpkgs.lib", - "rev": "14a40a1d7fb9afa4739275ac642ed7301a9ba1ab", + "rev": "02e72200e6d56494f4a7c0da8118760736e41b60", "type": "github" }, "original": { @@ -275,99 +31,30 @@ "type": "github" } }, - "nixpkgs_2": { - "locked": { - "lastModified": 1752446735, - "narHash": "sha256-Nz2vtUEaRB/UjvPfuhHpez060P/4mvGpXW4JCDIboA4=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "a421ac6595024edcfbb1ef950a3712b89161c359", - "type": "github" + "ren": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" }, - "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_3": { - "locked": { - "lastModified": 1747958103, - "narHash": "sha256-qmmFCrfBwSHoWw7cVK4Aj+fns+c54EBP8cGqp/yK410=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "fe51d34885f7b5e3e7b59572796e1bcb427eccb1", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixtest": { "locked": { "dir": "lib", - "lastModified": 1749915293, - "narHash": "sha256-SeDdPVcvtgkBK1fb8lLKf+1iOY8UyDTVN6A6H19aw2M=", - "owner": "technofab", - "repo": "nixtest", - "rev": "c2a1208534fbdd8ab28ff3e45262b527f81a1755", + "lastModified": 1766497301, + "narHash": "sha256-W7WeOXMUZROMtbU1qQNWy/yai+k8gG09YACFQ7ImpsQ=", + "owner": "rensa-nix", + "repo": "core", + "rev": "e08c48b5db1052bfb8b8dad764e05decc1af893e", "type": "gitlab" }, "original": { "dir": "lib", - "owner": "technofab", - "repo": "nixtest", + "owner": "rensa-nix", + "repo": "core", "type": "gitlab" } }, "root": { "inputs": { - "devenv": "devenv", - "flake-parts": "flake-parts_2", - "mkdocs-material-umami": "mkdocs-material-umami", - "nix-gitlab-ci": "nix-gitlab-ci", - "nix-mkdocs": "nix-mkdocs", - "nixpkgs": "nixpkgs_2", - "nixtest": "nixtest", - "systems": "systems", - "treefmt-nix": "treefmt-nix" - } - }, - "systems": { - "locked": { - "lastModified": 1689347949, - "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=", - "owner": "nix-systems", - "repo": "default-linux", - "rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default-linux", - "type": "github" - } - }, - "treefmt-nix": { - "inputs": { - "nixpkgs": "nixpkgs_3" - }, - "locked": { - "lastModified": 1752055615, - "narHash": "sha256-19m7P4O/Aw/6+CzncWMAJu89JaKeMh3aMle1CNQSIwM=", - "owner": "numtide", - "repo": "treefmt-nix", - "rev": "c9d477b5d5bd7f26adddd3f96cfd6a904768d4f9", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "treefmt-nix", - "type": "github" + "nixpkgs": "nixpkgs", + "ren": "ren" } } }, diff --git a/flake.nix b/flake.nix index 50c4504..a0f7f0d 100644 --- a/flake.nix +++ b/flake.nix @@ -1,202 +1,37 @@ { + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + ren.url = "gitlab:rensa-nix/core?dir=lib"; + }; + outputs = { - flake-parts, - systems, + ren, + self, ... } @ inputs: - flake-parts.lib.mkFlake {inherit inputs;} { - imports = [ - inputs.devenv.flakeModule - inputs.treefmt-nix.flakeModule - inputs.nix-gitlab-ci.flakeModule - inputs.nix-mkdocs.flakeModule - ./lib/flakeModule.nix + ren.buildWith + { + inherit inputs; + cellsFrom = ./nix; + transformInputs = system: i: + i + // { + pkgs = import i.nixpkgs {inherit system;}; + }; + cellBlocks = with ren.blocks; [ + (simple "devShells") + (simple "ci") + (simple "tests") + (simple "docs") + (simple "soonix") + ]; + } + { + packages = ren.select self [ + ["repo" "ci" "packages"] + ["repo" "tests"] + ["repo" "docs"] + ["repo" "soonix" "packages"] ]; - systems = import systems; - flake = {}; - perSystem = { - lib, - pkgs, - self', - config, - ... - }: { - treefmt = { - projectRootFile = "flake.nix"; - programs = { - alejandra.enable = true; - mdformat.enable = true; - }; - }; - devenv.shells.default = { - containers = pkgs.lib.mkForce {}; - - git-hooks.hooks = { - treefmt = { - enable = true; - packageOverrides.treefmt = config.treefmt.build.wrapper; - }; - convco.enable = true; - }; - }; - docs."default".config = { - path = ./docs; - material = { - enable = true; - colors = { - primary = "black"; - accent = "blue"; - }; - umami = { - enable = true; - src = "https://analytics.tf/umami"; - siteId = "d8354dfa-2ad2-4089-90d2-899b981aef22"; - domains = ["nixible.projects.tf"]; - }; - }; - macros = { - enable = true; - includeDir = toString self'.packages.optionsDocs; - }; - config = { - site_name = "Nixible"; - site_url = "https://nixible.projects.tf"; - repo_name = "TECHNOFAB/nixible"; - repo_url = "https://gitlab.com/TECHNOFAB/nixible"; - extra_css = ["style.css"]; - theme = { - icon.repo = "simple/gitlab"; - logo = "images/logo.svg"; - favicon = "images/logo.svg"; - }; - nav = [ - {"Introduction" = "index.md";} - {"Usage" = "usage.md";} - {"Examples" = "examples.md";} - {"Reference" = "reference.md";} - {"Options" = "options.md";} - ]; - markdown_extensions = [ - "pymdownx.superfences" - "admonition" - ]; - }; - }; - ci = { - stages = ["test" "build" "deploy"]; - jobs = { - "test:lib" = { - stage = "test"; - script = [ - "nix run .#tests -- --junit=junit.xml" - ]; - allow_failure = true; - artifacts = { - when = "always"; - reports.junit = "junit.xml"; - }; - }; - "docs" = { - stage = "build"; - script = [ - # sh - '' - nix build .#docs:default - mkdir -p public - cp -r result/. public/ - '' - ]; - artifacts.paths = ["public"]; - }; - "pages" = { - nix.enable = false; - image = "alpine:latest"; - stage = "deploy"; - script = ["true"]; - artifacts.paths = ["public"]; - rules = [ - { - "if" = "$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH"; - } - ]; - }; - }; - }; - - nixible = { - "hello".playbook = [ - { - name = "Hello World"; - hosts = "localhost"; - tasks = [ - { - name = "Say hello"; - debug.msg = "Hello from Nixible!"; - } - ]; - } - ]; - "another".playbook = []; - }; - - packages = let - nblib = import ./lib {inherit pkgs lib;}; - ntlib = inputs.nixtest.lib {inherit pkgs lib;}; - doclib = inputs.nix-mkdocs.lib {inherit lib pkgs;}; - in rec { - tests = ntlib.mkNixtest { - modules = ntlib.autodiscover {dir = ./tests;}; - args = { - inherit pkgs nblib ntlib; - }; - }; - optionsDoc = doclib.mkOptionDocs { - module = { - _module.args.pkgs = pkgs; - imports = [ - nblib.module - ]; - }; - roots = [ - { - url = "https://gitlab.com/TECHNOFAB/nixible/-/blob/main/lib"; - path = toString ./lib; - } - ]; - }; - optionsDocs = pkgs.runCommand "options-docs" {} '' - mkdir -p $out - ln -s ${optionsDoc} $out/options.md - ''; - }; - }; }; - - inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; - - # flake & devenv related - flake-parts.url = "github:hercules-ci/flake-parts"; - systems.url = "github:nix-systems/default-linux"; - devenv.url = "github:cachix/devenv"; - treefmt-nix.url = "github:numtide/treefmt-nix"; - nix-gitlab-ci.url = "gitlab:technofab/nix-gitlab-ci?dir=lib"; - nixtest.url = "gitlab:technofab/nixtest?dir=lib"; - nix-mkdocs.url = "gitlab:technofab/nixmkdocs?dir=lib"; - mkdocs-material-umami.url = "gitlab:technofab/mkdocs-material-umami"; - }; - - nixConfig = { - extra-substituters = [ - "https://cache.nixos.org/" - "https://nix-community.cachix.org" - "https://devenv.cachix.org" - ]; - - extra-trusted-public-keys = [ - "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" - "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" - "devenv.cachix.org-1:w1cLUi8dv3hnoSPGAuibQv+f9TZLr6cv/Hm9XgU50cw=" - ]; - }; } diff --git a/lib/ansible-core.nix b/lib/ansible-core.nix deleted file mode 100644 index dfa3cbc..0000000 --- a/lib/ansible-core.nix +++ /dev/null @@ -1,92 +0,0 @@ -{ - lib, - buildPythonPackage, - fetchPypi, - installShellFiles, - docutils, - setuptools, - cryptography, - jinja2, - junit-xml, - lxml, - ncclient, - packaging, - paramiko, - ansible-pylibssh, - pexpect, - psutil, - pycrypto, - pyyaml, - requests, - resolvelib, - scp, - windowsSupport ? false, - pywinrm, - xmltodict, -}: -buildPythonPackage rec { - pname = "ansible-core"; - version = "2.19.2"; - pyproject = true; - - src = fetchPypi { - pname = "ansible_core"; - inherit version; - hash = "sha256-h/y7xJLtFutq2wN5uuCtv2nzzoioRA5+iODc76n4pUw="; - }; - - # ansible_connection is already wrapped, so don't pass it through - # the python interpreter again, as it would break execution of - # connection plugins. - postPatch = '' - patchShebangs --build packaging/cli-doc/build.py - - SETUPTOOLS_PATTERN='"setuptools[0-9 <>=.,]+"' - WHEEL_PATTERN='"wheel[0-9 <>=.,]+"' - echo "Patching pyproject.toml" - # print replaced patterns to stdout - sed -r -i -e 's/'"$SETUPTOOLS_PATTERN"'/"setuptools"/w /dev/stdout' \ - -e 's/'"$WHEEL_PATTERN"'/"wheel"/w /dev/stdout' pyproject.toml - ''; - - nativeBuildInputs = [ - installShellFiles - docutils - ]; - - build-system = [setuptools]; - - dependencies = - [ - # from requirements.txt - cryptography - jinja2 - packaging - pyyaml - resolvelib - # optional dependencies - junit-xml - lxml - ncclient - paramiko - ansible-pylibssh - pexpect - psutil - pycrypto - requests - scp - xmltodict - ] - ++ lib.optionals windowsSupport [pywinrm]; - - pythonRelaxDeps = ["resolvelib"]; - - postInstall = '' - export HOME="$(mktemp -d)" - packaging/cli-doc/build.py man --output-dir=man - installManPage man/* - ''; - - # internal import errors, missing dependencies - doCheck = false; -} diff --git a/lib/module.nix b/lib/module.nix index 5624d58..9bb230c 100644 --- a/lib/module.nix +++ b/lib/module.nix @@ -10,7 +10,7 @@ name = "unset"; description = "unset"; descriptionClass = "noun"; - check = value: true; + check = value: isType "unset"; }; unset = { _type = "unset"; @@ -33,12 +33,18 @@ else value; mkUnsetOption = args: - mkOption args - // { - type = unsetOr args.type; - default = args.default or unset; - defaultText = literalExpression "unset"; - }; + mkOption (args + // { + type = unsetOr args.type; + default = args.default or unset; + defaultText = literalExpression "unset"; + }); + # no "getSubOptions" here, otherwise its infinite recursion + mkUnsetOptionNoSub = args: + mkUnsetOption (args + // { + type = (types.either unsetType args.type) // {inherit (args.type) description;}; + }); collectionType = types.submodule { options = { @@ -73,14 +79,14 @@ Register the task's output to a variable. ''; }; - block = mkUnsetOption { - type = types.listOf tasksType; + block = mkUnsetOptionNoSub { + type = types.listOf (tasksType // {description = "tasksType";}); description = '' A block of tasks to execute. ''; }; - rescue = mkUnsetOption { - type = types.listOf tasksType; + rescue = mkUnsetOptionNoSub { + type = types.listOf (tasksType // {description = "tasksType";}); description = '' A list of tasks to execute on failure of block tasks. ''; @@ -189,9 +195,19 @@ in { options = { ansiblePackage = mkOption { type = types.package; - default = pkgs.python3Packages.callPackage ./ansible-core.nix {}; + default = pkgs.ansible.overridePythonAttrs (before: { + # filter out "ansible" (non-core) since its useless for nixible and just bloats stuff... + dependencies = builtins.filter (el: el.pname != "ansible") before.dependencies; + }); + defaultText = literalExpression '' + pkgs.ansible.overridePythonAttrs (before: { + dependencies = builtins.filter (el: el.pname != "ansible") before.dependencies; + }) + ''; description = '' - The Ansible package to use. The default package is optimized for size, by not including the gazillion collections that pkgs.ansible and pkgs.ansible-core include. + The Ansible package to use. + The default package is optimized for size, by not including the gazillion collections that + `pkgs.ansible` and `pkgs.ansible-core` include by default. ''; example = literalExpression "pkgs.ansible"; }; @@ -216,7 +232,7 @@ in { }; playbook = mkOption { type = playbookType; - apply = res: filterUnset res; + # apply = res: filterUnset res; description = "The actual playbook, defined as a Nix data structure"; example = [ { @@ -273,7 +289,7 @@ in { }; config = { inventoryFile = (pkgs.formats.json {}).generate "inventory.json" config.inventory; - playbookFile = (pkgs.formats.yaml {}).generate "playbook.yml" config.playbook; + playbookFile = (pkgs.formats.yaml {}).generate "playbook.yml" (filterUnset config.playbook); installedCollections = pkgs.callPackage ./ansible-collections.nix {} config.ansiblePackage config.collections; cli = pkgs.writeShellApplication { name = "nixible"; @@ -283,13 +299,15 @@ in { if config.inventory != {} then "-i ${config.inventoryFile}" else ""; - in '' - set -euo pipefail - export ANSIBLE_COLLECTIONS_PATH=${config.installedCollections} + in + # sh + '' + set -euo pipefail + export ANSIBLE_COLLECTIONS_PATH=${config.installedCollections} - git_repo=$(git rev-parse --show-toplevel 2>/dev/null || true) - ${config.ansiblePackage}/bin/ansible-playbook ${inventoryStr} ${config.playbookFile} -e "pwd=$(pwd)" -e "git_root=$git_repo" "$@" - ''; + git_repo=$(git rev-parse --show-toplevel 2>/dev/null || true) + ${config.ansiblePackage}/bin/ansible-playbook ${inventoryStr} ${config.playbookFile} -e "pwd=$(pwd)" -e "git_root=$git_repo" "$@" + ''; }; }; } diff --git a/nix/repo/ci.nix b/nix/repo/ci.nix new file mode 100644 index 0000000..e3868a2 --- /dev/null +++ b/nix/repo/ci.nix @@ -0,0 +1,45 @@ +{inputs, ...}: let + inherit (inputs) cilib; +in + cilib.mkCI { + pipelines."default" = { + stages = ["test" "build" "deploy"]; + jobs = { + "test:lib" = { + stage = "test"; + script = [ + "nix run .#tests -- --junit=junit.xml" + ]; + allow_failure = true; + artifacts = { + when = "always"; + reports.junit = "junit.xml"; + }; + }; + "docs" = { + stage = "build"; + script = [ + # sh + '' + nix build .#docs:default + mkdir -p public + cp -r result/. public/ + '' + ]; + artifacts.paths = ["public"]; + }; + "pages" = { + nix.enable = false; + image = "alpine:latest"; + stage = "deploy"; + script = ["true"]; + artifacts.paths = ["public"]; + rules = [ + { + "if" = "$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH"; + } + ]; + }; + }; + }; + } diff --git a/nix/repo/devShells.nix b/nix/repo/devShells.nix new file mode 100644 index 0000000..da44426 --- /dev/null +++ b/nix/repo/devShells.nix @@ -0,0 +1,46 @@ +{ + inputs, + cell, + ... +}: let + inherit (inputs) pkgs devshell treefmt devtools-lib; + inherit (cell) soonix; + treefmtWrapper = treefmt.mkWrapper pkgs { + projectRootFile = "flake.nix"; + programs = { + alejandra.enable = true; + mdformat.enable = true; + }; + settings.formatter.mdformat.command = let + pkg = pkgs.python3.withPackages (p: [ + p.mdformat + p.mdformat-mkdocs + ]); + in "${pkg}/bin/mdformat"; + }; +in { + default = devshell.mkShell { + imports = [soonix.devshellModule devtools-lib.devshellModule]; + packages = [ + treefmtWrapper + ]; + lefthook.config = { + "pre-commit" = { + parallel = true; + jobs = [ + { + name = "treefmt"; + stage_fixed = true; + run = "${treefmtWrapper}/bin/treefmt"; + env.TERM = "dumb"; + } + { + name = "soonix"; + stage_fixed = true; + run = "nix run .#soonix:update"; + } + ]; + }; + }; + }; +} diff --git a/nix/repo/docs.nix b/nix/repo/docs.nix new file mode 100644 index 0000000..de28482 --- /dev/null +++ b/nix/repo/docs.nix @@ -0,0 +1,64 @@ +{inputs, ...}: let + inherit (inputs) pkgs doclib nblib; + + optionsDoc = doclib.mkOptionDocs { + module = nblib.module; + roots = [ + { + url = "https://gitlab.com/TECHNOFAB/nixible/-/blob/main/lib"; + path = "${inputs.self}/lib"; + } + ]; + }; + optionsDocs = pkgs.runCommand "options-docs" {} '' + mkdir -p $out + ln -s ${optionsDoc} $out/options.md + ''; +in + (doclib.mkDocs { + docs."default" = { + base = "${inputs.self}"; + path = "${inputs.self}/docs"; + material = { + enable = true; + colors = { + primary = "black"; + accent = "blue"; + }; + umami = { + enable = true; + src = "https://analytics.tf/umami"; + siteId = "d8354dfa-2ad2-4089-90d2-899b981aef22"; + domains = ["nixible.projects.tf"]; + }; + }; + macros = { + enable = true; + includeDir = toString optionsDocs; + }; + config = { + site_name = "Nixible"; + site_url = "https://nixible.projects.tf"; + repo_name = "TECHNOFAB/nixible"; + repo_url = "https://gitlab.com/TECHNOFAB/nixible"; + extra_css = ["style.css"]; + theme = { + logo = "images/logo.svg"; + icon.repo = "simple/gitlab"; + favicon = "images/logo.svg"; + }; + nav = [ + {"Introduction" = "index.md";} + {"Usage" = "usage.md";} + {"Examples" = "examples.md";} + {"Reference" = "reference.md";} + {"Options" = "options.md";} + ]; + markdown_extensions = [ + "pymdownx.superfences" + "admonition" + ]; + }; + }; + }).packages + // {inherit optionsDocs;} diff --git a/nix/repo/flake.lock b/nix/repo/flake.lock new file mode 100644 index 0000000..9cf1853 --- /dev/null +++ b/nix/repo/flake.lock @@ -0,0 +1,136 @@ +{ + "nodes": { + "devshell-lib": { + "locked": { + "dir": "lib", + "lastModified": 1758204313, + "narHash": "sha256-ainbY0Oajb1HMdvy+A8QxF/P5qwcbEzJGEY5pzKdDdc=", + "owner": "rensa-nix", + "repo": "devshell", + "rev": "7d0c4bc78d9f017a739b0c7eb2f4e563118353e6", + "type": "gitlab" + }, + "original": { + "dir": "lib", + "owner": "rensa-nix", + "repo": "devshell", + "type": "gitlab" + } + }, + "devtools-lib": { + "locked": { + "dir": "lib", + "lastModified": 1766237846, + "narHash": "sha256-7n3WFabnf49SFHXD/e4zfLit3BniZZOecUXfBm3d1d0=", + "owner": "rensa-nix", + "repo": "devtools", + "rev": "5c8712f48c5bcb6b79d3da1afd1268f84f5e35e3", + "type": "gitlab" + }, + "original": { + "dir": "lib", + "owner": "rensa-nix", + "repo": "devtools", + "type": "gitlab" + } + }, + "nix-gitlab-ci-lib": { + "locked": { + "dir": "lib", + "lastModified": 1765444672, + "narHash": "sha256-B0cMjRs9P50ym9Le0VUcRN69Yy6tbV13MXq81tTTEus=", + "owner": "TECHNOFAB", + "repo": "nix-gitlab-ci", + "rev": "8f88a53b5479773cd626420362631bc1da99e677", + "type": "gitlab" + }, + "original": { + "dir": "lib", + "owner": "TECHNOFAB", + "ref": "3.1.2", + "repo": "nix-gitlab-ci", + "type": "gitlab" + } + }, + "nixmkdocs-lib": { + "locked": { + "dir": "lib", + "lastModified": 1763481845, + "narHash": "sha256-Bp0+9rDmlPWMcnKqGx+BG4+o5KO8FuDAOvXRnXrm3Fo=", + "owner": "TECHNOFAB", + "repo": "nixmkdocs", + "rev": "73d59093df94a894d25bc4bf71880b6f00faa62f", + "type": "gitlab" + }, + "original": { + "dir": "lib", + "owner": "TECHNOFAB", + "repo": "nixmkdocs", + "type": "gitlab" + } + }, + "nixtest-lib": { + "locked": { + "dir": "lib", + "lastModified": 1766514204, + "narHash": "sha256-jK6gHvJJjUpEWrPvraBgstsF7oifatuWsj9suy7GFus=", + "owner": "TECHNOFAB", + "repo": "nixtest", + "rev": "b87e38847d84973e84b6727b24fea48b7bc108c1", + "type": "gitlab" + }, + "original": { + "dir": "lib", + "owner": "TECHNOFAB", + "repo": "nixtest", + "type": "gitlab" + } + }, + "root": { + "inputs": { + "devshell-lib": "devshell-lib", + "devtools-lib": "devtools-lib", + "nix-gitlab-ci-lib": "nix-gitlab-ci-lib", + "nixmkdocs-lib": "nixmkdocs-lib", + "nixtest-lib": "nixtest-lib", + "soonix-lib": "soonix-lib", + "treefmt-nix": "treefmt-nix" + } + }, + "soonix-lib": { + "locked": { + "dir": "lib", + "lastModified": 1763323017, + "narHash": "sha256-MJyg37d+VMfRoFiVUj16FW+zkEwQXbgK9LoFF/SHoxA=", + "owner": "TECHNOFAB", + "repo": "soonix", + "rev": "078034b01e4eaf1f9436d46721f7cbe0d96eb8b4", + "type": "gitlab" + }, + "original": { + "dir": "lib", + "owner": "TECHNOFAB", + "repo": "soonix", + "type": "gitlab" + } + }, + "treefmt-nix": { + "flake": false, + "locked": { + "lastModified": 1762938485, + "narHash": "sha256-AlEObg0syDl+Spi4LsZIBrjw+snSVU4T8MOeuZJUJjM=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "5b4ee75aeefd1e2d5a1cc43cf6ba65eba75e83e4", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/nix/repo/flake.nix b/nix/repo/flake.nix new file mode 100644 index 0000000..ccc3b0f --- /dev/null +++ b/nix/repo/flake.nix @@ -0,0 +1,25 @@ +{ + inputs = { + devshell-lib.url = "gitlab:rensa-nix/devshell?dir=lib"; + devtools-lib.url = "gitlab:rensa-nix/devtools?dir=lib"; + soonix-lib.url = "gitlab:TECHNOFAB/soonix?dir=lib"; + nix-gitlab-ci-lib.url = "gitlab:TECHNOFAB/nix-gitlab-ci/3.1.2?dir=lib"; + nixmkdocs-lib.url = "gitlab:TECHNOFAB/nixmkdocs?dir=lib"; + nixtest-lib.url = "gitlab:TECHNOFAB/nixtest?dir=lib"; + treefmt-nix = { + url = "github:numtide/treefmt-nix"; + flake = false; + }; + }; + outputs = i: + i + // { + devshell = i.devshell-lib.lib {inherit (i.parent) pkgs;}; + soonix = i.soonix-lib.lib {inherit (i.parent) pkgs;}; + cilib = i.nix-gitlab-ci-lib.lib {inherit (i.parent) pkgs;}; + ntlib = i.nixtest-lib.lib {inherit (i.parent) pkgs;}; + doclib = i.nixmkdocs-lib.lib {inherit (i.parent) pkgs;}; + nblib = import "${i.parent.self}/lib" {inherit (i.parent) pkgs;}; + treefmt = import i.treefmt-nix; + }; +} diff --git a/nix/repo/soonix.nix b/nix/repo/soonix.nix new file mode 100644 index 0000000..e98e2b7 --- /dev/null +++ b/nix/repo/soonix.nix @@ -0,0 +1,39 @@ +{ + inputs, + cell, + ... +}: let + inherit (inputs) soonix; + inherit (cell) ci; +in + (soonix.make { + hooks = { + ci = ci.soonix; + renovate = { + output = ".gitlab/renovate.json5"; + data = { + extends = ["config:recommended"]; + postUpgradeTasks = { + commands = [ + "nix-portable nix run .#soonix:update" + ]; + executionMode = "branch"; + }; + lockFileMaintenance = { + enabled = true; + extends = ["schedule:monthly"]; + + branchTopic = "lock-file-maintenance-{{packageFile}}"; + commitMessageExtra = "({{packageFile}})"; + }; + nix.enabled = true; + gitlabci.enabled = false; + }; + hook = { + mode = "copy"; + gitignore = false; + }; + opts.format = "json"; + }; + }; + }).config diff --git a/nix/repo/tests.nix b/nix/repo/tests.nix new file mode 100644 index 0000000..3c02401 --- /dev/null +++ b/nix/repo/tests.nix @@ -0,0 +1,10 @@ +{inputs, ...}: let + inherit (inputs) pkgs ntlib nblib; +in { + tests = ntlib.mkNixtest { + modules = ntlib.autodiscover {dir = "${inputs.self}/tests";}; + args = { + inherit pkgs ntlib nblib; + }; + }; +} diff --git a/tests/cli_test.nix b/tests/cli_test.nix index 06ec865..b13bd10 100644 --- a/tests/cli_test.nix +++ b/tests/cli_test.nix @@ -25,6 +25,7 @@ in # sh '' + ${ntlib.helpers.path [pkgs.gnugrep]} ${ntlib.helpers.scriptHelpers} # check that dependencies are included in runtime inputs @@ -54,6 +55,7 @@ in # sh '' + ${ntlib.helpers.path [pkgs.gnugrep]} ${ntlib.helpers.scriptHelpers} # check CLI is executable @@ -82,6 +84,7 @@ in # sh '' + ${ntlib.helpers.path [pkgs.gnugrep]} ${ntlib.helpers.scriptHelpers} assert_file_contains "${cli}/bin/nixible" 'export ANSIBLE_COLLECTIONS_PATH=' "should export collections path" @@ -107,6 +110,7 @@ in # sh '' + ${ntlib.helpers.path [pkgs.gnugrep]} ${ntlib.helpers.scriptHelpers} # check runtime dependencies are properly included diff --git a/tests/fixtures/flake_parts/flake.lock b/tests/fixtures/flake_parts/flake.lock new file mode 100644 index 0000000..15b9835 --- /dev/null +++ b/tests/fixtures/flake_parts/flake.lock @@ -0,0 +1,77 @@ +{ + "nodes": { + "flake-parts": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1754487366, + "narHash": "sha256-pHYj8gUBapuUzKV/kN/tR3Zvqc7o6gdFB9XKXIp1SQ8=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "af66ad14b28a127c5c0f3bbb298218fc63528a18", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1756636162, + "narHash": "sha256-mBecwgUTWRgClJYqcF+y4O1bY8PQHqeDpB+zsAn+/zA=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "37ff64b7108517f8b6ba5705ee5085eac636a249", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-lib": { + "locked": { + "lastModified": 1753579242, + "narHash": "sha256-zvaMGVn14/Zz8hnp4VWT9xVnhc8vuL3TStRqwk22biA=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "0f36c44e01a6129be94e3ade315a5883f0228a6e", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-parts": "flake-parts", + "nixpkgs": "nixpkgs", + "systems": "systems" + } + }, + "systems": { + "locked": { + "lastModified": 1689347949, + "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=", + "owner": "nix-systems", + "repo": "default-linux", + "rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default-linux", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/tests/fixtures/flake_parts/flake.nix b/tests/fixtures/flake_parts/flake.nix new file mode 100644 index 0000000..611451d --- /dev/null +++ b/tests/fixtures/flake_parts/flake.nix @@ -0,0 +1,37 @@ +{ + outputs = { + flake-parts, + systems, + ... + } @ inputs: + flake-parts.lib.mkFlake {inherit inputs;} { + imports = [ + "@repo_path@/lib/flakeModule.nix" + ]; + systems = import systems; + flake = {}; + perSystem = _: { + nixible = { + "hello".playbook = [ + { + name = "Hello World"; + hosts = "localhost"; + tasks = [ + { + name = "Say hello"; + debug.msg = "Hello from Nixible!"; + } + ]; + } + ]; + "test".playbook = []; + }; + }; + }; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + flake-parts.url = "github:hercules-ci/flake-parts"; + systems.url = "github:nix-systems/default-linux"; + }; +} diff --git a/tests/flake_parts_test.nix b/tests/flake_parts_test.nix new file mode 100644 index 0000000..a523857 --- /dev/null +++ b/tests/flake_parts_test.nix @@ -0,0 +1,39 @@ +{ + pkgs, + ntlib, + ... +}: { + suites."flake-parts" = { + pos = __curPos; + tests = [ + { + name = "flakeModule"; + type = "script"; + script = + # sh + '' + ${ntlib.helpers.path (with pkgs; [coreutils nix gnused gnugrep jq])} + ${ntlib.helpers.scriptHelpers} + export SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt + export NIX_SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt + repo_path=${../.} + + cp ${./fixtures/flake_parts}/* . + # import from the absolute path above, is easier than trying to figure out the repo path etc. + sed -i -e "s|@repo_path@|$repo_path|" flake.nix + + # NOTE: --impure is required since importing modules from absolute paths is not allowed in pure mode + nix build --impure .#nixible:test + assert "-f result/bin/nixible" "should exist" + assert_file_contains "result/bin/nixible" "ANSIBLE_COLLECTIONS_PATH" + assert_file_contains "result/bin/nixible" "ansible-playbook" + + nix build --impure .#nixible:hello + assert "-f result/bin/nixible" "should exist" + assert_file_contains "result/bin/nixible" "ANSIBLE_COLLECTIONS_PATH" + assert_file_contains "result/bin/nixible" "ansible-playbook" + ''; + } + ]; + }; +} diff --git a/tests/integration_test.nix b/tests/integration_test.nix index ec49be5..7605657 100644 --- a/tests/integration_test.nix +++ b/tests/integration_test.nix @@ -84,6 +84,7 @@ in # sh '' + ${ntlib.helpers.path [pkgs.gnugrep]} ${ntlib.helpers.scriptHelpers} assert "-f ${result.config.inventoryFile}" "SOPS example should generate inventory" diff --git a/tests/lib_test.nix b/tests/lib_test.nix index 3be6245..1a250ef 100644 --- a/tests/lib_test.nix +++ b/tests/lib_test.nix @@ -28,6 +28,7 @@ in # sh '' + ${ntlib.helpers.path [pkgs.gnugrep]} ${ntlib.helpers.scriptHelpers} # Check CLI contains expected content @@ -113,6 +114,7 @@ in # sh '' + ${ntlib.helpers.path [pkgs.gnugrep]} ${ntlib.helpers.scriptHelpers} # Check playbook file exists @@ -143,6 +145,7 @@ in # sh '' + ${ntlib.helpers.path [pkgs.gnugrep]} ${ntlib.helpers.scriptHelpers} # check that custom ansible package is used From 1ac485e44206f483bbd3286fe6dfa046133d8cb2 Mon Sep 17 00:00:00 2001 From: technofab Date: Wed, 31 Dec 2025 18:33:26 +0100 Subject: [PATCH 2/3] chore(devShell): add cocogitto --- nix/repo/devShells.nix | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/nix/repo/devShells.nix b/nix/repo/devShells.nix index da44426..830dff5 100644 --- a/nix/repo/devShells.nix +++ b/nix/repo/devShells.nix @@ -42,5 +42,22 @@ in { ]; }; }; + cocogitto.config = { + tag_prefix = "v"; + ignore_merge_commits = true; + changelog = { + authors = [ + { + username = "TECHNOFAB"; + signature = "technofab"; + } + ]; + path = "CHANGELOG.md"; + template = "remote"; + remote = "gitlab.com"; + repository = "nixible"; + owner = "TECHNOFAB"; + }; + }; }; } From 259818ec96fa8ca9f36e0fbb04de2f500a5d96c6 Mon Sep 17 00:00:00 2001 From: technofab Date: Wed, 31 Dec 2025 18:34:13 +0100 Subject: [PATCH 3/3] fix(module): typo --- lib/module.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/module.nix b/lib/module.nix index 9bb230c..845c241 100644 --- a/lib/module.nix +++ b/lib/module.nix @@ -10,7 +10,7 @@ name = "unset"; description = "unset"; descriptionClass = "noun"; - check = value: isType "unset"; + check = isType "unset"; }; unset = { _type = "unset";