diff --git a/lib/errors/inputsSource.nix b/lib/errors/inputsSource.nix new file mode 100644 index 0000000..e01e653 --- /dev/null +++ b/lib/errors/inputsSource.nix @@ -0,0 +1,24 @@ +{ lib }: +list: +lib.filter (pair: lib.elem pair.name list) [ + { + name = "nixpkgs"; + url = "github:nixpkgs/nixpkgs-unstable"; + } + { + name = "makes"; + url = "github:fluidattacks/makes"; + } + { + name = "home-manager"; + url = "github:github:nix-community/home-manager"; + } + { + name = "microvm"; + url = "github:astro/microvm.nix"; + } + { + name = "topiary"; + url = "github:github:tweag/topiary"; + } +] diff --git a/lib/errors/msg.nix b/lib/errors/msg.nix deleted file mode 100644 index fd5799c..0000000 --- a/lib/errors/msg.nix +++ /dev/null @@ -1,8 +0,0 @@ -_: name: '' - please, add the home-manager into omnibus.lib.addLoadExtender { - load.inputs = { - inputs.${name} = inputs.${name}; - }; - }; - } -'' diff --git a/lib/errors/requiredInputs.nix b/lib/errors/requiredInputs.nix new file mode 100644 index 0000000..d69333e --- /dev/null +++ b/lib/errors/requiredInputs.nix @@ -0,0 +1,59 @@ +{ + lib, + inputs, + super, +}: +inputs': listNames: +let + fondInputs = + if + (lib.length ( + lib.filter (pair: pair == true) (map (v: lib.hasAttr v inputs) listNames) + )) > 0 + then + true + else + false + ; + msg = + (lib.concatMapStringsSep "\n " + ( + { name, url }: + '' + # add `${name}.url = "${url}"` to your flake + ${name} = inputs.${name}; + '' + ) + (super.inputsSource listNames) + ); + + noSysNixpkgs = + if (lib.elem "nixpkgs" listNames) then + if (lib.hasAttr "path" inputs'.nixpkgs) then true else false + else + true + ; +in +assert lib.assertMsg fondInputs '' + please, add the these inputs into + + omnibus.lib.addLoadExtender { + load.inputs = { + ${msg} + + # you can also see the full inputs list at + # https://github.com/GTrunSec/omnibus/blob/main/local/lock/flake.nix#L1 + }; + }; + } +''; +assert lib.assertMsg noSysNixpkgs '' + please, add the following inputs into + omnibus.lib.addLoadExtender { + load.inputs = { + nixpkgs = inputs.nixpkgs.legacyPackages.''${system} or (import inputs.nixpkgs.path); + }; + }; + } +''; +inputs' diff --git a/lib/exporter/flakeOutputs.nix b/lib/exporter/flakeOutputs.nix index a6fac8f..31fc874 100644 --- a/lib/exporter/flakeOutputs.nix +++ b/lib/exporter/flakeOutputs.nix @@ -12,6 +12,11 @@ let in { inherit (outputs) srvos; + + units = { + inherit (outputs) configs; + }; + __inputs__ = super.pops.loadInputs.outputs; dotfiles = inputs.self.outPath + "/dotfiles"; diff --git a/lib/exporter/pops.nix b/lib/exporter/pops.nix index a9f2d96..e27703d 100644 --- a/lib/exporter/pops.nix +++ b/lib/exporter/pops.nix @@ -54,6 +54,11 @@ in load.src = inputs.self.outPath + "/nixos/darwinModules"; }; + configs = flops.haumea.pops.default.setInit { + src = inputs.self.outPath + "/units/configs"; + inputs = baseInputs; + }; + srvos = flops.haumea.pops.default.setInit { src = self.loadInputs.outputs.srvos + "/nixos"; type = "nixosProfiles"; @@ -62,24 +67,24 @@ in }; flake-parts = { loadModules = self.loadNixOSModules.addLoadExtender { - load.src = inputs.self.outPath + "/evalModules/flake-parts/modules"; + load.src = inputs.self.outPath + "/units/flake-parts/modules"; }; loadProfiles = self.loadNixOSProfiles.addLoadExtender { load = { - src = inputs.self.outPath + "/evalModules/flake-parts/profiles"; + src = inputs.self.outPath + "/units/flake-parts/profiles"; }; }; }; devshell = rec { loadModules = self.loadNixOSModules.addLoadExtender { load = { - src = inputs.self.outPath + "/evalModules/devshell/modules"; + src = inputs.self.outPath + "/units/devshell/modules"; type = "nixosModules"; }; }; loadProfiles = self.loadNixOSProfiles.addLoadExtender { load = { - src = inputs.self.outPath + "/evalModules/devshell/profiles"; + src = inputs.self.outPath + "/units/devshell/profiles"; type = "nixosProfiles"; }; }; diff --git a/lib/makes.nix b/lib/makes.nix new file mode 100644 index 0000000..10abe4b --- /dev/null +++ b/lib/makes.nix @@ -0,0 +1,27 @@ +{ + inputs, + lib, + root, +}: +let + l = nixpkgs.lib // builtins; + inherit + (root.errors.requiredInputs inputs [ + "nixpkgs" + "makes" + ]) + nixpkgs + makes + ; +in +l.fix ( + l.extends + (_: _: { + inherit inputs; + inherit (nixpkgs) system; + __nixpkgs__ = nixpkgs; + __nixpkgsSrc__ = nixpkgs.path; + }) + (import (makes + /src/args/agnostic.nix) { inherit (nixpkgs) system; }) + .__unfix__ +) diff --git a/lib/mkHome.nix b/lib/mkHome.nix index 835223c..c020b4a 100644 --- a/lib/mkHome.nix +++ b/lib/mkHome.nix @@ -4,10 +4,8 @@ root, }: userSet: shell: suites: -assert lib.assertMsg (inputs ? home-manager) (root.errors.msg "home-manager"); let - - inherit (inputs) home-manager; + inherit (root.errors.requiredInputs inputs [ "home-manager" ]) home-manager; user = lib.head (lib.attrNames userSet); pathsToLinkShell = lib.elem shell [ "fish" diff --git a/lib/mkMicrovm.nix b/lib/mkMicrovm.nix new file mode 100644 index 0000000..278b4ba --- /dev/null +++ b/lib/mkMicrovm.nix @@ -0,0 +1,33 @@ +# credit: https://github.com/divnix/std/blob/main/src/lib/ops/mkMicrovm.nix# +{ + inputs, + lib, + root, +}: +let + inherit + (root.errors.requiredInputs inputs [ + "nixpkgs" + "microvm" + ]) + nixpkgs + microvm + ; + nixosSystem = + args: + import "${nixpkgs.path}/nixos/lib/eval-config.nix" ( + args // { modules = args.modules; } + ); +in +module: +nixosSystem { + inherit (nixpkgs) system; + modules = [ + # for declarative MicroVM management + microvm.nixosModules.host + # this runs as a MicroVM that nests MicroVMs + microvm.nixosModules.microvm + # your custom module + module + ]; +} diff --git a/local/lock/flake.lock b/local/lock/flake.lock index ef8ab20..fd46b0d 100644 --- a/local/lock/flake.lock +++ b/local/lock/flake.lock @@ -82,6 +82,22 @@ "type": "github" } }, + "makes": { + "flake": false, + "locked": { + "lastModified": 1696868671, + "narHash": "sha256-4SGTcJ+E3wZXhtcvxZROCGam7371THcPYtmdyV9JzVo=", + "owner": "fluidattacks", + "repo": "makes", + "rev": "380ecfa979898ab283874ca44f76a75a551834b6", + "type": "github" + }, + "original": { + "owner": "fluidattacks", + "repo": "makes", + "type": "github" + } + }, "nixpkgs": { "locked": { "lastModified": 1696879762, @@ -104,6 +120,7 @@ "devshell": "devshell", "fenix": "fenix", "home-manager": "home-manager", + "makes": "makes", "nixpkgs": "nixpkgs", "srvos": "srvos" } diff --git a/local/lock/flake.nix b/local/lock/flake.nix index 4cd5b41..add744b 100644 --- a/local/lock/flake.nix +++ b/local/lock/flake.nix @@ -17,6 +17,9 @@ fenix.url = "github:nix-community/fenix"; fenix.inputs.nixpkgs.follows = "nixpkgs"; + + makes.url = "github:fluidattacks/makes"; + makes.flake = false; }; outputs = _: { }; } diff --git a/tests/_snapshots/makes b/tests/_snapshots/makes new file mode 100644 index 0000000..f785e80 --- /dev/null +++ b/tests/_snapshots/makes @@ -0,0 +1,4 @@ +#pretty +{ + makeScript = ; +} \ No newline at end of file diff --git a/tests/makes/expr.nix b/tests/makes/expr.nix new file mode 100644 index 0000000..b7e7d4b --- /dev/null +++ b/tests/makes/expr.nix @@ -0,0 +1,20 @@ +{ omnibus, lib }: +let + inherit (omnibus.__inputs__) nixpkgs makes; + makesLib = + (omnibus.pops.lib.addLoadExtender { + load = { + inputs = { + inputs = { + nixpkgs = nixpkgs.legacyPackages.x86_64-linux; + inherit makes; + }; + }; + }; + }).layouts.default.makes; + + inherit (makesLib) makeScript; +in +{ + makeScript = makeScript; +} diff --git a/tests/makes/format.nix b/tests/makes/format.nix new file mode 100644 index 0000000..f9e1770 --- /dev/null +++ b/tests/makes/format.nix @@ -0,0 +1 @@ +"pretty" diff --git a/units/configs/cog.nix b/units/configs/cog.nix new file mode 100644 index 0000000..8522166 --- /dev/null +++ b/units/configs/cog.nix @@ -0,0 +1,48 @@ +{ inputs }: +{ + default = { + output = "cog.toml"; + commands = [ { package = inputs.nixpkgs.cocogitto; } ]; + data = { + tag_prefix = "v"; + branch_whitelist = [ + "main" + "release/**" + ]; + ignore_merge_commits = true; + pre_bump_hooks = [ + "echo {{version}} > ./VERSION" + '' + branch="$(echo "release/{{version}}" | sed 's/\.[^.]*$//')" + if [ `git rev-parse --verify $branch 2>/dev/null` ] + then + git switch -m "$branch" || exit 1 + git merge main + else + git switch -c "$branch" || exit 1 + fi + '' + ]; + post_bump_hooks = [ + '' + branch="$(echo "release/{{version}}" | sed 's/\.[^.]*$//')" + git push --set-upstream origin "$branch" + git push origin v{{version}} + + git switch main + git merge "$branch" --no-commit --no-ff + echo {{version+minor-dev}} > ./VERSION + git add VERSION + git commit -m "chore: sync with release" + git push origin main + '' + "cog -q changelog --at v{{version}}" + ]; + changelog = { + path = "CHANGELOG.md"; + template = "remote"; + remote = "github.com"; + }; + }; + }; +} diff --git a/units/configs/conform.nix b/units/configs/conform.nix new file mode 100644 index 0000000..2e7c882 --- /dev/null +++ b/units/configs/conform.nix @@ -0,0 +1,24 @@ +{ + default.data = { + commit = { + header = { + length = 89; + }; + conventional = { + types = [ + "build" + "chore" + "ci" + "docs" + "feat" + "fix" + "perf" + "refactor" + "style" + "test" + ]; + scopes = [ ]; + }; + }; + }; +} diff --git a/units/configs/editorconfig.nix b/units/configs/editorconfig.nix new file mode 100644 index 0000000..1337752 --- /dev/null +++ b/units/configs/editorconfig.nix @@ -0,0 +1,33 @@ +{ + default.data = { + root = true; + "*" = { + end_of_line = "lf"; + insert_final_newline = true; + trim_trailing_whitespace = true; + charset = "utf-8"; + indent_style = "space"; + indent_size = 2; + }; + + "*.{diff,patch}" = { + end_of_line = "unset"; + insert_final_newline = "unset"; + trim_trailing_whitespace = "unset"; + indent_size = "unset"; + }; + + "*.md" = { + max_line_length = "off"; + trim_trailing_whitespace = false; + }; + "{LICENSES/**,LICENSE}" = { + end_of_line = "unset"; + insert_final_newline = "unset"; + trim_trailing_whitespace = "unset"; + charset = "unset"; + indent_style = "unset"; + indent_size = "unset"; + }; + }; +} diff --git a/units/configs/githubsettings.nix b/units/configs/githubsettings.nix new file mode 100644 index 0000000..f1a53b3 --- /dev/null +++ b/units/configs/githubsettings.nix @@ -0,0 +1,126 @@ +let + colors = { + black = "#000000"; + blue = "#1565C0"; + lightBlue = "#64B5F6"; + green = "#4CAF50"; + grey = "#A6A6A6"; + lightGreen = "#81C784"; + gold = "#FDD835"; + orange = "#FB8C00"; + purple = "#AB47BC"; + red = "#F44336"; + yellow = "#FFEE58"; + }; + labels = { + statuses = { + abandoned = { + name = ":running: Status: Abdandoned"; + description = "This issue has been abdandoned"; + color = colors.black; + }; + accepted = { + name = ":ok: Status: Accepted"; + description = "This issue has been accepted"; + color = colors.green; + }; + blocked = { + name = ":x: Status: Blocked"; + description = "This issue is in a blocking state"; + color = colors.red; + }; + inProgress = { + name = ":construction: Status: In Progress"; + description = "This issue is actively being worked on"; + color = colors.grey; + }; + onHold = { + name = ":golf: Status: On Hold"; + description = "This issue is not currently being worked on"; + color = colors.red; + }; + reviewNeeded = { + name = ":eyes: Status: Review Needed"; + description = "This issue is pending a review"; + color = colors.gold; + }; + }; + types = { + bug = { + name = ":bug: Type: Bug"; + description = "This issue targets a bug"; + color = colors.red; + }; + story = { + name = ":scroll: Type: Story"; + description = "This issue targets a new feature through a story"; + color = colors.lightBlue; + }; + maintenance = { + name = ":wrench: Type: Maintenance"; + description = "This issue targets general maintenance"; + color = colors.orange; + }; + question = { + name = ":grey_question: Type: Question"; + description = "This issue contains a question"; + color = colors.purple; + }; + security = { + name = ":cop: Type: Security"; + description = "This issue targets a security vulnerability"; + color = colors.red; + }; + }; + priorities = { + critical = { + name = ":boom: Priority: Critical"; + description = "This issue is prioritized as critical"; + color = colors.red; + }; + high = { + name = ":fire: Priority: High"; + description = "This issue is prioritized as high"; + color = colors.orange; + }; + medium = { + name = ":star2: Priority: Medium"; + description = "This issue is prioritized as medium"; + color = colors.yellow; + }; + low = { + name = ":low_brightness: Priority: Low"; + description = "This issue is prioritized as low"; + color = colors.green; + }; + }; + effort = { + "1" = { + name = ":muscle: Effort: 1"; + description = "This issue is of low complexity or very well understood"; + color = colors.green; + }; + "2" = { + name = ":muscle: Effort: 3"; + description = "This issue is of medium complexity or only partly well understood"; + color = colors.yellow; + }; + "5" = { + name = ":muscle: Effort: 5"; + description = "This issue is of high complexity or just not yet well understood"; + color = colors.red; + }; + }; + }; + + l = builtins; +in +{ + default.data.labels = + [ ] + ++ (l.attrValues labels.statuses) + ++ (l.attrValues labels.types) + ++ (l.attrValues labels.priorities) + ++ (l.attrValues labels.effort) + ; +} diff --git a/units/configs/lefthook.nix b/units/configs/lefthook.nix new file mode 100644 index 0000000..d224255 --- /dev/null +++ b/units/configs/lefthook.nix @@ -0,0 +1,29 @@ +{ + default.data = { + commit-msg = { + commands = { + conform = { + # allow WIP, fixup!/squash! commits locally + run = '' + [[ "$(head -n 1 {1})" =~ ^WIP(:.*)?$|^wip(:.*)?$|fixup\!.*|squash\!.* ]] || + conform enforce --commit-msg-file {1}''; + skip = [ + "merge" + "rebase" + ]; + }; + }; + }; + pre-commit = { + commands = { + treefmt = { + run = "treefmt --fail-on-change {staged_files}"; + skip = [ + "merge" + "rebase" + ]; + }; + }; + }; + }; +} diff --git a/units/configs/treefmt.nix b/units/configs/treefmt.nix new file mode 100644 index 0000000..5700868 --- /dev/null +++ b/units/configs/treefmt.nix @@ -0,0 +1,99 @@ +{ inputs, omnibus }: +let + inherit + (omnibus.lib.errors.requiredInputs inputs [ + "nixpkgs" + "topiary" + ]) + dmerge + topiary + nixpkgs + ; +in +with dmerge; { + default = { + data = { + formatter = { + nix = { + includes = [ "*.nix" ]; + command = "nixfmt"; + }; + prettier = { + command = "prettier"; + options = [ + "--plugin" + "${nixpkgs.nodePackages.prettier-plugin-toml}/lib/node_modules/prettier-plugin-toml/lib/api.js" + "--write" + ]; + includes = [ + "*.css" + "*.html" + "*.js" + "*.json" + "*.jsx" + "*.md" + "*.mdx" + "*.scss" + "*.ts" + "*.yaml" + "*.toml" + ]; + }; + shell = { + command = "shfmt"; + options = [ + "-i" + "2" + "-s" + "-w" + ]; + includes = [ "*.sh" ]; + }; + }; + }; + }; + julia = { + data.formatter.prettier = { + includes = prepend [ "" ]; + excludes = prepend [ + "Manifest.toml" + "Project.toml" + "julia2nix.toml" + ]; + }; + }; + rust = { + data.formatter.rust = { + command = "rustfmt"; + includes = [ "*.rs" ]; + options = [ + "--edition" + "2021" + ]; + }; + data.formatter.prettier = { + includes = prepend [ ".rustfmt.toml" ]; + }; + }; + nvfetcher = { + data.formatter.prettier = { + excludes = prepend [ "generated.json" ]; + }; + data.formatter.nix = { + excludes = prepend [ "generated.nix" ]; + }; + }; + nix = { + data.formatter.prettier = { + excludes = prepend [ ".nix.toml" ]; + }; + }; + topiary = { + data.formatter.topiary = { + command = "topiary"; + options = [ "fmt" ]; + includes = [ "*.ncl" ]; + }; + packages = [ topiary.packages.default ]; + }; +} diff --git a/evalModules/devshell/modules/language/rust.nix b/units/devshell/modules/language/rust.nix similarity index 100% rename from evalModules/devshell/modules/language/rust.nix rename to units/devshell/modules/language/rust.nix diff --git a/evalModules/devshell/profiles/rust.nix b/units/devshell/profiles/rust.nix similarity index 100% rename from evalModules/devshell/profiles/rust.nix rename to units/devshell/profiles/rust.nix diff --git a/evalModules/flake-parts/modules/todo.nix b/units/flake-parts/modules/todo.nix similarity index 100% rename from evalModules/flake-parts/modules/todo.nix rename to units/flake-parts/modules/todo.nix diff --git a/evalModules/flake-parts/profiles/process-compose/sqlite-example.nix b/units/flake-parts/profiles/process-compose/sqlite-example.nix similarity index 100% rename from evalModules/flake-parts/profiles/process-compose/sqlite-example.nix rename to units/flake-parts/profiles/process-compose/sqlite-example.nix