From 012a3afb2dfba45765efdcd089a3a341d921ec04 Mon Sep 17 00:00:00 2001 From: technofab Date: Thu, 18 Dec 2025 13:32:38 +0100 Subject: [PATCH 1/3] feat: switch from flake-parts & devenv to rensa + add nixtest --- .envrc | 6 +- .gitlab-ci.yml | 9 +- .gitlab/renovate.json5 | 23 ++ flake.lock | 434 ++---------------------------- flake.nix | 232 +++------------- nix/repo/apps.nix | 18 ++ nix/repo/ci.nix | 55 ++++ nix/repo/devShells.nix | 29 ++ nix/repo/docs.nix | 61 +++++ nix/repo/flake.lock | 118 ++++++++ nix/repo/flake.nix | 27 ++ nix/repo/nixlets.nix | 4 + nix/repo/soonix.nix | 37 +++ nix/repo/tests.nix | 16 ++ tests/fixtures/example/nixlet.nix | 6 + tests/fixtures/example/values.nix | 12 + tests/lib_test.nix | 47 ++++ tests/render_test.nix | 30 +++ 18 files changed, 553 insertions(+), 611 deletions(-) create mode 100644 .gitlab/renovate.json5 create mode 100644 nix/repo/apps.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/nixlets.nix create mode 100644 nix/repo/soonix.nix create mode 100644 nix/repo/tests.nix create mode 100644 tests/fixtures/example/nixlet.nix create mode 100644 tests/fixtures/example/values.nix create mode 100644 tests/lib_test.nix create mode 100644 tests/render_test.nix diff --git a/.envrc b/.envrc index a2d9328..565a52a 100644 --- a/.envrc +++ b/.envrc @@ -1,4 +1,2 @@ -if ! use flake . --impure -then - echo "devenv could not be build. The devenv environment was not loaded. Make the necessary changes to flake.nix and hit enter to try again." >&2 -fi +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/.gitlab-ci.yml b/.gitlab-ci.yml index e48e6d2..7d70f67 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,6 +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 - cache_files: ["ci.nix", "flake.*"] - +- 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..0ec29b2 --- /dev/null +++ b/.gitlab/renovate.json5 @@ -0,0 +1,23 @@ +{ + "extends": [ + "config:recommended" + ], + "gitlabci": { + "enabled": false + }, + "lockFileMaintenance": { + "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 a71fb5a..a018ecb 100644 --- a/flake.lock +++ b/flake.lock @@ -1,90 +1,6 @@ { "nodes": { - "cachix": { - "inputs": { - "devenv": [ - "devenv" - ], - "flake-compat": [ - "devenv" - ], - "git-hooks": [ - "devenv" - ], - "nixpkgs": "nixpkgs" - }, - "locked": { - "lastModified": 1728672398, - "narHash": "sha256-KxuGSoVUFnQLB2ZcYODW7AVPAh9JqRlD5BrfsC/Q4qs=", - "owner": "cachix", - "repo": "cachix", - "rev": "aac51f698309fd0f381149214b7eee213c66ef0a", - "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_3" - }, - "locked": { - "lastModified": 1732460433, - "narHash": "sha256-ve3DZpwbVNTdohE2RxA7QdCvByHNHu38+oZHjVGK6Ok=", - "owner": "cachix", - "repo": "devenv", - "rev": "6f9f633c50265c836aa685feefe15ea2a8865d28", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "devenv", - "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-compat_2": { - "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-compat_3": { "flake": false, "locked": { "lastModified": 1673956053, @@ -100,91 +16,9 @@ "type": "github" } }, - "flake-parts": { - "inputs": { - "nixpkgs-lib": [ - "devenv", - "nix", - "nixpkgs" - ] - }, - "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" - } - }, - "flake-parts_2": { - "inputs": { - "nixpkgs-lib": "nixpkgs-lib" - }, - "locked": { - "lastModified": 1730504689, - "narHash": "sha256-hgmguH29K2fvs9szpq2r3pz2/8cJd2LPS+b4tfNFCwE=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "506278e768c2a08bec68eb62932193e341f55c90", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "flake-parts", - "type": "github" - } - }, - "git-hooks": { - "inputs": { - "flake-compat": "flake-compat_2", - "gitignore": "gitignore", - "nixpkgs": "nixpkgs_4", - "nixpkgs-stable": "nixpkgs-stable" - }, - "locked": { - "lastModified": 1732021966, - "narHash": "sha256-mnTbjpdqF0luOkou8ZFi2asa1N3AA2CchR/RqCNmsGE=", - "owner": "cachix", - "repo": "git-hooks.nix", - "rev": "3308484d1a443fc5bc92012435d79e80458fe43c", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "git-hooks.nix", - "type": "github" - } - }, - "gitignore": { - "inputs": { - "nixpkgs": [ - "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" - } - }, "kubenix": { "inputs": { - "flake-compat": "flake-compat_3", + "flake-compat": "flake-compat", "nixpkgs": [ "nixpkgs" ], @@ -205,112 +39,13 @@ "type": "github" } }, - "libgit2": { - "flake": false, - "locked": { - "lastModified": 1697646580, - "narHash": "sha256-oX4Z3S9WtJlwvj0uH9HlYcWv+x1hqp8mhXl7HsLu2f0=", - "owner": "libgit2", - "repo": "libgit2", - "rev": "45fd9ed7ae1a9b74b957ef4f337bc3c8b3df01b5", - "type": "github" - }, - "original": { - "owner": "libgit2", - "repo": "libgit2", - "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-parts": "flake-parts", - "libgit2": "libgit2", - "nixpkgs": "nixpkgs_2", - "nixpkgs-23-11": [ - "devenv" - ], - "nixpkgs-regression": [ - "devenv" - ], - "pre-commit-hooks": [ - "devenv" - ] - }, - "locked": { - "lastModified": 1727438425, - "narHash": "sha256-X8ES7I1cfNhR9oKp06F6ir4Np70WGZU5sfCOuNBEwMg=", - "owner": "domenkozar", - "repo": "nix", - "rev": "f6c5ae4c1b2e411e6b1e6a8181cc84363d6a7546", - "type": "github" - }, - "original": { - "owner": "domenkozar", - "ref": "devenv-2.24", - "repo": "nix", - "type": "github" - } - }, - "nix-gitlab-ci": { - "locked": { - "dir": "lib", - "lastModified": 1749124633, - "narHash": "sha256-vgYHrbAFRfgNYysW74Eam/S7KruYWMLCHG4U32xgHKY=", - "owner": "TECHNOFAB", - "repo": "nix-gitlab-ci", - "rev": "f121b10dc9a7417906a886154e3065410a72462d", - "type": "gitlab" - }, - "original": { - "dir": "lib", - "owner": "TECHNOFAB", - "ref": "2.1.0", - "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": 1730531603, - "narHash": "sha256-Dqg6si5CqIzm87sp57j5nTaeBbWhHFaVyG7V6L8k3lY=", + "lastModified": 1765779637, + "narHash": "sha256-KJ2wa/BLSrTqDjbfyNx70ov/HdgNBCBBSQP3BIzKnv4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "7ffd9ae656aec493492b44d0ddfb28e79a1ea25d", + "rev": "1306659b587dc277866c7b69eb97e5f07864d8c4", "type": "github" }, "original": { @@ -322,124 +57,44 @@ }, "nixpkgs-lib": { "locked": { - "lastModified": 1730504152, - "narHash": "sha256-lXvH/vOfb4aGYyvFmZK/HlsNsr/0CVWlwYvo2rxJk3s=", - "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/cc2f28000298e1269cea6612cd06ec9979dd5d7f.tar.gz" - }, - "original": { - "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/cc2f28000298e1269cea6612cd06ec9979dd5d7f.tar.gz" - } - }, - "nixpkgs-stable": { - "locked": { - "lastModified": 1730741070, - "narHash": "sha256-edm8WG19kWozJ/GqyYx2VjW99EdhjKwbY3ZwdlPAAlo=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "d063c1dd113c91ab27959ba540c0d9753409edf3", + "lastModified": 1754184128, + "narHash": "sha256-AjhoyBL4eSyXf01Bmc6DiuaMrJRNdWopmdnMY0Pa/M0=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "02e72200e6d56494f4a7c0da8118760736e41b60", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "nixos-24.05", - "repo": "nixpkgs", + "owner": "nix-community", + "repo": "nixpkgs.lib", "type": "github" } }, - "nixpkgs_2": { + "ren": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, "locked": { - "lastModified": 1717432640, - "narHash": "sha256-+f9c4/ZX5MWDOuB1rKoWj+lBNm0z0rs4CK47HBLxy1o=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "88269ab3044128b7c2f4c7d68448b2fb50456870", - "type": "github" + "dir": "lib", + "lastModified": 1758738378, + "narHash": "sha256-NjzqdvQCDDdObEBH8x/vdhbdhrIB+N9E570uCdksGHY=", + "owner": "rensa-nix", + "repo": "core", + "rev": "abe19f9f13aff41de2b63304545c87d193d19ef4", + "type": "gitlab" }, "original": { - "owner": "NixOS", - "ref": "release-24.05", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_3": { - "locked": { - "lastModified": 1716977621, - "narHash": "sha256-Q1UQzYcMJH4RscmpTkjlgqQDX5yi1tZL0O345Ri6vXQ=", - "owner": "cachix", - "repo": "devenv-nixpkgs", - "rev": "4267e705586473d3e5c8d50299e71503f16a6fb6", - "type": "github" - }, - "original": { - "owner": "cachix", - "ref": "rolling", - "repo": "devenv-nixpkgs", - "type": "github" - } - }, - "nixpkgs_4": { - "locked": { - "lastModified": 1730768919, - "narHash": "sha256-8AKquNnnSaJRXZxc5YmF/WfmxiHX6MMZZasRP6RRQkE=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "a04d33c0c3f1a59a2c1cb0c6e34cd24500e5a1dc", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_5": { - "locked": { - "lastModified": 1732238832, - "narHash": "sha256-sQxuJm8rHY20xq6Ah+GwIUkF95tWjGRd1X8xF+Pkk38=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "8edf06bea5bcbee082df1b7369ff973b91618b8d", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_6": { - "locked": { - "lastModified": 1731890469, - "narHash": "sha256-D1FNZ70NmQEwNxpSSdTXCSklBH1z2isPR84J6DQrJGs=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "5083ec887760adfe12af64830a66807423a859a7", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" + "dir": "lib", + "owner": "rensa-nix", + "repo": "core", + "type": "gitlab" } }, "root": { "inputs": { - "devenv": "devenv", - "flake-parts": "flake-parts_2", - "git-hooks": "git-hooks", "kubenix": "kubenix", - "mkdocs-material-umami": "mkdocs-material-umami", - "nix-gitlab-ci": "nix-gitlab-ci", - "nix-mkdocs": "nix-mkdocs", - "nixpkgs": "nixpkgs_5", - "systems": "systems_2", - "treefmt-nix": "treefmt-nix" + "nixpkgs": "nixpkgs", + "ren": "ren" } }, "systems": { @@ -456,21 +111,6 @@ "type": "indirect" } }, - "systems_2": { - "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": { "inputs": { "nixpkgs": [ @@ -491,24 +131,6 @@ "repo": "treefmt-nix", "type": "github" } - }, - "treefmt-nix": { - "inputs": { - "nixpkgs": "nixpkgs_6" - }, - "locked": { - "lastModified": 1732292307, - "narHash": "sha256-5WSng844vXt8uytT5djmqBCkopyle6ciFgteuA9bJpw=", - "owner": "numtide", - "repo": "treefmt-nix", - "rev": "705df92694af7093dfbb27109ce16d828a79155f", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "treefmt-nix", - "type": "github" - } } }, "root": "root", diff --git a/flake.nix b/flake.nix index d982071..67b9843 100644 --- a/flake.nix +++ b/flake.nix @@ -1,205 +1,45 @@ { - outputs = { - self, - nixpkgs, - flake-parts, - systems, - ... - } @ inputs: let - nixlet-lib = import ./lib { - inherit (nixpkgs) lib; - inherit (inputs) kubenix; - }; - in - flake-parts.lib.mkFlake {inherit inputs;} { - imports = [ - inputs.devenv.flakeModule - inputs.nix-gitlab-ci.flakeModule - inputs.nix-mkdocs.flakeModule - inputs.treefmt-nix.flakeModule - ]; - systems = import systems; - flake = { - nixlets = import ./nixlets {inherit nixlet-lib;}; - }; - perSystem = { - lib, - pkgs, - config, - system, - ... - }: { - imports = [ - ./ci.nix - ]; - treefmt = { - 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 - lib.mkForce "${pkg}/bin/mdformat"; - }; - devenv.shells.default = { - containers = lib.mkForce {}; - packages = with pkgs; [ - kube-linter - ]; - - pre-commit.hooks.treefmt = { - enable = true; - packageOverrides.treefmt = config.treefmt.build.wrapper; - }; - }; - - docs."default".config = { - path = ./docs; - deps = pp: [ - (pp.buildPythonPackage rec { - pname = "mkdocs-gen-files"; - version = "0.5.0"; - pyproject = true; - build-system = [pp.hatchling]; - src = pkgs.fetchFromGitHub { - owner = "oprypin"; - repo = "mkdocs-gen-files"; - rev = "v${version}"; - hash = "sha256-nRRdY7/en42s4PmHH+9vccRIl4pIp1F/Ka1bYvSHpBw="; - }; - dependencies = [pp.mkdocs]; - }) - ]; - material = { - enable = true; - colors = { - primary = "blue"; - accent = "light blue"; - }; - umami = { - enable = true; - src = "https://analytics.tf/umami"; - siteId = "a4181010-317a-45e3-978c-5d07a93e0cd2"; - domains = ["nixlets.projects.tf"]; - }; - }; - config = { - site_name = "Nixlets"; - site_url = "https://nixlets.projects.tf"; - repo_name = "TECHNOFAB/nixlets"; - repo_url = "https://gitlab.com/TECHNOFAB/nixlets"; - extra_css = ["style.css"]; - theme = { - icon.repo = "simple/gitlab"; - logo = "images/logo.svg"; - favicon = "images/logo.svg"; - }; - plugins = [ - { - # bit hacky, but works :D - "gen-files".scripts = let - docsEntries = builtins.toJSON (builtins.mapAttrs (n: v: v.mkDocs {}) self.nixlets); - in [ - (builtins.toFile "gen.py" - # py - '' - import mkdocs_gen_files, json - data = json.loads('${docsEntries}') - for name, file in data.items(): - with open(file, 'r') as infile: - content = infile.read() - with mkdocs_gen_files.open(f"options/{name}.md", "w") as outfile: - outfile.write(content) - '') - ]; - } - ]; - nav = [ - {"Introduction" = "index.md";} - {"Creating Nixlets" = "creation.md";} - {"Packaging" = "packaging.md";} - {"Usage" = "usage.md";} - {"Secrets" = "secrets.md";} - { - "Nixlets Values" = - lib.mapAttrsToList (n: v: { - ${v.name} = "options/${n}.md"; - }) - self.nixlets; - } - ]; - markdown_extensions = [ - { - "pymdownx.highlight".pygments_lang_class = true; - } - "pymdownx.inlinehilite" - "pymdownx.snippets" - "pymdownx.superfences" - "fenced_code" - "admonition" - ]; - }; - }; - - # check if every nixlet successfully renders with default values - checks = - builtins.mapAttrs ( - _: nixlet: - nixlet.render { - inherit system; - } - ) - self.nixlets; - - # allow directly building every nixlet with default values - packages = - builtins.mapAttrs ( - _: nixlet: - nixlet.render { - inherit system; - } - ) - self.nixlets; - - apps.upload = { - type = "app"; - program = pkgs.callPackage nixlet-lib.uploadNixletsToGitlab { - projectId = "55602785"; - nixlets = lib.attrValues self.nixlets; - }; - }; - }; - }; - 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"; - inputs.git-hooks.follows = "git-hooks"; - }; - git-hooks.url = "github:cachix/git-hooks.nix"; - treefmt-nix.url = "github:numtide/treefmt-nix"; - nix-gitlab-ci.url = "gitlab:TECHNOFAB/nix-gitlab-ci/2.1.0?dir=lib"; - nix-mkdocs.url = "gitlab:TECHNOFAB/nixmkdocs?dir=lib"; - mkdocs-material-umami.url = "gitlab:technofab/mkdocs-material-umami"; - + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + ren.url = "gitlab:rensa-nix/core?dir=lib"; kubenix = { url = "github:TECHNOFAB11/kubenix"; inputs.nixpkgs.follows = "nixpkgs"; }; }; - nixConfig = { - extra-trusted-public-keys = "devenv.cachix.org-1:w1cLUi8dv3hnoSPGAuibQv+f9TZLr6cv/Hm9XgU50cw="; - extra-substituters = "https://devenv.cachix.org"; - }; + outputs = { + self, + ren, + ... + } @ inputs: + 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 "docs") + (simple "soonix") + (simple "apps") + (simple "nixlets") + (simple "tests") + ]; + } + { + packages = ren.select self [ + ["repo" "ci" "packages"] + ["repo" "docs"] + ["repo" "soonix" "packages"] + ["repo" "tests"] + ]; + apps = ren.select self ["repo" "apps"]; + nixlets = ren.get self ["repo" "nixlets"]; + }; } diff --git a/nix/repo/apps.nix b/nix/repo/apps.nix new file mode 100644 index 0000000..24bcaad --- /dev/null +++ b/nix/repo/apps.nix @@ -0,0 +1,18 @@ +{ + inputs, + cell, + ... +}: let + inherit (inputs) pkgs nixlet-lib; + inherit (cell) nixlets; +in { + upload = { + type = "app"; + program = + (pkgs.callPackage nixlet-lib.uploadNixletsToGitlab { + projectId = "55602785"; + nixlets = builtins.attrValues nixlets; + }) + + "/bin/nixlets-upload"; + }; +} diff --git a/nix/repo/ci.nix b/nix/repo/ci.nix new file mode 100644 index 0000000..6cae120 --- /dev/null +++ b/nix/repo/ci.nix @@ -0,0 +1,55 @@ +{inputs, ...}: let + inherit (inputs) cilib; +in + cilib.mkCI { + pipelines."default" = { + stages = ["test" "build" "deploy"]; + jobs = { + "test" = { + stage = "test"; + script = [ + # sh + "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";} + ]; + }; + "upload" = { + stage = "deploy"; + rules = [ + {"if" = "$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH";} + ]; + variables.AUTH_HEADER = "JOB-TOKEN: \${CI_JOB_TOKEN}"; + script = [ + # sh + "nix run .#upload --impure" + ]; + }; + }; + }; + } diff --git a/nix/repo/devShells.nix b/nix/repo/devShells.nix new file mode 100644 index 0000000..3ea9415 --- /dev/null +++ b/nix/repo/devShells.nix @@ -0,0 +1,29 @@ +{ + cell, + inputs, + ... +}: let + inherit (inputs) pkgs devshell treefmt; + inherit (cell) soonix; +in { + default = devshell.mkShell { + imports = [soonix.devshellModule]; + packages = [ + pkgs.nil + (treefmt.mkWrapper pkgs { + programs = { + alejandra.enable = true; + deadnix.enable = true; + statix.enable = true; + mdformat.enable = true; + }; + settings.formatter.mdformat.command = let + pkg = pkgs.python3.withPackages (p: [ + p.mdformat + p.mdformat-mkdocs + ]); + in "${pkg}/bin/mdformat"; + }) + ]; + }; +} diff --git a/nix/repo/docs.nix b/nix/repo/docs.nix new file mode 100644 index 0000000..2f5ced7 --- /dev/null +++ b/nix/repo/docs.nix @@ -0,0 +1,61 @@ +{ + inputs, + cell, + ... +}: let + inherit (inputs) doclib; + inherit (cell) nixlets; +in + (doclib.mkDocs { + docs."default" = { + base = "${inputs.self}"; + path = "${inputs.self}/docs"; + material = { + enable = true; + colors = { + primary = "blue"; + accent = "light blue"; + }; + umami = { + enable = true; + src = "https://analytics.tf/umami"; + siteId = "a4181010-317a-45e3-978c-5d07a93e0cd2"; + domains = ["nixlets.projects.tf"]; + }; + }; + dynamic-nav = { + enable = true; + files."Nixlets Values" = builtins.map (val: {${val.name} = val.mkDocs {};}) (builtins.attrValues nixlets); + }; + config = { + site_name = "Nixlets"; + site_url = "https://nixlets.projects.tf"; + repo_name = "TECHNOFAB/nixlets"; + repo_url = "https://gitlab.com/TECHNOFAB/nixlets"; + extra_css = ["style.css"]; + theme = { + logo = "images/logo.svg"; + icon.repo = "simple/gitlab"; + favicon = "images/logo.svg"; + }; + nav = [ + {"Introduction" = "index.md";} + {"Creating Nixlets" = "creation.md";} + {"Packaging" = "packaging.md";} + {"Usage" = "usage.md";} + {"Secrets" = "secrets.md";} + ]; + markdown_extensions = [ + { + "pymdownx.highlight".pygments_lang_class = true; + } + "pymdownx.inlinehilite" + "pymdownx.snippets" + "pymdownx.superfences" + "fenced_code" + "admonition" + ]; + }; + }; + }) + .packages diff --git a/nix/repo/flake.lock b/nix/repo/flake.lock new file mode 100644 index 0000000..cd48965 --- /dev/null +++ b/nix/repo/flake.lock @@ -0,0 +1,118 @@ +{ + "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" + } + }, + "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": 1766000281, + "narHash": "sha256-rtQKu/snzEjZBCyTkZMWUIuvCThtjmVEwBXb6T1mm40=", + "owner": "TECHNOFAB", + "repo": "nixmkdocs", + "rev": "6999c026457d7dee3a7ab336cd4d1b38bae77957", + "type": "gitlab" + }, + "original": { + "dir": "lib", + "owner": "TECHNOFAB", + "repo": "nixmkdocs", + "type": "gitlab" + } + }, + "nixtest-lib": { + "locked": { + "dir": "lib", + "lastModified": 1765788390, + "narHash": "sha256-CwICjxGzu43jLaF+Ez6veRW1rEOvkT9zm46X0YrqdYc=", + "owner": "TECHNOFAB", + "repo": "nixtest", + "rev": "fc2b64839c97bca96d4b03d0c1d6ea6ec847c84b", + "type": "gitlab" + }, + "original": { + "dir": "lib", + "owner": "TECHNOFAB", + "repo": "nixtest", + "type": "gitlab" + } + }, + "root": { + "inputs": { + "devshell-lib": "devshell-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": 1766044966, + "narHash": "sha256-VB8PgA5QYmehFCGGz8YmlmuhCG43ab9rK9ufdKmfjao=", + "owner": "TECHNOFAB", + "repo": "soonix", + "rev": "e9860d65a0123af948c1a2da65664a6d481efe05", + "type": "gitlab" + }, + "original": { + "dir": "lib", + "owner": "TECHNOFAB", + "repo": "soonix", + "type": "gitlab" + } + }, + "treefmt-nix": { + "flake": false, + "locked": { + "lastModified": 1766000401, + "narHash": "sha256-+cqN4PJz9y0JQXfAK5J1drd0U05D5fcAGhzhfVrDlsI=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "42d96e75aa56a3f70cab7e7dc4a32868db28e8fd", + "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..7ae9e66 --- /dev/null +++ b/nix/repo/flake.nix @@ -0,0 +1,27 @@ +{ + inputs = { + devshell-lib.url = "gitlab:rensa-nix/devshell?dir=lib"; + nixtest-lib.url = "gitlab:TECHNOFAB/nixtest?dir=lib"; + soonix-lib.url = "gitlab:TECHNOFAB/soonix?dir=lib"; + nixmkdocs-lib.url = "gitlab:TECHNOFAB/nixmkdocs?dir=lib"; + nix-gitlab-ci-lib.url = "gitlab:TECHNOFAB/nix-gitlab-ci/3.1.2?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;}; + ntlib = i.nixtest-lib.lib {inherit (i.parent) pkgs;}; + cilib = i.nix-gitlab-ci-lib.lib {inherit (i.parent) pkgs;}; + doclib = i.nixmkdocs-lib.lib {inherit (i.parent) pkgs;}; + nixlet-lib = import "${i.parent.self}/lib" { + inherit (i.parent) kubenix; + inherit (i.parent.pkgs) lib; + }; + treefmt = import i.treefmt-nix; + }; +} diff --git a/nix/repo/nixlets.nix b/nix/repo/nixlets.nix new file mode 100644 index 0000000..b78c9ad --- /dev/null +++ b/nix/repo/nixlets.nix @@ -0,0 +1,4 @@ +{inputs, ...}: let + inherit (inputs) self nixlet-lib; +in + import "${self}/nixlets" {inherit nixlet-lib;} diff --git a/nix/repo/soonix.nix b/nix/repo/soonix.nix new file mode 100644 index 0000000..927f419 --- /dev/null +++ b/nix/repo/soonix.nix @@ -0,0 +1,37 @@ +{ + 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"]; + }; + 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..cc3c53a --- /dev/null +++ b/nix/repo/tests.nix @@ -0,0 +1,16 @@ +{ + inputs, + cell, + system, + ... +}: let + inherit (inputs) pkgs ntlib nixlet-lib; + inherit (cell) nixlets; +in { + tests = ntlib.mkNixtest { + modules = ntlib.autodiscover {dir = "${inputs.self}/tests";}; + args = { + inherit pkgs ntlib nixlet-lib nixlets system; + }; + }; +} diff --git a/tests/fixtures/example/nixlet.nix b/tests/fixtures/example/nixlet.nix new file mode 100644 index 0000000..98747d4 --- /dev/null +++ b/tests/fixtures/example/nixlet.nix @@ -0,0 +1,6 @@ +{ + name = "example"; + version = "0.0.1"; + description = "hello world"; + defaultProject = "example"; +} diff --git a/tests/fixtures/example/values.nix b/tests/fixtures/example/values.nix new file mode 100644 index 0000000..8ddf30c --- /dev/null +++ b/tests/fixtures/example/values.nix @@ -0,0 +1,12 @@ +{lib, ...}: +with lib; { + options = { + example = mkOption { + type = types.str; + default = "Hello world!"; + description = '' + Some description. + ''; + }; + }; +} diff --git a/tests/lib_test.nix b/tests/lib_test.nix new file mode 100644 index 0000000..eeeb34b --- /dev/null +++ b/tests/lib_test.nix @@ -0,0 +1,47 @@ +{ + pkgs, + ntlib, + nixlet-lib, + ... +}: { + suites."Lib Tests" = { + pos = __curPos; + tests = let + nixlet = nixlet-lib.mkNixlet ./fixtures/example; + in [ + { + name = "mkNixlet fail on nonexistant nixlet.nix"; + expected = { + success = false; + value = false; + }; + actual = builtins.tryEval (nixlet-lib.mkNixlet "/nonexistant").name; + } + { + name = "mkNixlet success"; + expected = { + name = "example"; + version = "0.0.1"; + description = "hello world"; + }; + actual = {inherit (nixlet) name description version;}; + } + { + name = "Nixlet mkDocs"; + type = "script"; + script = let + docs = nixlet.mkDocs {}; + in + # sh + '' + ${ntlib.helpers.path [pkgs.gnugrep]} + ${ntlib.helpers.scriptHelpers} + assert "-f ${docs}" "generated the file" + assert_file_contains "${docs}" '`example`' + assert_file_contains "${docs}" "Some description." + assert_file_contains "${docs}" '"Hello world!"' + ''; + } + ]; + }; +} diff --git a/tests/render_test.nix b/tests/render_test.nix new file mode 100644 index 0000000..032c34e --- /dev/null +++ b/tests/render_test.nix @@ -0,0 +1,30 @@ +{ + pkgs, + ntlib, + system, + nixlets, + ... +}: { + suites."Render Tests" = { + pos = __curPos; + tests = builtins.map ( + nixlet: { + name = "render ${nixlet.name}"; + type = "script"; + script = let + output = nixlet.render {inherit system;}; + in + # sh + '' + ${ntlib.helpers.path [pkgs.gnugrep]} + ${ntlib.helpers.scriptHelpers} + + assert "-f ${output}" "should render" + assert_file_contains "${output}" "apiVersion" + assert_file_contains "${output}" "kubenix/k8s-version" + assert_file_contains "${output}" "kubenix/project-name" + ''; + } + ) (builtins.attrValues nixlets); + }; +} From 471cb8b7b529beb1b300e96e940b523302397ae7 Mon Sep 17 00:00:00 2001 From: technofab Date: Thu, 18 Dec 2025 13:42:14 +0100 Subject: [PATCH 2/3] chore: format files --- .gitignore | 4 --- docs/packaging.md | 1 + lib/default.nix | 59 ++++++++++++++++---------------- lib/valuesDocs.nix | 8 ++--- nixlets/attic/service.nix | 2 +- nixlets/mosquitto/service.nix | 4 +-- nixlets/postgres/service.nix | 4 +-- nixlets/surrealdb/deployment.nix | 6 +--- nixlets/surrealdb/service.nix | 4 +-- nixlets/tikv/service.nix | 8 ++--- template/default.nix | 2 +- 11 files changed, 48 insertions(+), 54 deletions(-) diff --git a/.gitignore b/.gitignore index b7ecd6b..b2be92b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1 @@ -.direnv -.devenv -.idea result -.pre-commit-config.yaml diff --git a/docs/packaging.md b/docs/packaging.md index c9408e0..eb5224f 100644 --- a/docs/packaging.md +++ b/docs/packaging.md @@ -30,6 +30,7 @@ In GitLab CI this should for example be `JOB-TOKEN: $CI_JOB_TOKEN`. A personal access token requires this format instead: `PRIVATE-TOKEN: `. !!! note + The script only uploads a version once. If the version already exists it will skip that Nixlet. ## General diff --git a/lib/default.nix b/lib/default.nix index 8fec02c..2f311bc 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -10,7 +10,7 @@ with lib; rec { }; modules = [ file - ({...}: { + (_: { # pass through all args to the values.nix module config = rawValues @@ -59,41 +59,42 @@ with lib; rec { eval = { system, project ? defaultProject, - overrides ? ({...}: {}), + overrides ? (_: {}), values ? {}, }: assert lib.assertMsg (project != null) "No default project set, please pass a project to the render method"; let nixletArg = baseNixletArg // {inherit project;}; - in (kubenix.evalModules.${system} { - module = {kubenix, ...}: { - imports = with kubenix.modules; [ - k8s - helm - docker - files - ./secretsModule.nix - ({...}: let - finalValues = mkValues "${path}/values.nix" { - rawValues = values; - nixlet = nixletArg; - }; - in { - imports = [path]; - _module.args.nixlet = - { - values = finalValues; - } - // nixletArg; - }) - overrides - ]; - kubenix.project = project; + in + kubenix.evalModules.${system} { + module = {kubenix, ...}: { + imports = with kubenix.modules; [ + k8s + helm + docker + files + ./secretsModule.nix + (_: let + finalValues = mkValues "${path}/values.nix" { + rawValues = values; + nixlet = nixletArg; + }; + in { + imports = [path]; + _module.args.nixlet = + { + values = finalValues; + } + // nixletArg; + }) + overrides + ]; + kubenix.project = project; + }; }; - }); render = { system, project ? defaultProject, - overrides ? ({...}: {}), + overrides ? (_: {}), values ? {}, }: (nixlet.eval { @@ -150,6 +151,6 @@ with lib; rec { ) ); - mkDocs = {nixlet, ...} @ opts: + mkDocs = opts: import ./valuesDocs.nix (opts // {inherit lib;}); } diff --git a/lib/valuesDocs.nix b/lib/valuesDocs.nix index e0a14ef..3ddf161 100644 --- a/lib/valuesDocs.nix +++ b/lib/valuesDocs.nix @@ -31,7 +31,7 @@ optionsNix = builtins.listToAttrs ( map (o: { - name = o.name; + inherit (o) name; value = removeAttrs o [ "visible" "internal" @@ -76,9 +76,9 @@ '') + "\n"; - opts = mapAttrsToList (name: opt: - optToMd opt) - optionsNix; + opts = + mapAttrsToList (_name: optToMd) + optionsNix; markdown = concatStringsSep "\n" opts; in builtins.toFile "values-doc.md" markdown diff --git a/nixlets/attic/service.nix b/nixlets/attic/service.nix index 84246b9..82959d1 100644 --- a/nixlets/attic/service.nix +++ b/nixlets/attic/service.nix @@ -10,7 +10,7 @@ with nixlet; { port = 8080; } ]; - type = values.service.type; + inherit (values.service) type; }; }; }; diff --git a/nixlets/mosquitto/service.nix b/nixlets/mosquitto/service.nix index df90272..ba67caa 100644 --- a/nixlets/mosquitto/service.nix +++ b/nixlets/mosquitto/service.nix @@ -7,11 +7,11 @@ with nixlet; { ports = [ { name = "mqtt"; - port = values.service.port; + inherit (values.service) port; targetPort = 1883; } ]; - type = values.service.type; + inherit (values.service) type; }; }; }; diff --git a/nixlets/postgres/service.nix b/nixlets/postgres/service.nix index d094985..f1f58e6 100644 --- a/nixlets/postgres/service.nix +++ b/nixlets/postgres/service.nix @@ -7,11 +7,11 @@ with nixlet; { ports = [ { name = "tcp"; - port = values.service.port; + inherit (values.service) port; targetPort = 5432; } ]; - type = values.service.type; + inherit (values.service) type; }; }; }; diff --git a/nixlets/surrealdb/deployment.nix b/nixlets/surrealdb/deployment.nix index 2c28d7d..e3b4f76 100644 --- a/nixlets/surrealdb/deployment.nix +++ b/nixlets/surrealdb/deployment.nix @@ -1,8 +1,4 @@ -{ - nixlet, - lib, - ... -}: +{nixlet, ...}: with nixlet; { kubernetes.resources = { deployments."${values.uniqueName}" = { diff --git a/nixlets/surrealdb/service.nix b/nixlets/surrealdb/service.nix index b9a1763..4fe7af5 100644 --- a/nixlets/surrealdb/service.nix +++ b/nixlets/surrealdb/service.nix @@ -8,10 +8,10 @@ with nixlet; { { name = "http"; targetPort = "http"; - port = values.service.port; + inherit (values.service) port; } ]; - type = values.service.type; + inherit (values.service) type; }; }; }; diff --git a/nixlets/tikv/service.nix b/nixlets/tikv/service.nix index 5495554..a525d71 100644 --- a/nixlets/tikv/service.nix +++ b/nixlets/tikv/service.nix @@ -10,7 +10,7 @@ with nixlet; { ports = [ { name = "pd-server"; - port = values.pd.service.port; + inherit (values.pd.service) port; } { name = "peer"; @@ -29,7 +29,7 @@ with nixlet; { ports = [ { name = "peer"; - port = values.tikv.service.port; + inherit (values.tikv.service) port; } ]; type = "ClusterIP"; @@ -44,10 +44,10 @@ with nixlet; { ports = [ { name = "server"; - port = values.pd.service.port; + inherit (values.pd.service) port; } ]; - type = values.pd.service.type; + inherit (values.pd.service) type; }; }; }; diff --git a/template/default.nix b/template/default.nix index 3246912..3cec3dc 100644 --- a/template/default.nix +++ b/template/default.nix @@ -1,4 +1,4 @@ -{nixlet, ...}: { +{...}: { imports = [ # import other files here ]; From f574e32083ff5ed66245d960c09decf126830d1d Mon Sep 17 00:00:00 2001 From: technofab Date: Thu, 18 Dec 2025 13:54:55 +0100 Subject: [PATCH 3/3] docs: add docs for generating docs for nixlet values, update nixmkdocs --- docs/generating_docs.md | 38 ++++++++++++++++++++++++++++++++++++++ nix/repo/docs.nix | 1 + nix/repo/flake.lock | 6 +++--- 3 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 docs/generating_docs.md diff --git a/docs/generating_docs.md b/docs/generating_docs.md new file mode 100644 index 0000000..9c4fc14 --- /dev/null +++ b/docs/generating_docs.md @@ -0,0 +1,38 @@ +# Generating Docs + +Like you can see on the left (if you are looking at the built MkDocs site), it's possible +to generate docs for Nixlets' values automatically. +Since the values are basically just Nix module options, we can generate docs similarly to NixOS options etc. + +## Generate Markdown + +This is all that's needed: + +```nix +().mkDocs { +# Params: +# transformOptions ? opt: opt, +# filter ? _: true, +# headingDepth ? 3, +} +``` + +This will return the path to a markdown file containing the docs, like this: + +````md +### `example` + +(no description) + +**Type**: + +```console +string +``` + +**Default value**: + +```nix +"Hello world!" +``` +```` diff --git a/nix/repo/docs.nix b/nix/repo/docs.nix index 2f5ced7..b111e3f 100644 --- a/nix/repo/docs.nix +++ b/nix/repo/docs.nix @@ -43,6 +43,7 @@ in {"Creating Nixlets" = "creation.md";} {"Packaging" = "packaging.md";} {"Usage" = "usage.md";} + {"Generating Docs" = "generating_docs.md";} {"Secrets" = "secrets.md";} ]; markdown_extensions = [ diff --git a/nix/repo/flake.lock b/nix/repo/flake.lock index cd48965..3db8b5f 100644 --- a/nix/repo/flake.lock +++ b/nix/repo/flake.lock @@ -38,11 +38,11 @@ "nixmkdocs-lib": { "locked": { "dir": "lib", - "lastModified": 1766000281, - "narHash": "sha256-rtQKu/snzEjZBCyTkZMWUIuvCThtjmVEwBXb6T1mm40=", + "lastModified": 1766062227, + "narHash": "sha256-jhr5CUi9eDeMIAJn7ayXP8Wr+Y2loV5EhdDIKDkRIdw=", "owner": "TECHNOFAB", "repo": "nixmkdocs", - "rev": "6999c026457d7dee3a7ab336cd4d1b38bae77957", + "rev": "cb0bb5dc3382e8ba5d81324a2f1fd94ccd5a5df4", "type": "gitlab" }, "original": {