diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 1040ee637..ca1ca2895 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -35,4 +35,4 @@ Please search on the [issue tracker](../) before creating one. ## Your Environment - + diff --git a/.github/ISSUE_TEMPLATE/community_request.md b/.github/ISSUE_TEMPLATE/community_request.md deleted file mode 100644 index c55a3faf4..000000000 --- a/.github/ISSUE_TEMPLATE/community_request.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -name: Commuity Request -about: inspire contribution to the `community` branch -title: '' -labels: 'community' -assignees: '' - ---- - -Your issue may already be reported! -Please search on the [issue tracker](../) before creating one. - -## Ideas - - - - - - -## Requests - - diff --git a/.github/ISSUE_TEMPLATE/upstream_notice.md b/.github/ISSUE_TEMPLATE/upstream_notice.md deleted file mode 100644 index 4ada54e3b..000000000 --- a/.github/ISSUE_TEMPLATE/upstream_notice.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -name: Upstream notice (Issues or Changes) -about: Create an upstream notice to help our research -title: '[ ]: ' -labels: 'upstream' -assignees: '' - ---- - -## Link - - - -## Context - diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 756aa2bf1..0141f1709 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -1,29 +1,40 @@ name: "Check & Cachix" + on: push: branches: - main - trying - staging + jobs: check: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2.3.4 - - uses: cachix/install-nix-action@v13 + - uses: actions/checkout@v2.4.0 + with: + submodules: true + fetch-depth: 0 + - uses: cachix/install-nix-action@v16 with: - install_url: https://github.com/numtide/nix-flakes-installer/releases/download/nix-2.4pre20210415_76980a1/install extra_nix_config: | - experimental-features = nix-command flakes system-features = nixos-test benchmark big-parallel kvm recursive-nix substituters = https://nrdxp.cachix.org https://nix-community.cachix.org https://cache.nixos.org trusted-public-keys = nrdxp.cachix.org-1:Fc5PSqY2Jm1TrWfm88l6cvGWwz3s93c6IOifQWnhNW4= nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= + - uses: cachix/cachix-action@v10 with: name: nrdxp signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}' authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' - - run: nix -Lv flake check - - run: nix -Lv build ".#nixosConfigurations.NixOS.config.system.build.toplevel" - - run: nix -Lv develop -c echo OK - - run: nix -Lv develop --command bud --help + + # Quick eval + - run: nix develop --command evalnix + + # Check the digga library + - run: nix flake check --show-trace + + # Check /examples/* + - run: nix develop --command -- check-devos --show-trace + - run: nix develop --command -- check-groupByConfig --show-trace + - run: nix develop --command -- check-hmOnly --show-trace diff --git a/.github/workflows/mdbook_docs.yml b/.github/workflows/mdbook_docs.yml index 5faf9c28f..2f73853b6 100644 --- a/.github/workflows/mdbook_docs.yml +++ b/.github/workflows/mdbook_docs.yml @@ -24,4 +24,4 @@ jobs: github_token: ${{ secrets.GITHUB_TOKEN }} publish_branch: gh-pages publish_dir: ./doc/book - cname: devos.divnix.com + cname: digga.divnix.com diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8cabd1285..111be3191 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,7 +19,7 @@ jobs: - name: Checkout code uses: actions/checkout@v2 with: - ref: main + ref: master - name: Update Changelog uses: heinrichreimer/github-changelog-generator-action@v2.1.1 with: @@ -49,7 +49,7 @@ jobs: - name: Checkout code uses: actions/checkout@v2 with: - ref: main + ref: master - name: Get Changelog Entry id: changelog_reader diff --git a/.gitignore b/.gitignore index 6cce155f3..726d2d63b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,2 @@ result .direnv -doc/index.html - -# Result of bud commands -vm -iso -doi - -pkgs/_sources/.shake* diff --git a/CHANGELOG.md b/CHANGELOG.md index b8d9a688f..718a0f086 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,113 +1,19 @@ # Changelog -## [v0.10.0](https://github.com/divnix/devos/tree/v0.10.0) (2021-05-24) +## [v0.2.0](https://github.com/divnix/digga/tree/v0.2.0) (2021-06-08) **Implemented enhancements:** -- Providing an interface to nixpkgs.config [\#237](https://github.com/divnix/devos/issues/237) -- Making the user available in profiles [\#230](https://github.com/divnix/devos/issues/230) -- copy evaluation store paths to iso [\#195](https://github.com/divnix/devos/issues/195) -- Extract custom system builds from devosSystem out of lib [\#170](https://github.com/divnix/devos/issues/170) -- Allow setting of channel host-wide [\#117](https://github.com/divnix/devos/issues/117) -- alacritty: CSIu support [\#51](https://github.com/divnix/devos/issues/51) +- Overlays / Imports and treatment of non-nix files [\#26](https://github.com/divnix/digga/issues/26) +- NixOS Veteran Migration [\#25](https://github.com/divnix/digga/issues/25) +- Add option of devshellOverlays for devshell [\#21](https://github.com/divnix/digga/issues/21) +- Is it a right way to enable the deploy-rs multi-arch support [\#18](https://github.com/divnix/digga/issues/18) **Fixed bugs:** -- Cachix timeouts + how to disable nrdxp cachix \(if needed\) [\#294](https://github.com/divnix/devos/issues/294) -- default.nix flake-compat is broken [\#285](https://github.com/divnix/devos/issues/285) -- All suites return "attribute missing" [\#282](https://github.com/divnix/devos/issues/282) -- nix is built two times [\#203](https://github.com/divnix/devos/issues/203) -- fix lib docs [\#166](https://github.com/divnix/devos/issues/166) +- Can't override nixpkgs sub-systems with deprecated attributes [\#13](https://github.com/divnix/digga/issues/13) -**Closed issues:** - -- eliminate userFlakeNixOS [\#257](https://github.com/divnix/devos/issues/257) -- devos-as-library [\#214](https://github.com/divnix/devos/issues/214) - -**Merged pull requests:** - -- Update evalArgs to match the new planned API [\#239](https://github.com/divnix/devos/pull/239) - -## [v0.9.0](https://github.com/divnix/devos/tree/v0.9.0) (2021-04-19) - -**Implemented enhancements:** - -- pin inputs into iso live registry [\#190](https://github.com/divnix/devos/issues/190) -- Pass 'self' to lib [\#169](https://github.com/divnix/devos/issues/169) -- doc: quickstart "ISO. What next?" [\#167](https://github.com/divnix/devos/issues/167) -- Integrate Android AOSP putting mobile under control [\#149](https://github.com/divnix/devos/issues/149) -- Inoculate host identity on first use [\#132](https://github.com/divnix/devos/issues/132) -- kubenix support [\#130](https://github.com/divnix/devos/issues/130) -- Improve Home Manager support: profiles/suites, modules, extern, flake outputs [\#119](https://github.com/divnix/devos/issues/119) -- Local CA \(between hosts\) [\#104](https://github.com/divnix/devos/issues/104) -- Q5: git annex for machine state [\#68](https://github.com/divnix/devos/issues/68) -- name space ./pkgs overlays [\#60](https://github.com/divnix/devos/issues/60) -- remap global keys easily [\#57](https://github.com/divnix/devos/issues/57) -- make pass state part of this repo's structure [\#56](https://github.com/divnix/devos/issues/56) -- Incorporate ./shells [\#38](https://github.com/divnix/devos/issues/38) -- Encrypt with \(r\)age [\#37](https://github.com/divnix/devos/issues/37) - -**Fixed bugs:** - -- `pathsToImportedAttrs` does not accept directories [\#221](https://github.com/divnix/devos/issues/221) -- Cachix caches aren't added to the configuration [\#208](https://github.com/divnix/devos/issues/208) -- Issues with current changelog workflow [\#205](https://github.com/divnix/devos/issues/205) -- iso: systemd service startup [\#194](https://github.com/divnix/devos/issues/194) -- Help adding easy-hls-nix to devos [\#174](https://github.com/divnix/devos/issues/174) -- `flk update` fails because of obsolete flag [\#159](https://github.com/divnix/devos/issues/159) -- Expected that not all packages are exported? [\#151](https://github.com/divnix/devos/issues/151) -- Segmentation fault when generating iso [\#150](https://github.com/divnix/devos/issues/150) - -**Documentation:** - -- doc: split iso [\#193](https://github.com/divnix/devos/issues/193) -- lib: can depend on pkgs \(a la nixpkgs\#pkgs/pkgs-lib\) [\#147](https://github.com/divnix/devos/pull/147) - -**Closed issues:** - -- FRRouting router implementation [\#154](https://github.com/divnix/devos/issues/154) -- ARM aarch64 Support [\#72](https://github.com/divnix/devos/issues/72) - -## [v0.8.0](https://github.com/divnix/devos/tree/v0.8.0) (2021-03-02) - -**Implemented enhancements:** - -- semi automatic update for /pkgs [\#118](https://github.com/divnix/devos/issues/118) -- Home-manager external modules from flakes [\#106](https://github.com/divnix/devos/issues/106) - -**Fixed bugs:** - -- My emacsGcc overlay is not working [\#146](https://github.com/divnix/devos/issues/146) -- local flake registry freezes branches [\#142](https://github.com/divnix/devos/issues/142) -- nixos-option no longer works after collect garbage [\#138](https://github.com/divnix/devos/issues/138) -- Profiles imports are brittle, causing failure if imported twice [\#136](https://github.com/divnix/devos/issues/136) - -## [0.7.0](https://github.com/divnix/devos/tree/0.7.0) (2021-02-20) - -**Implemented enhancements:** - -- add zoxide [\#53](https://github.com/divnix/devos/issues/53) -- Multiarch support? [\#17](https://github.com/divnix/devos/issues/17) -- initial multiArch support [\#18](https://github.com/divnix/devos/pull/18) - -**Fixed bugs:** - -- Missing shebang from flk.sh [\#131](https://github.com/divnix/devos/issues/131) -- Rename Meta Issue [\#128](https://github.com/divnix/devos/issues/128) -- specialisations break the `system` argument [\#46](https://github.com/divnix/devos/issues/46) -- Revert "Add extraArgs to lib.nixosSystem call to add system args." [\#47](https://github.com/divnix/devos/pull/47) - -**Documentation:** - -- update home-manager urls [\#62](https://github.com/divnix/devos/pull/62) - -**Closed issues:** - -- add github action for cachix build ci [\#59](https://github.com/divnix/devos/issues/59) - -## [12052020](https://github.com/divnix/devos/tree/12052020) (2020-12-06) - -## [07092020](https://github.com/divnix/devos/tree/07092020) (2020-07-09) +## [v0.1.0](https://github.com/divnix/digga/tree/v0.1.0) (2021-05-15) diff --git a/README.md b/README.md index e2a83eb90..696152e8b 100644 --- a/README.md +++ b/README.md @@ -1,95 +1,80 @@ -[![NixOS](https://img.shields.io/badge/NixOS-unstable-blue.svg?style=flat&logo=NixOS&logoColor=white)](https://nixos.org) +[![Bors enabled](https://bors.tech/images/badge_small.svg)](https://app.bors.tech/repositories/33905) [![MIT License](https://img.shields.io/github/license/divnix/devos)][mit] -[![Chat](https://img.shields.io/matrix/devos:nixos.org.svg?label=%23devos%3Anixos.org&logo=matrix&server_fqdn=matrix.org)][matrix] - -> #### ⚠ Advisory ⚠ -> DevOS requires the [flakes][flakes] feature available via an _experimental_ -> branch of [nix][nix]. Until nix 2.4 is released, this project -> should be considered unstable. - -### Why? -Make an awesome template for NixOS users, with consideration for common tools like [home-manager][home-manager], -[devshell][devshell], and [more](./doc/integrations). - -### No. Why _flakes_? -Flakes are a part of an explicit push to improve [Nix's UX](https://github.com/NixOS/nix/blob/master/doc/manual/src/contributing/cli-guideline.md), and have become an integral part of that effort. - -They also make [Nix expressions](https://nixos.org/manual/nix/unstable/expressions/expression-syntax.html) easier to distribute and reuse with convient [flake references](https://github.com/NixOS/nix/blob/master/src/nix/flake.md#flake-references) for building or using packages, modules, and whole systems. - -## Getting Started -Check out the [guide](https://devos.divnix.com/start) to get up and running. -Also, have a look at [_flake.nix_](./flake.nix). If anything is not immediately -discoverable via "[`digga`][digga]'s [`mkFlake`][mk-flake], -please file a bug report. - -### Status: Beta -Although this project has already matured quite a bit, especially through -recent outfactoring of [`digga`][digga], a fair amount of api polishing is still -expected. There are unstable versions (0._x_._x_) to help users keep track -of changes and progress, and a [`develop`](https://github.com/divnix/devos/tree/develop) branch for the brave 😜 - -## In the Wild -* @Pacman99: [Personal](https://gitlab.com/coffeetables/lower), [Server](https://gitlab.com/coffeetables/myrdd) -* [@danielphan2003](https://github.com/danielphan2003/flk) and make sure to also check out [devos-ext-lib][devos-ext-lib] -* [PubSolarOS](https://git.sr.ht/~b12f/pub-solar-os) - -## Shoulders -This work does not reinvent the wheel. It stands on the [shoulders of the -following giants][giants]: - -### :onion: — like the layers of an onion -- [`divnix/digga`][digga] -- [`gytis-ivaskevicius/flake-utils-plus`][fup] -- [`numtide/flake-utils`][fu] - -### :family: — like family -- [`numtide/devshell`][devshell] -- [`serokell/deploy-rs`][deploy] -- [`berberman/nvfetcher`][nvfetcher] -- [`NixOS/nixpkgs`][nixpkgs] - -:heart: - -## Inspiration & Art -- [hlissner/dotfiles][dotfiles] -- [nix-user-chroot](https://github.com/nix-community/nix-user-chroot) -- [Nickel](https://github.com/tweag/nickel) -- [Awesome Nix](https://github.com/nix-community/awesome-nix) -- [devshell](https://github.com/numtide/devshell) - -## Divnix -The divnix org is an open space that spontaneously formed out of "the Nix". -It is really just a place where otherwise unrelated people work -together and get stuff done. - -It's a place to stop "geeking out in isolation" (or within company boundaries). -A place to experiment, learn together, and iterate quickly on best practices. -That's what it is. - -It might eventually become a non-profit if that's not too complicated or, if those -goals are sufficiently upstreamed into "the Nix", dissolved. +[![NixOS](https://img.shields.io/badge/NixOS-unstable-blue.svg?style=flat&logo=NixOS&logoColor=white)](https://nixos.org) +[![Chat](https://img.shields.io/badge/chat-join%20us-brightgreen.svg?style=flat&logo=matrix&logoColor=white)](https://matrix.to/#/#devos:nixos.org) + + +Digga — slangy German for "good friend" — is a flake utility library +that helps you declaratively craft and manage all three layers of your system +environment within a single [nix flakes][flakes] repository: + +- development shells (via [`numtide/devshell`][devshell]), +- home environments (via [`nix-community/home-manager`][home-manager]), and +- host configurations (via [`NixOS/nixpkgs/nixos`][nixpkgs]). + +This library is based on [flake-utils-plus][]. + +# Usage +The best way to make use of library is with the [Official template][template]. + +You can also have a look at the different [examples][]. + +# Philosophy + +In it's `lib.mkFlake` function, _Digga_ implements a well-specified API +interface comprising four API containers that allow you to: + +1. configure **nixpkgs channels** including internal and external overlays, + +2. define **NixOS hosts** including internal and external NixOS modules as well as + host defaults that apply to all hosts in the environment, + +3. specify **user home environments** including internal and external home-manager + modules, and + +4. setup & combine a series of **devshells** that you like to have available in + your projects. + +## Modules, Profiles & Suites +For NixOS- & home-manager-modules, _Digga_ allows you to distinguish between +_modules_, _profiles_ and _suites_. + +- **Modules** are abstract configurations that, while holding the implementation, do not +set any system state. + +- **Profiles** are concrete configurations that set system state within the profile domain. + +- **Suites** are a composable, clean and discoverable mechanism for profile aggregation. + +## Internal Art vs External Art +Overlays and modules can be defined internally coming from your repo or externally +coming from an upstream flake. This distinction serves the library to only export +your own work as the public flake output. + +Downstream consumers of your flake can now more easily tell your art apart from +other upstream art. + +# Contributing +We encourage contributions of any kind. The simplest way to get involved is to +join the [chat][] or report problems and ideas on the [issue thread][issues]. + +To craft well thought out APIs we need all the thoughts regarding new ideas. + +Pull Requests are just as amazing. # License -DevOS is licensed under the [MIT License][mit]. -[community]: https://github.com/divnix/devos/tree/community -[core]: https://github.com/divnix/devos -[deploy]: https://github.com/serokell/deploy-rs +Digga is licensed under the [MIT License][mit]. + +[chat]: https://matrix.to/#/#devos:matrix.org [devshell]: https://github.com/numtide/devshell -[digga]: https://github.com/divnix/digga -[dotfiles]: https://github.com/hlissner/dotfiles -[flake-doc]: https://github.com/NixOS/nix/blob/master/src/nix/flake.md +[examples]: https://github.com/divnix/digga/tree/main/examples [flakes]: https://nixos.wiki/wiki/Flakes -[fu]: https://github.com/numtide/flake-utils -[fup]: https://github.com/gytis-ivaskevicius/flake-utils-plus -[giants]: https://en.wikipedia.org/wiki/Standing_on_the_shoulders_of_giants -[home-manager]: https://nix-community.github.io/home-manager +[flake-utils-plus]: https://github.com/gytis-ivaskevicius/flake-utils-plus +[home-manager]: https://github.com/nix-community/home-manager +[issues]: https://github.com/divnix/digga/issues [mit]: https://mit-license.org -[mk-flake]: https://github.com/divnix/digga/tree/main/src/mkFlake [nix]: https://nixos.org/manual/nix/stable -[nixos]: https://nixos.org/manual/nixos/stable -[nixpkgs]: https://github.com/NixOS/nixpkgs -[nvfetcher]: https://github.com/berberman/nvfetcher -[please]: https://github.com/nrdxp/devos/tree/nrd -[matrix]: https://matrix.to/#/#devos:nixos.org -[devos-ext-lib]: https://github.com/divnix/devos-ext-lib +[nixpkgs]: https://github.com/nixos/nixpkgs +[template]: https://github.com/divnix/devos + diff --git a/bors.toml b/bors.toml index 6703d4169..72690c0bb 100644 --- a/bors.toml +++ b/bors.toml @@ -3,3 +3,5 @@ status = [ "check" ] required_approvals = 1 up_to_date_approvals = true + +delete_merged_branches = true diff --git a/checks/default.nix b/checks/default.nix new file mode 100644 index 000000000..584d1d660 --- /dev/null +++ b/checks/default.nix @@ -0,0 +1,40 @@ +{ system ? builtins.currentSystem +, inputs # flake style polyfill not possible, since this depends on digga's internals +}: +let + + nixpkgs = inputs.nixpkgs; + digga = inputs.digga; + lib = nixpkgs.lib // digga.lib; + pkgs = import nixpkgs { inherit system; config = { }; overlays = [ ]; }; + +in +{ + + libTests = pkgs.runCommandNoCC "devos-lib-tests" + { + buildInputs = [ + pkgs.nix + ( + let tests = import ./lib { inherit pkgs lib; }; in + if tests == [ ] then null + else throw (builtins.toJSON tests) + ) + ]; + } '' + datadir="${pkgs.nix}/share" + export TEST_ROOT=$(pwd)/test-tmp + export NIX_BUILD_HOOK= + export NIX_CONF_DIR=$TEST_ROOT/etc + export NIX_LOCALSTATE_DIR=$TEST_ROOT/var + export NIX_LOG_DIR=$TEST_ROOT/var/log/nix + export NIX_STATE_DIR=$TEST_ROOT/var/nix + export NIX_STORE_DIR=$TEST_ROOT/store + export PAGER=cat + cacheDir=$TEST_ROOT/binary-cache + nix-store --init + + touch $out + ''; + +} diff --git a/checks/lib/default.nix b/checks/lib/default.nix new file mode 100644 index 000000000..305818d8b --- /dev/null +++ b/checks/lib/default.nix @@ -0,0 +1,23 @@ +{ pkgs, lib }: +with lib; +lib.runTests { + testRakeLeaves = { + expr = rakeLeaves ./profiles; + expected = { + f = ./profiles/f.nix; + foo = ./profiles/foo; + t = { + bar = ./profiles/t/bar.nix; + }; + }; + }; + + testFlattenTree = { + expr = flattenTree (rakeLeaves ./profiles); + expected = { + f = ./profiles/f.nix; + foo = ./profiles/foo; + "t.bar" = ./profiles/t/bar.nix; + }; + }; +} diff --git a/users/modules/.flake-keep b/checks/lib/profiles/a/b/c.foo similarity index 100% rename from users/modules/.flake-keep rename to checks/lib/profiles/a/b/c.foo diff --git a/checks/lib/profiles/f.nix b/checks/lib/profiles/f.nix new file mode 100644 index 000000000..ffcd4415b --- /dev/null +++ b/checks/lib/profiles/f.nix @@ -0,0 +1 @@ +{ } diff --git a/checks/lib/profiles/foo/default.nix b/checks/lib/profiles/foo/default.nix new file mode 100644 index 000000000..2181e561c --- /dev/null +++ b/checks/lib/profiles/foo/default.nix @@ -0,0 +1,3 @@ +{ + bar = 5; +} diff --git a/checks/lib/profiles/t/bar.nix b/checks/lib/profiles/t/bar.nix new file mode 100644 index 000000000..ffcd4415b --- /dev/null +++ b/checks/lib/profiles/t/bar.nix @@ -0,0 +1 @@ +{ } diff --git a/deprecated.nix b/deprecated.nix new file mode 100644 index 000000000..fd9047666 --- /dev/null +++ b/deprecated.nix @@ -0,0 +1,121 @@ +{ lib, flake-utils-plus, internal-modules, importers, nixosModules }: +let + importers' = importers; +in +lib.warn '' + You are accessing a deprecated item of the digga lib. + Please update timely, it will be remove soon. +'' +rec { + + mkSuites = lib.warn '' + Deprecated Function: mkSuites. + '' + ( + { suites, profiles }: + let + profileSet = lib.genAttrs' profiles (path: { + name = baseNameOf path; + value = mkProfileAttrs (toString path); + }); + in + lib.mapAttrs (_: v: lib.profileMap v) (suites profileSet) + ) + ; + + mkProfileAttrs = lib.warn '' + Deprecated Function: mkProfileAttrs. + '' + ( + dir: + let + imports = + let + files = builtins.readDir dir; + + p = n: v: + v == "directory" + && n != "profiles"; + in + lib.filterAttrs p files; + + f = n: _: + lib.optionalAttrs + (lib.pathExists (dir + "/${n}/default.nix")) + { default = dir + "/${n}"; } + // mkProfileAttrs (dir + "/${n}"); + in + lib.mapAttrs f imports + ) + ; + + profileMap = + lib.warn '' + Deprecated Function: profileMap. + '' + ( + list: map (profile: profile.default) (lib.flatten list) + ) + ; + + + exporters = + lib.warn '' + Deprecated Attribute Set: lib.exporters. + + Please use export* functions instead: + lib.exporters.modulesFromList -> lib.exportModules + lib.exporters.fromOverlays -> lib.exportPackages + lib.exporters.internalOverlays -> lib.exportOverlays + '' + { + modulesFromList = flake-utils-plus.lib.exportModules; + fromOverlays = flake-utils-plus.lib.exportPackages; + internalOverlays = flake-utils-plus.lib.exportOverlays; + } + ; + + modules = + lib.warn '' + Deprecated Attribute Set: lib.modules. + + Internal modules 'customBuilds', 'hmNixosDefaults' & 'globalDefaults' + will be completely removed from the api soon. + + Please use digga.nixosModules for exported modules or proto-modules: + lib.modules.isoConfig -> nixosModules.boostrapIso + '' + ( + internal-modules // { isoConfig = nixosModules.boostrapIso; } + ) + ; + + importModules = + lib.warn '' + Deprecated Function: lib.importModules. + + Use lib.importExportableModules instead to set `exportedModules` option + '' + importers'.importExportableModules; + + importers = + lib.warn '' + Deprecated Attribute Set: lib.importers. + + Please use import* functions instead: + lib.importers.overlays -> lib.importOverlays + lib.importers.modules -> lib.importModules + lib.importers.hosts -> lib.importHosts + lib.importers.rakeLeaves -> lib.rakeLeaves + lib.importers.flattenTree -> lib.flattenTree + '' + { + overlays = importers'.importOverlays; + modules = importers'.importModules; + hosts = importers'.importHosts; + rakeLeaves = importers'.rakeLeaves; + flattenTree = importers'.flattenTree; + } + ; + +} diff --git a/doc/CONTRIBUTING.md b/doc/CONTRIBUTING.md index 86f5dd70e..de6131942 100644 --- a/doc/CONTRIBUTING.md +++ b/doc/CONTRIBUTING.md @@ -1,18 +1,16 @@ -# Pull Requests - -## TL;DR; +# TL;DR; - **Target Branch**: `main` - **Merge Policy**: [`bors`][bors] is always right (→ `bors try`) -- **Docs**: every changeset is expected to contain doc updates +- **Docs**: every change set is expected to contain doc updates - **Commit Msg**: be a poet! Comprehensive and explanatory commit messages should cover the motivation and use case in an easily understandable manner even when read after a few months. -- **Test Driven Development**: please default to test driven development where possible. +- **Test Driven Development**: please default to test driven development you can + make use of the `./examples` & `./e2e` and wire test up in the devshell. ### Within the Devshell (`nix develop`) - **Hooks**: please `git commit` within the devshell -- **Fail Early**: please run from within the devshell on your local machine: - - `nix flake check` +- **Fail Early**: please run `check-all` from within the devshell on your local machine [bors]: https://bors.tech diff --git a/doc/SUMMARY.md b/doc/SUMMARY.md index 1d7bafe95..4ff28332d 100644 --- a/doc/SUMMARY.md +++ b/doc/SUMMARY.md @@ -1,28 +1,10 @@ # Summary - [Introduction](../README.md) -- [Quick Start](./start/index.md) - - [ISO](./start/iso.md) - - [Bootstrapping](./start/bootstrapping.md) - - [From NixOS](./start/from-nixos.md) -- [Key Concepts](./concepts/index.md) - - [Hosts](./concepts/hosts.md) - - [Overrides](./concepts/overrides.md) - - [Profiles](./concepts/profiles.md) - - [Suites](./concepts/suites.md) - - [Users](./concepts/users.md) -- [Outputs](./outputs/index.md) - - [Modules](./outputs/modules.md) - - [Overlays](./outputs/overlays.md) - - [Packages](./outputs/pkgs.md) -- [Concerns]() - - [Secrets](./secrets.md) - - [Tests](./tests.md) -- [Helper Script – `bud`](./bud/index.md) - - [get](./bud/get.md) -- [Integrations](./integrations/index.md) - - [Cachix](./integrations/cachix.md) - - [Deploy RS](./integrations/deploy.md) - - [NvFetcher](./integrations/nvfetcher.md) - - [Hercules CI](./integrations/hercules.md) +- [API Reference](./api-reference.md) + - [Channels](./api-reference-channels.md) + - [Home](./api-reference-home.md) + - [Devshell](./api-reference-devshell.md) + - [NixOS](./api-reference-nixos.md) +- [Library Reference]() - [Contributing](./CONTRIBUTING.md) diff --git a/doc/api-reference-channels.md b/doc/api-reference-channels.md new file mode 100755 index 000000000..9fbc3e7f8 --- /dev/null +++ b/doc/api-reference-channels.md @@ -0,0 +1,75 @@ +# Channels API Container +Configure your channels that you can use throughout your configurations. + +> #### ⚠ Gotcha ⚠ +> Devshell & (non-host-specific) Home-Manager `pkgs` instances are rendered off the +> `nixos.hostDefaults.channelName` (default) channel. + + +## channels +nixpkgs channels to create + + +*_Type_*: +attribute set of submodules or path convertible to it + + +*_Default_* +``` +{} +``` + + + + +## channels.\.config +nixpkgs config for this channel + + +*_Type_*: +attribute set or path convertible to it + + +*_Default_* +``` +{} +``` + + + + +## channels.\.input +nixpkgs flake input to use for this channel + + +*_Type_*: +nix flake + + +*_Default_* +``` +"self.inputs." +``` + + + + +## channels.\.overlays +overlays to apply to this channel +these will get exported under the 'overlays' flake output +as \/\ and any overlay pulled from ${inputs} +will be filtered out + + +*_Type_*: +list of valid Nixpkgs overlay or path convertible to its or anything convertible to it or path convertible to it + + +*_Default_* +``` +[] +``` + + + + diff --git a/doc/api-reference-devshell.md b/doc/api-reference-devshell.md new file mode 100755 index 000000000..28f18087e --- /dev/null +++ b/doc/api-reference-devshell.md @@ -0,0 +1,72 @@ +# Devshell API Container +Configure your devshell module collections of your environment. + + +## devshell +Modules to include in your DevOS shell. the `modules` argument +will be exported under the `devshellModules` output + + +*_Type_*: +submodule or path convertible to it + + +*_Default_* +``` +{} +``` + + + + +## devshell.exportedModules +modules to include in all hosts and export to devshellModules output + + +*_Type_*: +list of valid module or path convertible to its or anything convertible to it + + +*_Default_* +``` +[] +``` + + + + +## devshell.externalModules +The `externalModules` option has been removed. +Any modules that should be exported should be defined with the `exportedModules` +option and all other modules should just go into the `modules` option. + + +*_Type_*: +list of valid modules or anything convertible to it + + +*_Default_* +``` +[] +``` + + + + +## devshell.modules +modules to include that won't be exported +meant importing modules from external flakes + + +*_Type_*: +list of valid modules or anything convertible to it or path convertible to it + + +*_Default_* +``` +[] +``` + + + + diff --git a/doc/api-reference-home.md b/doc/api-reference-home.md new file mode 100755 index 000000000..8d3b05535 --- /dev/null +++ b/doc/api-reference-home.md @@ -0,0 +1,167 @@ +# Home-Manager API Container +Configure your home manager modules, profiles & suites. + + +## home +hosts, modules, suites, and profiles for home-manager + + +*_Type_*: +submodule or path convertible to it + + +*_Default_* +``` +{} +``` + + + + +## home.exportedModules +modules to include in all hosts and export to homeModules output + + +*_Type_*: +list of valid modules or anything convertible to it or path convertible to it + + +*_Default_* +``` +[] +``` + + + + +## home.externalModules +The `externalModules` option has been removed. +Any modules that should be exported should be defined with the `exportedModules` +option and all other modules should just go into the `modules` option. + + +*_Type_*: +list of valid modules or anything convertible to it + + +*_Default_* +``` +[] +``` + + + + +## home.importables +Packages of paths to be passed to modules as `specialArgs`. + + +*_Type_*: +attribute set + + +*_Default_* +``` +{} +``` + + + + +## home.importables.suites +collections of profiles + + +*_Type_*: +null or attribute set of list of paths or anything convertible to its or path convertible to it + + +*_Default_* +``` +null +``` + + + + +## home.modules +modules to include that won't be exported +meant importing modules from external flakes + + +*_Type_*: +list of valid modules or anything convertible to it or path convertible to it + + +*_Default_* +``` +[] +``` + + + + +## home.profiles +WARNING: The 'suites' and `profiles` options have been deprecated, you can now create +both with the importables option. `rakeLeaves` can be used to create profiles and +by passing a module or `rec` set to `importables`, suites can access profiles. +Example: +``` +importables = rec { + profiles = digga.lib.rakeLeaves ./profiles; + suites = with profiles; { }; +} +``` +See https://github.com/divnix/digga/pull/30 for more details + + +*_Type_*: +list of paths or path convertible to it + + +*_Default_* +``` +[] +``` + + + + +## home.suites +WARNING: The 'suites' and `profiles` options have been deprecated, you can now create +both with the importables option. `rakeLeaves` can be used to create profiles and +by passing a module or `rec` set to `importables`, suites can access profiles. +Example: +``` +importables = rec { + profiles = digga.lib.rakeLeaves ./profiles; + suites = with profiles; { }; +} +``` +See https://github.com/divnix/digga/pull/30 for more details + + +*_Type_*: +function that evaluates to a(n) attrs or path convertible to it + + + + + + +## home.users +HM users that can be deployed portably without a host. + + +*_Type_*: +attribute set of HM user configs + + +*_Default_* +``` +{} +``` + + + + diff --git a/doc/api-reference-nixos.md b/doc/api-reference-nixos.md new file mode 100755 index 000000000..6d2a8d673 --- /dev/null +++ b/doc/api-reference-nixos.md @@ -0,0 +1,282 @@ +# NixOS API Container +Configure your nixos modules, profiles & suites. + + +## nixos +hosts, modules, suites, and profiles for NixOS + + +*_Type_*: +submodule or path convertible to it + + +*_Default_* +``` +{} +``` + + + + +## nixos.hostDefaults +Defaults for all hosts. +the modules passed under hostDefaults will be exported +to the 'nixosModules' flake output. +They will also be added to all hosts. + + +*_Type_*: +submodule + + +*_Default_* +``` +{} +``` + + + + +## nixos.hostDefaults.channelName +Channel this host should follow + + +*_Type_*: +channel defined in `channels` + + + + + + +## nixos.hostDefaults.exportedModules +modules to include in all hosts and export to nixosModules output + + +*_Type_*: +list of valid modules or anything convertible to it or path convertible to it + + +*_Default_* +``` +[] +``` + + + + +## nixos.hostDefaults.externalModules +The `externalModules` option has been removed. +Any modules that should be exported should be defined with the `exportedModules` +option and all other modules should just go into the `modules` option. + + +*_Type_*: +list of valid modules or anything convertible to it + + +*_Default_* +``` +[] +``` + + + + +## nixos.hostDefaults.modules +modules to include that won't be exported +meant importing modules from external flakes + + +*_Type_*: +list of valid modules or anything convertible to it or path convertible to it + + +*_Default_* +``` +[] +``` + + + + +## nixos.hostDefaults.system +system for this host + + +*_Type_*: +null or system defined in `supportedSystems` + + +*_Default_* +``` +null +``` + + + + +## nixos.hosts +configurations to include in the nixosConfigurations output + + +*_Type_*: +attribute set of submodules + + +*_Default_* +``` +{} +``` + + + + +## nixos.hosts.\.channelName +Channel this host should follow + + +*_Type_*: +null or channel defined in `channels` + + +*_Default_* +``` +null +``` + + + + +## nixos.hosts.\.modules +modules to include + + +*_Type_*: +list of valid modules or anything convertible to it or path convertible to it + + +*_Default_* +``` +[] +``` + + + + +## nixos.hosts.\.system +system for this host + + +*_Type_*: +null or system defined in `supportedSystems` + + +*_Default_* +``` +null +``` + + + + +## nixos.hosts.\.tests +tests to run + + +*_Type_*: +list of valid NixOS test or path convertible to its or anything convertible to it + + +*_Default_* +``` +[] +``` + + +*_Example_* +``` +{"_type":"literalExpression","text":"[\n {\n name = \"testname1\";\n machine = { ... };\n testScript = ''\n # ...\n '';\n }\n ({ corutils, writers, ... }: {\n name = \"testname2\";\n machine = { ... };\n testScript = ''\n # ...\n '';\n })\n ./path/to/test.nix\n];\n"} +``` + + +## nixos.importables +Packages of paths to be passed to modules as `specialArgs`. + + +*_Type_*: +attribute set + + +*_Default_* +``` +{} +``` + + + + +## nixos.importables.suites +collections of profiles + + +*_Type_*: +null or attribute set of list of paths or anything convertible to its or path convertible to it + + +*_Default_* +``` +null +``` + + + + +## nixos.profiles +WARNING: The 'suites' and `profiles` options have been deprecated, you can now create +both with the importables option. `rakeLeaves` can be used to create profiles and +by passing a module or `rec` set to `importables`, suites can access profiles. +Example: +``` +importables = rec { + profiles = digga.lib.rakeLeaves ./profiles; + suites = with profiles; { }; +} +``` +See https://github.com/divnix/digga/pull/30 for more details + + +*_Type_*: +list of paths or path convertible to it + + +*_Default_* +``` +[] +``` + + + + +## nixos.suites +WARNING: The 'suites' and `profiles` options have been deprecated, you can now create +both with the importables option. `rakeLeaves` can be used to create profiles and +by passing a module or `rec` set to `importables`, suites can access profiles. +Example: +``` +importables = rec { + profiles = digga.lib.rakeLeaves ./profiles; + suites = with profiles; { }; +} +``` +See https://github.com/divnix/digga/pull/30 for more details + + +*_Type_*: +function that evaluates to a(n) attrs or path convertible to it + + + + + + diff --git a/doc/api-reference.md b/doc/api-reference.md new file mode 100755 index 000000000..41694c24c --- /dev/null +++ b/doc/api-reference.md @@ -0,0 +1,79 @@ +# Top Level API +`digga`'s top level API. API Containers are documented in their respective sub-chapter: + +- [Channels](./api-reference-channels.md) +- [Home](./api-reference-home.md) +- [Devshell](./api-reference-devshell.md) +- [NixOS](./api-reference-nixos.md) + +## channelsConfig +nixpkgs config for all channels + + +*_Type_*: +attribute set or path convertible to it + + +*_Default_* +``` +{} +``` + + + + +## inputs +The flake's inputs + +*_Type_*: +attribute set of nix flakes + + + + + + +## outputsBuilder +builder for flake system-spaced outputs +The builder gets passed an attrset of all channels + + +*_Type_*: +function that evaluates to a(n) attrs or path convertible to it + + +*_Default_* +``` +"channels: { }" +``` + + + + +## self +The flake to create the DevOS outputs for + +*_Type_*: +nix flake + + + + + + +## supportedSystems +The systems supported by this flake + + +*_Type_*: +list of strings + + +*_Default_* +``` +["aarch64-linux","aarch64-darwin","i686-linux","x86_64-darwin","x86_64-linux"] +``` + + + + diff --git a/doc/book.toml b/doc/book.toml index 373d26fd4..c3ab1e2b9 100644 --- a/doc/book.toml +++ b/doc/book.toml @@ -1,6 +1,10 @@ [book] -authors = ["Timothy DeHerrera"] +authors = [ + "Timothy DeHerrera", + "Parthiv Seetharaman", + "David Arnold", +] language = "en" multilingual = false src = "." -title = "devos docs" +title = "Digga Library Docs" diff --git a/doc/tests.md b/doc/tests.md index 4844912d3..9c47a577f 100644 --- a/doc/tests.md +++ b/doc/tests.md @@ -12,12 +12,21 @@ packages during their [check phase][check]. All packages and their tests will be built during CI. ## Integration Tests -All your profiles defined in suites will be tested in a NixOS VM. +All your profiles defined in suites can be tested against an individual host. +Simply use digga's pre-baked `digga.lib.allProfilesTest` like so: + +```nix +{ + hosts = { + Morty.tests = [ allProfilesTest ]; + }; +} +``` You can write integration tests for one or more NixOS VMs that can, optionally, be networked together, and yes, it's as awesome as it sounds! -Be sure to use the `mkTest` function from digga, `digga.lib.pkgs-lib.mkTest` +Be sure to use the `mkTest` function from Digga, `digga.lib.mkTest` which wraps the official [testing-python][testing-python] function to ensure that the system is setup exactly as it is for a bare DevOS system. There are already great resources for learning how to use these tests effectively, @@ -26,7 +35,7 @@ and the examples in [nixpkgs][nixos-tests]. [test-doc]: https://nixos.org/manual/nixos/stable/index.html#sec-nixos-tests [test-blog]: https://www.haskellforall.com/2020/11/how-to-use-nixos-for-lightweight.html -[default]: https://github.com/divnix/devos/tree/main/tests/default.nix +[default]: https://github.com/divnix/devos/tree/core/tests/default.nix [run-test]: https://github.com/NixOS/nixpkgs/blob/6571462647d7316aff8b8597ecdf5922547bf365/lib/debug.nix#L154-L166 [nixos-tests]: https://github.com/NixOS/nixpkgs/tree/master/nixos/tests [testing-python]: https://github.com/NixOS/nixpkgs/tree/master/nixos/lib/testing-python.nix diff --git a/examples/devos/.editorconfig b/examples/devos/.editorconfig new file mode 100644 index 000000000..96e5188b3 --- /dev/null +++ b/examples/devos/.editorconfig @@ -0,0 +1,32 @@ +# Editor configuration, see http://editorconfig.org +root = true + +[*] +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +charset = utf-8 +indent_style = space +indent_size = 2 + +# Ignore diffs/patches +[*.{diff,patch}] +end_of_line = unset +insert_final_newline = unset +trim_trailing_whitespace = unset +indent_size = unset + +[{.*,secrets}/**] +end_of_line = unset +insert_final_newline = unset +trim_trailing_whitespace = unset +charset = unset +indent_style = unset +indent_size = unset + +[*.py] +indent_size = 4 + +[*.md] +max_line_length = off +trim_trailing_whitespace = false diff --git a/.envrc b/examples/devos/.envrc similarity index 100% rename from .envrc rename to examples/devos/.envrc diff --git a/examples/devos/.gitignore b/examples/devos/.gitignore new file mode 100644 index 000000000..6cce155f3 --- /dev/null +++ b/examples/devos/.gitignore @@ -0,0 +1,10 @@ +result +.direnv +doc/index.html + +# Result of bud commands +vm +iso +doi + +pkgs/_sources/.shake* diff --git a/examples/devos/CHANGELOG.md b/examples/devos/CHANGELOG.md new file mode 100644 index 000000000..b8d9a688f --- /dev/null +++ b/examples/devos/CHANGELOG.md @@ -0,0 +1,114 @@ +# Changelog + +## [v0.10.0](https://github.com/divnix/devos/tree/v0.10.0) (2021-05-24) + +**Implemented enhancements:** + +- Providing an interface to nixpkgs.config [\#237](https://github.com/divnix/devos/issues/237) +- Making the user available in profiles [\#230](https://github.com/divnix/devos/issues/230) +- copy evaluation store paths to iso [\#195](https://github.com/divnix/devos/issues/195) +- Extract custom system builds from devosSystem out of lib [\#170](https://github.com/divnix/devos/issues/170) +- Allow setting of channel host-wide [\#117](https://github.com/divnix/devos/issues/117) +- alacritty: CSIu support [\#51](https://github.com/divnix/devos/issues/51) + +**Fixed bugs:** + +- Cachix timeouts + how to disable nrdxp cachix \(if needed\) [\#294](https://github.com/divnix/devos/issues/294) +- default.nix flake-compat is broken [\#285](https://github.com/divnix/devos/issues/285) +- All suites return "attribute missing" [\#282](https://github.com/divnix/devos/issues/282) +- nix is built two times [\#203](https://github.com/divnix/devos/issues/203) +- fix lib docs [\#166](https://github.com/divnix/devos/issues/166) + +**Closed issues:** + +- eliminate userFlakeNixOS [\#257](https://github.com/divnix/devos/issues/257) +- devos-as-library [\#214](https://github.com/divnix/devos/issues/214) + +**Merged pull requests:** + +- Update evalArgs to match the new planned API [\#239](https://github.com/divnix/devos/pull/239) + +## [v0.9.0](https://github.com/divnix/devos/tree/v0.9.0) (2021-04-19) + +**Implemented enhancements:** + +- pin inputs into iso live registry [\#190](https://github.com/divnix/devos/issues/190) +- Pass 'self' to lib [\#169](https://github.com/divnix/devos/issues/169) +- doc: quickstart "ISO. What next?" [\#167](https://github.com/divnix/devos/issues/167) +- Integrate Android AOSP putting mobile under control [\#149](https://github.com/divnix/devos/issues/149) +- Inoculate host identity on first use [\#132](https://github.com/divnix/devos/issues/132) +- kubenix support [\#130](https://github.com/divnix/devos/issues/130) +- Improve Home Manager support: profiles/suites, modules, extern, flake outputs [\#119](https://github.com/divnix/devos/issues/119) +- Local CA \(between hosts\) [\#104](https://github.com/divnix/devos/issues/104) +- Q5: git annex for machine state [\#68](https://github.com/divnix/devos/issues/68) +- name space ./pkgs overlays [\#60](https://github.com/divnix/devos/issues/60) +- remap global keys easily [\#57](https://github.com/divnix/devos/issues/57) +- make pass state part of this repo's structure [\#56](https://github.com/divnix/devos/issues/56) +- Incorporate ./shells [\#38](https://github.com/divnix/devos/issues/38) +- Encrypt with \(r\)age [\#37](https://github.com/divnix/devos/issues/37) + +**Fixed bugs:** + +- `pathsToImportedAttrs` does not accept directories [\#221](https://github.com/divnix/devos/issues/221) +- Cachix caches aren't added to the configuration [\#208](https://github.com/divnix/devos/issues/208) +- Issues with current changelog workflow [\#205](https://github.com/divnix/devos/issues/205) +- iso: systemd service startup [\#194](https://github.com/divnix/devos/issues/194) +- Help adding easy-hls-nix to devos [\#174](https://github.com/divnix/devos/issues/174) +- `flk update` fails because of obsolete flag [\#159](https://github.com/divnix/devos/issues/159) +- Expected that not all packages are exported? [\#151](https://github.com/divnix/devos/issues/151) +- Segmentation fault when generating iso [\#150](https://github.com/divnix/devos/issues/150) + +**Documentation:** + +- doc: split iso [\#193](https://github.com/divnix/devos/issues/193) +- lib: can depend on pkgs \(a la nixpkgs\#pkgs/pkgs-lib\) [\#147](https://github.com/divnix/devos/pull/147) + +**Closed issues:** + +- FRRouting router implementation [\#154](https://github.com/divnix/devos/issues/154) +- ARM aarch64 Support [\#72](https://github.com/divnix/devos/issues/72) + +## [v0.8.0](https://github.com/divnix/devos/tree/v0.8.0) (2021-03-02) + +**Implemented enhancements:** + +- semi automatic update for /pkgs [\#118](https://github.com/divnix/devos/issues/118) +- Home-manager external modules from flakes [\#106](https://github.com/divnix/devos/issues/106) + +**Fixed bugs:** + +- My emacsGcc overlay is not working [\#146](https://github.com/divnix/devos/issues/146) +- local flake registry freezes branches [\#142](https://github.com/divnix/devos/issues/142) +- nixos-option no longer works after collect garbage [\#138](https://github.com/divnix/devos/issues/138) +- Profiles imports are brittle, causing failure if imported twice [\#136](https://github.com/divnix/devos/issues/136) + +## [0.7.0](https://github.com/divnix/devos/tree/0.7.0) (2021-02-20) + +**Implemented enhancements:** + +- add zoxide [\#53](https://github.com/divnix/devos/issues/53) +- Multiarch support? [\#17](https://github.com/divnix/devos/issues/17) +- initial multiArch support [\#18](https://github.com/divnix/devos/pull/18) + +**Fixed bugs:** + +- Missing shebang from flk.sh [\#131](https://github.com/divnix/devos/issues/131) +- Rename Meta Issue [\#128](https://github.com/divnix/devos/issues/128) +- specialisations break the `system` argument [\#46](https://github.com/divnix/devos/issues/46) +- Revert "Add extraArgs to lib.nixosSystem call to add system args." [\#47](https://github.com/divnix/devos/pull/47) + +**Documentation:** + +- update home-manager urls [\#62](https://github.com/divnix/devos/pull/62) + +**Closed issues:** + +- add github action for cachix build ci [\#59](https://github.com/divnix/devos/issues/59) + +## [12052020](https://github.com/divnix/devos/tree/12052020) (2020-12-06) + +## [07092020](https://github.com/divnix/devos/tree/07092020) (2020-07-09) + + + +\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)* diff --git a/examples/devos/COPYING b/examples/devos/COPYING new file mode 100644 index 000000000..c9b44cb8a --- /dev/null +++ b/examples/devos/COPYING @@ -0,0 +1,18 @@ +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/examples/devos/README.md b/examples/devos/README.md new file mode 100644 index 000000000..e2a83eb90 --- /dev/null +++ b/examples/devos/README.md @@ -0,0 +1,95 @@ +[![NixOS](https://img.shields.io/badge/NixOS-unstable-blue.svg?style=flat&logo=NixOS&logoColor=white)](https://nixos.org) +[![MIT License](https://img.shields.io/github/license/divnix/devos)][mit] +[![Chat](https://img.shields.io/matrix/devos:nixos.org.svg?label=%23devos%3Anixos.org&logo=matrix&server_fqdn=matrix.org)][matrix] + +> #### ⚠ Advisory ⚠ +> DevOS requires the [flakes][flakes] feature available via an _experimental_ +> branch of [nix][nix]. Until nix 2.4 is released, this project +> should be considered unstable. + +### Why? +Make an awesome template for NixOS users, with consideration for common tools like [home-manager][home-manager], +[devshell][devshell], and [more](./doc/integrations). + +### No. Why _flakes_? +Flakes are a part of an explicit push to improve [Nix's UX](https://github.com/NixOS/nix/blob/master/doc/manual/src/contributing/cli-guideline.md), and have become an integral part of that effort. + +They also make [Nix expressions](https://nixos.org/manual/nix/unstable/expressions/expression-syntax.html) easier to distribute and reuse with convient [flake references](https://github.com/NixOS/nix/blob/master/src/nix/flake.md#flake-references) for building or using packages, modules, and whole systems. + +## Getting Started +Check out the [guide](https://devos.divnix.com/start) to get up and running. +Also, have a look at [_flake.nix_](./flake.nix). If anything is not immediately +discoverable via "[`digga`][digga]'s [`mkFlake`][mk-flake], +please file a bug report. + +### Status: Beta +Although this project has already matured quite a bit, especially through +recent outfactoring of [`digga`][digga], a fair amount of api polishing is still +expected. There are unstable versions (0._x_._x_) to help users keep track +of changes and progress, and a [`develop`](https://github.com/divnix/devos/tree/develop) branch for the brave 😜 + +## In the Wild +* @Pacman99: [Personal](https://gitlab.com/coffeetables/lower), [Server](https://gitlab.com/coffeetables/myrdd) +* [@danielphan2003](https://github.com/danielphan2003/flk) and make sure to also check out [devos-ext-lib][devos-ext-lib] +* [PubSolarOS](https://git.sr.ht/~b12f/pub-solar-os) + +## Shoulders +This work does not reinvent the wheel. It stands on the [shoulders of the +following giants][giants]: + +### :onion: — like the layers of an onion +- [`divnix/digga`][digga] +- [`gytis-ivaskevicius/flake-utils-plus`][fup] +- [`numtide/flake-utils`][fu] + +### :family: — like family +- [`numtide/devshell`][devshell] +- [`serokell/deploy-rs`][deploy] +- [`berberman/nvfetcher`][nvfetcher] +- [`NixOS/nixpkgs`][nixpkgs] + +:heart: + +## Inspiration & Art +- [hlissner/dotfiles][dotfiles] +- [nix-user-chroot](https://github.com/nix-community/nix-user-chroot) +- [Nickel](https://github.com/tweag/nickel) +- [Awesome Nix](https://github.com/nix-community/awesome-nix) +- [devshell](https://github.com/numtide/devshell) + +## Divnix +The divnix org is an open space that spontaneously formed out of "the Nix". +It is really just a place where otherwise unrelated people work +together and get stuff done. + +It's a place to stop "geeking out in isolation" (or within company boundaries). +A place to experiment, learn together, and iterate quickly on best practices. +That's what it is. + +It might eventually become a non-profit if that's not too complicated or, if those +goals are sufficiently upstreamed into "the Nix", dissolved. + +# License +DevOS is licensed under the [MIT License][mit]. + +[community]: https://github.com/divnix/devos/tree/community +[core]: https://github.com/divnix/devos +[deploy]: https://github.com/serokell/deploy-rs +[devshell]: https://github.com/numtide/devshell +[digga]: https://github.com/divnix/digga +[dotfiles]: https://github.com/hlissner/dotfiles +[flake-doc]: https://github.com/NixOS/nix/blob/master/src/nix/flake.md +[flakes]: https://nixos.wiki/wiki/Flakes +[fu]: https://github.com/numtide/flake-utils +[fup]: https://github.com/gytis-ivaskevicius/flake-utils-plus +[giants]: https://en.wikipedia.org/wiki/Standing_on_the_shoulders_of_giants +[home-manager]: https://nix-community.github.io/home-manager +[mit]: https://mit-license.org +[mk-flake]: https://github.com/divnix/digga/tree/main/src/mkFlake +[nix]: https://nixos.org/manual/nix/stable +[nixos]: https://nixos.org/manual/nixos/stable +[nixpkgs]: https://github.com/NixOS/nixpkgs +[nvfetcher]: https://github.com/berberman/nvfetcher +[please]: https://github.com/nrdxp/devos/tree/nrd +[matrix]: https://matrix.to/#/#devos:nixos.org +[devos-ext-lib]: https://github.com/divnix/devos-ext-lib diff --git a/examples/devos/bors.toml b/examples/devos/bors.toml new file mode 100644 index 000000000..6703d4169 --- /dev/null +++ b/examples/devos/bors.toml @@ -0,0 +1,5 @@ +status = [ "check" ] + +required_approvals = 1 + +up_to_date_approvals = true diff --git a/default.nix b/examples/devos/default.nix similarity index 100% rename from default.nix rename to examples/devos/default.nix diff --git a/examples/devos/doc/.gitignore b/examples/devos/doc/.gitignore new file mode 100644 index 000000000..7585238ef --- /dev/null +++ b/examples/devos/doc/.gitignore @@ -0,0 +1 @@ +book diff --git a/examples/devos/doc/CONTRIBUTING.md b/examples/devos/doc/CONTRIBUTING.md new file mode 100644 index 000000000..86f5dd70e --- /dev/null +++ b/examples/devos/doc/CONTRIBUTING.md @@ -0,0 +1,18 @@ +# Pull Requests + +## TL;DR; +- **Target Branch**: `main` +- **Merge Policy**: [`bors`][bors] is always right (→ `bors try`) +- **Docs**: every changeset is expected to contain doc updates +- **Commit Msg**: be a poet! Comprehensive and explanatory commit messages + should cover the motivation and use case in an easily understandable manner + even when read after a few months. +- **Test Driven Development**: please default to test driven development where possible. + +### Within the Devshell (`nix develop`) +- **Hooks**: please `git commit` within the devshell +- **Fail Early**: please run from within the devshell on your local machine: + - `nix flake check` + +[bors]: https://bors.tech + diff --git a/examples/devos/doc/SUMMARY.md b/examples/devos/doc/SUMMARY.md new file mode 100644 index 000000000..1d7bafe95 --- /dev/null +++ b/examples/devos/doc/SUMMARY.md @@ -0,0 +1,28 @@ +# Summary + +- [Introduction](../README.md) +- [Quick Start](./start/index.md) + - [ISO](./start/iso.md) + - [Bootstrapping](./start/bootstrapping.md) + - [From NixOS](./start/from-nixos.md) +- [Key Concepts](./concepts/index.md) + - [Hosts](./concepts/hosts.md) + - [Overrides](./concepts/overrides.md) + - [Profiles](./concepts/profiles.md) + - [Suites](./concepts/suites.md) + - [Users](./concepts/users.md) +- [Outputs](./outputs/index.md) + - [Modules](./outputs/modules.md) + - [Overlays](./outputs/overlays.md) + - [Packages](./outputs/pkgs.md) +- [Concerns]() + - [Secrets](./secrets.md) + - [Tests](./tests.md) +- [Helper Script – `bud`](./bud/index.md) + - [get](./bud/get.md) +- [Integrations](./integrations/index.md) + - [Cachix](./integrations/cachix.md) + - [Deploy RS](./integrations/deploy.md) + - [NvFetcher](./integrations/nvfetcher.md) + - [Hercules CI](./integrations/hercules.md) +- [Contributing](./CONTRIBUTING.md) diff --git a/examples/devos/doc/book.toml b/examples/devos/doc/book.toml new file mode 100644 index 000000000..373d26fd4 --- /dev/null +++ b/examples/devos/doc/book.toml @@ -0,0 +1,6 @@ +[book] +authors = ["Timothy DeHerrera"] +language = "en" +multilingual = false +src = "." +title = "devos docs" diff --git a/doc/bud/get.md b/examples/devos/doc/bud/get.md similarity index 100% rename from doc/bud/get.md rename to examples/devos/doc/bud/get.md diff --git a/doc/bud/index.md b/examples/devos/doc/bud/index.md similarity index 100% rename from doc/bud/index.md rename to examples/devos/doc/bud/index.md diff --git a/doc/concepts/hosts.md b/examples/devos/doc/concepts/hosts.md similarity index 100% rename from doc/concepts/hosts.md rename to examples/devos/doc/concepts/hosts.md diff --git a/doc/concepts/index.md b/examples/devos/doc/concepts/index.md similarity index 100% rename from doc/concepts/index.md rename to examples/devos/doc/concepts/index.md diff --git a/doc/concepts/overrides.md b/examples/devos/doc/concepts/overrides.md similarity index 100% rename from doc/concepts/overrides.md rename to examples/devos/doc/concepts/overrides.md diff --git a/doc/concepts/profiles.md b/examples/devos/doc/concepts/profiles.md similarity index 100% rename from doc/concepts/profiles.md rename to examples/devos/doc/concepts/profiles.md diff --git a/doc/concepts/suites.md b/examples/devos/doc/concepts/suites.md similarity index 100% rename from doc/concepts/suites.md rename to examples/devos/doc/concepts/suites.md diff --git a/doc/concepts/users.md b/examples/devos/doc/concepts/users.md similarity index 100% rename from doc/concepts/users.md rename to examples/devos/doc/concepts/users.md diff --git a/doc/integrations/cachix.md b/examples/devos/doc/integrations/cachix.md similarity index 100% rename from doc/integrations/cachix.md rename to examples/devos/doc/integrations/cachix.md diff --git a/doc/integrations/deploy.md b/examples/devos/doc/integrations/deploy.md similarity index 100% rename from doc/integrations/deploy.md rename to examples/devos/doc/integrations/deploy.md diff --git a/doc/integrations/hercules.md b/examples/devos/doc/integrations/hercules.md similarity index 100% rename from doc/integrations/hercules.md rename to examples/devos/doc/integrations/hercules.md diff --git a/doc/integrations/index.md b/examples/devos/doc/integrations/index.md similarity index 100% rename from doc/integrations/index.md rename to examples/devos/doc/integrations/index.md diff --git a/doc/integrations/nvfetcher.md b/examples/devos/doc/integrations/nvfetcher.md similarity index 100% rename from doc/integrations/nvfetcher.md rename to examples/devos/doc/integrations/nvfetcher.md diff --git a/doc/outputs/index.md b/examples/devos/doc/outputs/index.md similarity index 100% rename from doc/outputs/index.md rename to examples/devos/doc/outputs/index.md diff --git a/doc/outputs/modules.md b/examples/devos/doc/outputs/modules.md similarity index 100% rename from doc/outputs/modules.md rename to examples/devos/doc/outputs/modules.md diff --git a/doc/outputs/overlays.md b/examples/devos/doc/outputs/overlays.md similarity index 100% rename from doc/outputs/overlays.md rename to examples/devos/doc/outputs/overlays.md diff --git a/doc/outputs/pkgs.md b/examples/devos/doc/outputs/pkgs.md similarity index 100% rename from doc/outputs/pkgs.md rename to examples/devos/doc/outputs/pkgs.md diff --git a/doc/secrets.md b/examples/devos/doc/secrets.md similarity index 100% rename from doc/secrets.md rename to examples/devos/doc/secrets.md diff --git a/doc/start/bootstrapping.md b/examples/devos/doc/start/bootstrapping.md similarity index 100% rename from doc/start/bootstrapping.md rename to examples/devos/doc/start/bootstrapping.md diff --git a/doc/start/from-nixos.md b/examples/devos/doc/start/from-nixos.md similarity index 100% rename from doc/start/from-nixos.md rename to examples/devos/doc/start/from-nixos.md diff --git a/doc/start/index.md b/examples/devos/doc/start/index.md similarity index 100% rename from doc/start/index.md rename to examples/devos/doc/start/index.md diff --git a/doc/start/iso.md b/examples/devos/doc/start/iso.md similarity index 100% rename from doc/start/iso.md rename to examples/devos/doc/start/iso.md diff --git a/examples/devos/doc/tests.md b/examples/devos/doc/tests.md new file mode 100644 index 000000000..4844912d3 --- /dev/null +++ b/examples/devos/doc/tests.md @@ -0,0 +1,33 @@ +# Testing + +Testing is always an important aspect of any software development project, and +NixOS offers some incredibly powerful tools to write tests for your +configuration, and, optionally, run them in +[CI](./integrations/hercules.md). + +## Unit Tests +Unit tests can be created from regular derivations, and they can do +almost anything you can imagine. By convention, it is best to test your +packages during their [check phase][check]. All packages and their tests will +be built during CI. + +## Integration Tests +All your profiles defined in suites will be tested in a NixOS VM. + +You can write integration tests for one or more NixOS VMs that can, +optionally, be networked together, and yes, it's as awesome as it sounds! + +Be sure to use the `mkTest` function from digga, `digga.lib.pkgs-lib.mkTest` +which wraps the official [testing-python][testing-python] function to ensure +that the system is setup exactly as it is for a bare DevOS system. There are +already great resources for learning how to use these tests effectively, +including the official [docs][test-doc], a fantastic [blog post][test-blog], +and the examples in [nixpkgs][nixos-tests]. + +[test-doc]: https://nixos.org/manual/nixos/stable/index.html#sec-nixos-tests +[test-blog]: https://www.haskellforall.com/2020/11/how-to-use-nixos-for-lightweight.html +[default]: https://github.com/divnix/devos/tree/main/tests/default.nix +[run-test]: https://github.com/NixOS/nixpkgs/blob/6571462647d7316aff8b8597ecdf5922547bf365/lib/debug.nix#L154-L166 +[nixos-tests]: https://github.com/NixOS/nixpkgs/tree/master/nixos/tests +[testing-python]: https://github.com/NixOS/nixpkgs/tree/master/nixos/lib/testing-python.nix +[check]: https://nixos.org/manual/nixpkgs/stable/#ssec-check-phase diff --git a/examples/devos/doc/theme/highlight.js b/examples/devos/doc/theme/highlight.js new file mode 100644 index 000000000..f4fd4faea --- /dev/null +++ b/examples/devos/doc/theme/highlight.js @@ -0,0 +1,6 @@ +/* + Highlight.js 10.1.2 (edd73d24) + License: BSD-3-Clause + Copyright (c) 2006-2020, Ivan Sagalaev +*/ +var hljs=function(){"use strict";function e(n){Object.freeze(n);var t="function"==typeof n;return Object.getOwnPropertyNames(n).forEach((function(r){!Object.hasOwnProperty.call(n,r)||null===n[r]||"object"!=typeof n[r]&&"function"!=typeof n[r]||t&&("caller"===r||"callee"===r||"arguments"===r)||Object.isFrozen(n[r])||e(n[r])})),n}class n{constructor(e){void 0===e.data&&(e.data={}),this.data=e.data}ignoreMatch(){this.ignore=!0}}function t(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}function r(e,...n){var t={};for(const n in e)t[n]=e[n];return n.forEach((function(e){for(const n in e)t[n]=e[n]})),t}function a(e){return e.nodeName.toLowerCase()}var i=Object.freeze({__proto__:null,escapeHTML:t,inherit:r,nodeStream:function(e){var n=[];return function e(t,r){for(var i=t.firstChild;i;i=i.nextSibling)3===i.nodeType?r+=i.nodeValue.length:1===i.nodeType&&(n.push({event:"start",offset:r,node:i}),r=e(i,r),a(i).match(/br|hr|img|input/)||n.push({event:"stop",offset:r,node:i}));return r}(e,0),n},mergeStreams:function(e,n,r){var i=0,s="",o=[];function l(){return e.length&&n.length?e[0].offset!==n[0].offset?e[0].offset"}function u(e){s+=""}function d(e){("start"===e.event?c:u)(e.node)}for(;e.length||n.length;){var g=l();if(s+=t(r.substring(i,g[0].offset)),i=g[0].offset,g===e){o.reverse().forEach(u);do{d(g.splice(0,1)[0]),g=l()}while(g===e&&g.length&&g[0].offset===i);o.reverse().forEach(c)}else"start"===g[0].event?o.push(g[0].node):o.pop(),d(g.splice(0,1)[0])}return s+t(r.substr(i))}});const s="",o=e=>!!e.kind;class l{constructor(e,n){this.buffer="",this.classPrefix=n.classPrefix,e.walk(this)}addText(e){this.buffer+=t(e)}openNode(e){if(!o(e))return;let n=e.kind;e.sublanguage||(n=`${this.classPrefix}${n}`),this.span(n)}closeNode(e){o(e)&&(this.buffer+=s)}value(){return this.buffer}span(e){this.buffer+=``}}class c{constructor(){this.rootNode={children:[]},this.stack=[this.rootNode]}get top(){return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){this.top.children.push(e)}openNode(e){const n={kind:e,children:[]};this.add(n),this.stack.push(n)}closeNode(){if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)}walk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,n){return"string"==typeof n?e.addText(n):n.children&&(e.openNode(n),n.children.forEach(n=>this._walk(e,n)),e.closeNode(n)),e}static _collapse(e){"string"!=typeof e&&e.children&&(e.children.every(e=>"string"==typeof e)?e.children=[e.children.join("")]:e.children.forEach(e=>{c._collapse(e)}))}}class u extends c{constructor(e){super(),this.options=e}addKeyword(e,n){""!==e&&(this.openNode(n),this.addText(e),this.closeNode())}addText(e){""!==e&&this.add(e)}addSublanguage(e,n){const t=e.root;t.kind=n,t.sublanguage=!0,this.add(t)}toHTML(){return new l(this,this.options).value()}finalize(){return!0}}function d(e){return e?"string"==typeof e?e:e.source:null}const g="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",h={begin:"\\\\[\\s\\S]",relevance:0},f={className:"string",begin:"'",end:"'",illegal:"\\n",contains:[h]},p={className:"string",begin:'"',end:'"',illegal:"\\n",contains:[h]},b={begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},m=function(e,n,t={}){var a=r({className:"comment",begin:e,end:n,contains:[]},t);return a.contains.push(b),a.contains.push({className:"doctag",begin:"(?:TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):",relevance:0}),a},v=m("//","$"),x=m("/\\*","\\*/"),E=m("#","$");var _=Object.freeze({__proto__:null,IDENT_RE:"[a-zA-Z]\\w*",UNDERSCORE_IDENT_RE:"[a-zA-Z_]\\w*",NUMBER_RE:"\\b\\d+(\\.\\d+)?",C_NUMBER_RE:g,BINARY_NUMBER_RE:"\\b(0b[01]+)",RE_STARTERS_RE:"!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",SHEBANG:(e={})=>{const n=/^#![ ]*\//;return e.binary&&(e.begin=function(...e){return e.map(e=>d(e)).join("")}(n,/.*\b/,e.binary,/\b.*/)),r({className:"meta",begin:n,end:/$/,relevance:0,"on:begin":(e,n)=>{0!==e.index&&n.ignoreMatch()}},e)},BACKSLASH_ESCAPE:h,APOS_STRING_MODE:f,QUOTE_STRING_MODE:p,PHRASAL_WORDS_MODE:b,COMMENT:m,C_LINE_COMMENT_MODE:v,C_BLOCK_COMMENT_MODE:x,HASH_COMMENT_MODE:E,NUMBER_MODE:{className:"number",begin:"\\b\\d+(\\.\\d+)?",relevance:0},C_NUMBER_MODE:{className:"number",begin:g,relevance:0},BINARY_NUMBER_MODE:{className:"number",begin:"\\b(0b[01]+)",relevance:0},CSS_NUMBER_MODE:{className:"number",begin:"\\b\\d+(\\.\\d+)?(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",relevance:0},REGEXP_MODE:{begin:/(?=\/[^/\n]*\/)/,contains:[{className:"regexp",begin:/\//,end:/\/[gimuy]*/,illegal:/\n/,contains:[h,{begin:/\[/,end:/\]/,relevance:0,contains:[h]}]}]},TITLE_MODE:{className:"title",begin:"[a-zA-Z]\\w*",relevance:0},UNDERSCORE_TITLE_MODE:{className:"title",begin:"[a-zA-Z_]\\w*",relevance:0},METHOD_GUARD:{begin:"\\.\\s*[a-zA-Z_]\\w*",relevance:0},END_SAME_AS_BEGIN:function(e){return Object.assign(e,{"on:begin":(e,n)=>{n.data._beginMatch=e[1]},"on:end":(e,n)=>{n.data._beginMatch!==e[1]&&n.ignoreMatch()}})}}),N="of and for in not or if then".split(" ");function w(e,n){return n?+n:function(e){return N.includes(e.toLowerCase())}(e)?0:1}const R=t,y=r,{nodeStream:O,mergeStreams:k}=i,M=Symbol("nomatch");return function(t){var a=[],i=Object.create(null),s=Object.create(null),o=[],l=!0,c=/(^(<[^>]+>|\t|)+|\n)/gm,g="Could not find the language '{}', did you forget to load/include a language module?";const h={disableAutodetect:!0,name:"Plain text",contains:[]};var f={noHighlightRe:/^(no-?highlight)$/i,languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:null,__emitter:u};function p(e){return f.noHighlightRe.test(e)}function b(e,n,t,r){var a={code:n,language:e};S("before:highlight",a);var i=a.result?a.result:m(a.language,a.code,t,r);return i.code=a.code,S("after:highlight",i),i}function m(e,t,a,s){var o=t;function c(e,n){var t=E.case_insensitive?n[0].toLowerCase():n[0];return Object.prototype.hasOwnProperty.call(e.keywords,t)&&e.keywords[t]}function u(){null!=y.subLanguage?function(){if(""!==A){var e=null;if("string"==typeof y.subLanguage){if(!i[y.subLanguage])return void k.addText(A);e=m(y.subLanguage,A,!0,O[y.subLanguage]),O[y.subLanguage]=e.top}else e=v(A,y.subLanguage.length?y.subLanguage:null);y.relevance>0&&(I+=e.relevance),k.addSublanguage(e.emitter,e.language)}}():function(){if(!y.keywords)return void k.addText(A);let e=0;y.keywordPatternRe.lastIndex=0;let n=y.keywordPatternRe.exec(A),t="";for(;n;){t+=A.substring(e,n.index);const r=c(y,n);if(r){const[e,a]=r;k.addText(t),t="",I+=a,k.addKeyword(n[0],e)}else t+=n[0];e=y.keywordPatternRe.lastIndex,n=y.keywordPatternRe.exec(A)}t+=A.substr(e),k.addText(t)}(),A=""}function h(e){return e.className&&k.openNode(e.className),y=Object.create(e,{parent:{value:y}})}function p(e){return 0===y.matcher.regexIndex?(A+=e[0],1):(L=!0,0)}var b={};function x(t,r){var i=r&&r[0];if(A+=t,null==i)return u(),0;if("begin"===b.type&&"end"===r.type&&b.index===r.index&&""===i){if(A+=o.slice(r.index,r.index+1),!l){const n=Error("0 width match regex");throw n.languageName=e,n.badRule=b.rule,n}return 1}if(b=r,"begin"===r.type)return function(e){var t=e[0],r=e.rule;const a=new n(r),i=[r.__beforeBegin,r["on:begin"]];for(const n of i)if(n&&(n(e,a),a.ignore))return p(t);return r&&r.endSameAsBegin&&(r.endRe=RegExp(t.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"),"m")),r.skip?A+=t:(r.excludeBegin&&(A+=t),u(),r.returnBegin||r.excludeBegin||(A=t)),h(r),r.returnBegin?0:t.length}(r);if("illegal"===r.type&&!a){const e=Error('Illegal lexeme "'+i+'" for mode "'+(y.className||"")+'"');throw e.mode=y,e}if("end"===r.type){var s=function(e){var t=e[0],r=o.substr(e.index),a=function e(t,r,a){let i=function(e,n){var t=e&&e.exec(n);return t&&0===t.index}(t.endRe,a);if(i){if(t["on:end"]){const e=new n(t);t["on:end"](r,e),e.ignore&&(i=!1)}if(i){for(;t.endsParent&&t.parent;)t=t.parent;return t}}if(t.endsWithParent)return e(t.parent,r,a)}(y,e,r);if(!a)return M;var i=y;i.skip?A+=t:(i.returnEnd||i.excludeEnd||(A+=t),u(),i.excludeEnd&&(A=t));do{y.className&&k.closeNode(),y.skip||y.subLanguage||(I+=y.relevance),y=y.parent}while(y!==a.parent);return a.starts&&(a.endSameAsBegin&&(a.starts.endRe=a.endRe),h(a.starts)),i.returnEnd?0:t.length}(r);if(s!==M)return s}if("illegal"===r.type&&""===i)return 1;if(B>1e5&&B>3*r.index)throw Error("potential infinite loop, way more iterations than matches");return A+=i,i.length}var E=T(e);if(!E)throw console.error(g.replace("{}",e)),Error('Unknown language: "'+e+'"');var _=function(e){function n(n,t){return RegExp(d(n),"m"+(e.case_insensitive?"i":"")+(t?"g":""))}class t{constructor(){this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0}addRule(e,n){n.position=this.position++,this.matchIndexes[this.matchAt]=n,this.regexes.push([n,e]),this.matchAt+=function(e){return RegExp(e.toString()+"|").exec("").length-1}(e)+1}compile(){0===this.regexes.length&&(this.exec=()=>null);const e=this.regexes.map(e=>e[1]);this.matcherRe=n(function(e,n="|"){for(var t=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./,r=0,a="",i=0;i0&&(a+=n),a+="(";o.length>0;){var l=t.exec(o);if(null==l){a+=o;break}a+=o.substring(0,l.index),o=o.substring(l.index+l[0].length),"\\"===l[0][0]&&l[1]?a+="\\"+(+l[1]+s):(a+=l[0],"("===l[0]&&r++)}a+=")"}return a}(e),!0),this.lastIndex=0}exec(e){this.matcherRe.lastIndex=this.lastIndex;const n=this.matcherRe.exec(e);if(!n)return null;const t=n.findIndex((e,n)=>n>0&&void 0!==e),r=this.matchIndexes[t];return n.splice(0,t),Object.assign(n,r)}}class a{constructor(){this.rules=[],this.multiRegexes=[],this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(e){if(this.multiRegexes[e])return this.multiRegexes[e];const n=new t;return this.rules.slice(e).forEach(([e,t])=>n.addRule(e,t)),n.compile(),this.multiRegexes[e]=n,n}considerAll(){this.regexIndex=0}addRule(e,n){this.rules.push([e,n]),"begin"===n.type&&this.count++}exec(e){const n=this.getMatcher(this.regexIndex);n.lastIndex=this.lastIndex;const t=n.exec(e);return t&&(this.regexIndex+=t.position+1,this.regexIndex===this.count&&(this.regexIndex=0)),t}}function i(e,n){const t=e.input[e.index-1],r=e.input[e.index+e[0].length];"."!==t&&"."!==r||n.ignoreMatch()}if(e.contains&&e.contains.includes("self"))throw Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.");return function t(s,o){const l=s;if(s.compiled)return l;s.compiled=!0,s.__beforeBegin=null,s.keywords=s.keywords||s.beginKeywords;let c=null;if("object"==typeof s.keywords&&(c=s.keywords.$pattern,delete s.keywords.$pattern),s.keywords&&(s.keywords=function(e,n){var t={};return"string"==typeof e?r("keyword",e):Object.keys(e).forEach((function(n){r(n,e[n])})),t;function r(e,r){n&&(r=r.toLowerCase()),r.split(" ").forEach((function(n){var r=n.split("|");t[r[0]]=[e,w(r[0],r[1])]}))}}(s.keywords,e.case_insensitive)),s.lexemes&&c)throw Error("ERR: Prefer `keywords.$pattern` to `mode.lexemes`, BOTH are not allowed. (see mode reference) ");return l.keywordPatternRe=n(s.lexemes||c||/\w+/,!0),o&&(s.beginKeywords&&(s.begin="\\b("+s.beginKeywords.split(" ").join("|")+")(?=\\b|\\s)",s.__beforeBegin=i),s.begin||(s.begin=/\B|\b/),l.beginRe=n(s.begin),s.endSameAsBegin&&(s.end=s.begin),s.end||s.endsWithParent||(s.end=/\B|\b/),s.end&&(l.endRe=n(s.end)),l.terminator_end=d(s.end)||"",s.endsWithParent&&o.terminator_end&&(l.terminator_end+=(s.end?"|":"")+o.terminator_end)),s.illegal&&(l.illegalRe=n(s.illegal)),void 0===s.relevance&&(s.relevance=1),s.contains||(s.contains=[]),s.contains=[].concat(...s.contains.map((function(e){return function(e){return e.variants&&!e.cached_variants&&(e.cached_variants=e.variants.map((function(n){return r(e,{variants:null},n)}))),e.cached_variants?e.cached_variants:function e(n){return!!n&&(n.endsWithParent||e(n.starts))}(e)?r(e,{starts:e.starts?r(e.starts):null}):Object.isFrozen(e)?r(e):e}("self"===e?s:e)}))),s.contains.forEach((function(e){t(e,l)})),s.starts&&t(s.starts,o),l.matcher=function(e){const n=new a;return e.contains.forEach(e=>n.addRule(e.begin,{rule:e,type:"begin"})),e.terminator_end&&n.addRule(e.terminator_end,{type:"end"}),e.illegal&&n.addRule(e.illegal,{type:"illegal"}),n}(l),l}(e)}(E),N="",y=s||_,O={},k=new f.__emitter(f);!function(){for(var e=[],n=y;n!==E;n=n.parent)n.className&&e.unshift(n.className);e.forEach(e=>k.openNode(e))}();var A="",I=0,S=0,B=0,L=!1;try{for(y.matcher.considerAll();;){B++,L?L=!1:(y.matcher.lastIndex=S,y.matcher.considerAll());const e=y.matcher.exec(o);if(!e)break;const n=x(o.substring(S,e.index),e);S=e.index+n}return x(o.substr(S)),k.closeAllNodes(),k.finalize(),N=k.toHTML(),{relevance:I,value:N,language:e,illegal:!1,emitter:k,top:y}}catch(n){if(n.message&&n.message.includes("Illegal"))return{illegal:!0,illegalBy:{msg:n.message,context:o.slice(S-100,S+100),mode:n.mode},sofar:N,relevance:0,value:R(o),emitter:k};if(l)return{illegal:!1,relevance:0,value:R(o),emitter:k,language:e,top:y,errorRaised:n};throw n}}function v(e,n){n=n||f.languages||Object.keys(i);var t=function(e){const n={relevance:0,emitter:new f.__emitter(f),value:R(e),illegal:!1,top:h};return n.emitter.addText(e),n}(e),r=t;return n.filter(T).filter(I).forEach((function(n){var a=m(n,e,!1);a.language=n,a.relevance>r.relevance&&(r=a),a.relevance>t.relevance&&(r=t,t=a)})),r.language&&(t.second_best=r),t}function x(e){return f.tabReplace||f.useBR?e.replace(c,e=>"\n"===e?f.useBR?"
":e:f.tabReplace?e.replace(/\t/g,f.tabReplace):e):e}function E(e){let n=null;const t=function(e){var n=e.className+" ";n+=e.parentNode?e.parentNode.className:"";const t=f.languageDetectRe.exec(n);if(t){var r=T(t[1]);return r||(console.warn(g.replace("{}",t[1])),console.warn("Falling back to no-highlight mode for this block.",e)),r?t[1]:"no-highlight"}return n.split(/\s+/).find(e=>p(e)||T(e))}(e);if(p(t))return;S("before:highlightBlock",{block:e,language:t}),f.useBR?(n=document.createElement("div")).innerHTML=e.innerHTML.replace(/\n/g,"").replace(//g,"\n"):n=e;const r=n.textContent,a=t?b(t,r,!0):v(r),i=O(n);if(i.length){const e=document.createElement("div");e.innerHTML=a.value,a.value=k(i,O(e),r)}a.value=x(a.value),S("after:highlightBlock",{block:e,result:a}),e.innerHTML=a.value,e.className=function(e,n,t){var r=n?s[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),e.includes(r)||a.push(r),a.join(" ").trim()}(e.className,t,a.language),e.result={language:a.language,re:a.relevance,relavance:a.relevance},a.second_best&&(e.second_best={language:a.second_best.language,re:a.second_best.relevance,relavance:a.second_best.relevance})}const N=()=>{if(!N.called){N.called=!0;var e=document.querySelectorAll("pre code");a.forEach.call(e,E)}};function T(e){return e=(e||"").toLowerCase(),i[e]||i[s[e]]}function A(e,{languageName:n}){"string"==typeof e&&(e=[e]),e.forEach(e=>{s[e]=n})}function I(e){var n=T(e);return n&&!n.disableAutodetect}function S(e,n){var t=e;o.forEach((function(e){e[t]&&e[t](n)}))}Object.assign(t,{highlight:b,highlightAuto:v,fixMarkup:x,highlightBlock:E,configure:function(e){f=y(f,e)},initHighlighting:N,initHighlightingOnLoad:function(){window.addEventListener("DOMContentLoaded",N,!1)},registerLanguage:function(e,n){var r=null;try{r=n(t)}catch(n){if(console.error("Language definition for '{}' could not be registered.".replace("{}",e)),!l)throw n;console.error(n),r=h}r.name||(r.name=e),i[e]=r,r.rawDefinition=n.bind(null,t),r.aliases&&A(r.aliases,{languageName:e})},listLanguages:function(){return Object.keys(i)},getLanguage:T,registerAliases:A,requireLanguage:function(e){var n=T(e);if(n)return n;throw Error("The '{}' language is required, but not loaded.".replace("{}",e))},autoDetection:I,inherit:y,addPlugin:function(e){o.push(e)}}),t.debugMode=function(){l=!1},t.safeMode=function(){l=!0},t.versionString="10.1.2";for(const n in _)"object"==typeof _[n]&&e(_[n]);return Object.assign(t,_),t}({})}();"object"==typeof exports&&"undefined"!=typeof module&&(module.exports=hljs);hljs.registerLanguage("xml",function(){"use strict";return function(e){var n={className:"symbol",begin:"&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;"},a={begin:"\\s",contains:[{className:"meta-keyword",begin:"#?[a-z_][a-z1-9_-]+",illegal:"\\n"}]},s=e.inherit(a,{begin:"\\(",end:"\\)"}),t=e.inherit(e.APOS_STRING_MODE,{className:"meta-string"}),i=e.inherit(e.QUOTE_STRING_MODE,{className:"meta-string"}),c={endsWithParent:!0,illegal:/`]+/}]}]}]};return{name:"HTML, XML",aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist","wsf","svg"],case_insensitive:!0,contains:[{className:"meta",begin:"",relevance:10,contains:[a,i,t,s,{begin:"\\[",end:"\\]",contains:[{className:"meta",begin:"",contains:[a,s,i,t]}]}]},e.COMMENT("\x3c!--","--\x3e",{relevance:10}),{begin:"<\\!\\[CDATA\\[",end:"\\]\\]>",relevance:10},n,{className:"meta",begin:/<\?xml/,end:/\?>/,relevance:10},{className:"tag",begin:")",end:">",keywords:{name:"style"},contains:[c],starts:{end:"",returnEnd:!0,subLanguage:["css","xml"]}},{className:"tag",begin:")",end:">",keywords:{name:"script"},contains:[c],starts:{end:"<\/script>",returnEnd:!0,subLanguage:["javascript","handlebars","xml"]}},{className:"tag",begin:"",contains:[{className:"name",begin:/[^\/><\s]+/,relevance:0},c]}]}}}());hljs.registerLanguage("markdown",function(){"use strict";return function(n){const e={begin:"<",end:">",subLanguage:"xml",relevance:0},a={begin:"\\[.+?\\][\\(\\[].*?[\\)\\]]",returnBegin:!0,contains:[{className:"string",begin:"\\[",end:"\\]",excludeBegin:!0,returnEnd:!0,relevance:0},{className:"link",begin:"\\]\\(",end:"\\)",excludeBegin:!0,excludeEnd:!0},{className:"symbol",begin:"\\]\\[",end:"\\]",excludeBegin:!0,excludeEnd:!0}],relevance:10},i={className:"strong",contains:[],variants:[{begin:/_{2}/,end:/_{2}/},{begin:/\*{2}/,end:/\*{2}/}]},s={className:"emphasis",contains:[],variants:[{begin:/\*(?!\*)/,end:/\*/},{begin:/_(?!_)/,end:/_/,relevance:0}]};i.contains.push(s),s.contains.push(i);var c=[e,a];return i.contains=i.contains.concat(c),s.contains=s.contains.concat(c),{name:"Markdown",aliases:["md","mkdown","mkd"],contains:[{className:"section",variants:[{begin:"^#{1,6}",end:"$",contains:c=c.concat(i,s)},{begin:"(?=^.+?\\n[=-]{2,}$)",contains:[{begin:"^[=-]*$"},{begin:"^",end:"\\n",contains:c}]}]},e,{className:"bullet",begin:"^[ \t]*([*+-]|(\\d+\\.))(?=\\s+)",end:"\\s+",excludeEnd:!0},i,s,{className:"quote",begin:"^>\\s+",contains:c,end:"$"},{className:"code",variants:[{begin:"(`{3,})(.|\\n)*?\\1`*[ ]*"},{begin:"(~{3,})(.|\\n)*?\\1~*[ ]*"},{begin:"```",end:"```+[ ]*$"},{begin:"~~~",end:"~~~+[ ]*$"},{begin:"`.+?`"},{begin:"(?=^( {4}|\\t))",contains:[{begin:"^( {4}|\\t)",end:"(\\n)$"}],relevance:0}]},{begin:"^[-\\*]{3,}",end:"$"},a,{begin:/^\[[^\n]+\]:/,returnBegin:!0,contains:[{className:"symbol",begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0},{className:"link",begin:/:\s*/,end:/$/,excludeBegin:!0}]}]}}}());hljs.registerLanguage("perl",function(){"use strict";return function(e){var n={$pattern:/[\w.]+/,keyword:"getpwent getservent quotemeta msgrcv scalar kill dbmclose undef lc ma syswrite tr send umask sysopen shmwrite vec qx utime local oct semctl localtime readpipe do return format read sprintf dbmopen pop getpgrp not getpwnam rewinddir qq fileno qw endprotoent wait sethostent bless s|0 opendir continue each sleep endgrent shutdown dump chomp connect getsockname die socketpair close flock exists index shmget sub for endpwent redo lstat msgctl setpgrp abs exit select print ref gethostbyaddr unshift fcntl syscall goto getnetbyaddr join gmtime symlink semget splice x|0 getpeername recv log setsockopt cos last reverse gethostbyname getgrnam study formline endhostent times chop length gethostent getnetent pack getprotoent getservbyname rand mkdir pos chmod y|0 substr endnetent printf next open msgsnd readdir use unlink getsockopt getpriority rindex wantarray hex system getservbyport endservent int chr untie rmdir prototype tell listen fork shmread ucfirst setprotoent else sysseek link getgrgid shmctl waitpid unpack getnetbyname reset chdir grep split require caller lcfirst until warn while values shift telldir getpwuid my getprotobynumber delete and sort uc defined srand accept package seekdir getprotobyname semop our rename seek if q|0 chroot sysread setpwent no crypt getc chown sqrt write setnetent setpriority foreach tie sin msgget map stat getlogin unless elsif truncate exec keys glob tied closedir ioctl socket readlink eval xor readline binmode setservent eof ord bind alarm pipe atan2 getgrent exp time push setgrent gt lt or ne m|0 break given say state when"},t={className:"subst",begin:"[$@]\\{",end:"\\}",keywords:n},s={begin:"->{",end:"}"},r={variants:[{begin:/\$\d/},{begin:/[\$%@](\^\w\b|#\w+(::\w+)*|{\w+}|\w+(::\w*)*)/},{begin:/[\$%@][^\s\w{]/,relevance:0}]},i=[e.BACKSLASH_ESCAPE,t,r],a=[r,e.HASH_COMMENT_MODE,e.COMMENT("^\\=\\w","\\=cut",{endsWithParent:!0}),s,{className:"string",contains:i,variants:[{begin:"q[qwxr]?\\s*\\(",end:"\\)",relevance:5},{begin:"q[qwxr]?\\s*\\[",end:"\\]",relevance:5},{begin:"q[qwxr]?\\s*\\{",end:"\\}",relevance:5},{begin:"q[qwxr]?\\s*\\|",end:"\\|",relevance:5},{begin:"q[qwxr]?\\s*\\<",end:"\\>",relevance:5},{begin:"qw\\s+q",end:"q",relevance:5},{begin:"'",end:"'",contains:[e.BACKSLASH_ESCAPE]},{begin:'"',end:'"'},{begin:"`",end:"`",contains:[e.BACKSLASH_ESCAPE]},{begin:"{\\w+}",contains:[],relevance:0},{begin:"-?\\w+\\s*\\=\\>",contains:[],relevance:0}]},{className:"number",begin:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",relevance:0},{begin:"(\\/\\/|"+e.RE_STARTERS_RE+"|\\b(split|return|print|reverse|grep)\\b)\\s*",keywords:"split return print reverse grep",relevance:0,contains:[e.HASH_COMMENT_MODE,{className:"regexp",begin:"(s|tr|y)/(\\\\.|[^/])*/(\\\\.|[^/])*/[a-z]*",relevance:10},{className:"regexp",begin:"(m|qr)?/",end:"/[a-z]*",contains:[e.BACKSLASH_ESCAPE],relevance:0}]},{className:"function",beginKeywords:"sub",end:"(\\s*\\(.*?\\))?[;{]",excludeEnd:!0,relevance:5,contains:[e.TITLE_MODE]},{begin:"-\\w\\b",relevance:0},{begin:"^__DATA__$",end:"^__END__$",subLanguage:"mojolicious",contains:[{begin:"^@@.*",end:"$",className:"comment"}]}];return t.contains=a,s.contains=a,{name:"Perl",aliases:["pl","pm"],keywords:n,contains:a}}}());hljs.registerLanguage("plaintext",function(){"use strict";return function(t){return{name:"Plain text",aliases:["text","txt"],disableAutodetect:!0}}}());hljs.registerLanguage("ini",function(){"use strict";function e(e){return e?"string"==typeof e?e:e.source:null}function n(...n){return n.map(n=>e(n)).join("")}return function(a){var s={className:"number",relevance:0,variants:[{begin:/([\+\-]+)?[\d]+_[\d_]+/},{begin:a.NUMBER_RE}]},i=a.COMMENT();i.variants=[{begin:/;/,end:/$/},{begin:/#/,end:/$/}];var t={className:"variable",variants:[{begin:/\$[\w\d"][\w\d_]*/},{begin:/\$\{(.*?)}/}]},r={className:"literal",begin:/\bon|off|true|false|yes|no\b/},l={className:"string",contains:[a.BACKSLASH_ESCAPE],variants:[{begin:"'''",end:"'''",relevance:10},{begin:'"""',end:'"""',relevance:10},{begin:'"',end:'"'},{begin:"'",end:"'"}]},c={begin:/\[/,end:/\]/,contains:[i,r,t,l,s,"self"],relevance:0},g="("+[/[A-Za-z0-9_-]+/,/"(\\"|[^"])*"/,/'[^']*'/].map(n=>e(n)).join("|")+")";return{name:"TOML, also INI",aliases:["toml"],case_insensitive:!0,illegal:/\S/,contains:[i,{className:"section",begin:/\[+/,end:/\]+/},{begin:n(g,"(\\s*\\.\\s*",g,")*",n("(?=",/\s*=\s*[^#\s]/,")")),className:"attr",starts:{end:/$/,contains:[i,c,r,t,l,s]}}]}}}());hljs.registerLanguage("json",function(){"use strict";return function(n){var e={literal:"true false null"},i=[n.C_LINE_COMMENT_MODE,n.C_BLOCK_COMMENT_MODE],t=[n.QUOTE_STRING_MODE,n.C_NUMBER_MODE],a={end:",",endsWithParent:!0,excludeEnd:!0,contains:t,keywords:e},l={begin:"{",end:"}",contains:[{className:"attr",begin:/"/,end:/"/,contains:[n.BACKSLASH_ESCAPE],illegal:"\\n"},n.inherit(a,{begin:/:/})].concat(i),illegal:"\\S"},s={begin:"\\[",end:"\\]",contains:[n.inherit(a)],illegal:"\\S"};return t.push(l,s),i.forEach((function(n){t.push(n)})),{name:"JSON",contains:t,keywords:e,illegal:"\\S"}}}());hljs.registerLanguage("ruby",function(){"use strict";return function(e){var n="[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?",a={keyword:"and then defined module in return redo if BEGIN retry end for self when next until do begin unless END rescue else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor",literal:"true false nil"},s={className:"doctag",begin:"@[A-Za-z]+"},i={begin:"#<",end:">"},r=[e.COMMENT("#","$",{contains:[s]}),e.COMMENT("^\\=begin","^\\=end",{contains:[s],relevance:10}),e.COMMENT("^__END__","\\n$")],c={className:"subst",begin:"#\\{",end:"}",keywords:a},t={className:"string",contains:[e.BACKSLASH_ESCAPE,c],variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/`/,end:/`/},{begin:"%[qQwWx]?\\(",end:"\\)"},{begin:"%[qQwWx]?\\[",end:"\\]"},{begin:"%[qQwWx]?{",end:"}"},{begin:"%[qQwWx]?<",end:">"},{begin:"%[qQwWx]?/",end:"/"},{begin:"%[qQwWx]?%",end:"%"},{begin:"%[qQwWx]?-",end:"-"},{begin:"%[qQwWx]?\\|",end:"\\|"},{begin:/\B\?(\\\d{1,3}|\\x[A-Fa-f0-9]{1,2}|\\u[A-Fa-f0-9]{4}|\\?\S)\b/},{begin:/<<[-~]?'?(\w+)(?:.|\n)*?\n\s*\1\b/,returnBegin:!0,contains:[{begin:/<<[-~]?'?/},e.END_SAME_AS_BEGIN({begin:/(\w+)/,end:/(\w+)/,contains:[e.BACKSLASH_ESCAPE,c]})]}]},b={className:"params",begin:"\\(",end:"\\)",endsParent:!0,keywords:a},d=[t,i,{className:"class",beginKeywords:"class module",end:"$|;",illegal:/=/,contains:[e.inherit(e.TITLE_MODE,{begin:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?"}),{begin:"<\\s*",contains:[{begin:"("+e.IDENT_RE+"::)?"+e.IDENT_RE}]}].concat(r)},{className:"function",beginKeywords:"def",end:"$|;",contains:[e.inherit(e.TITLE_MODE,{begin:n}),b].concat(r)},{begin:e.IDENT_RE+"::"},{className:"symbol",begin:e.UNDERSCORE_IDENT_RE+"(\\!|\\?)?:",relevance:0},{className:"symbol",begin:":(?!\\s)",contains:[t,{begin:n}],relevance:0},{className:"number",begin:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",relevance:0},{begin:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},{className:"params",begin:/\|/,end:/\|/,keywords:a},{begin:"("+e.RE_STARTERS_RE+"|unless)\\s*",keywords:"unless",contains:[i,{className:"regexp",contains:[e.BACKSLASH_ESCAPE,c],illegal:/\n/,variants:[{begin:"/",end:"/[a-z]*"},{begin:"%r{",end:"}[a-z]*"},{begin:"%r\\(",end:"\\)[a-z]*"},{begin:"%r!",end:"![a-z]*"},{begin:"%r\\[",end:"\\][a-z]*"}]}].concat(r),relevance:0}].concat(r);c.contains=d,b.contains=d;var g=[{begin:/^\s*=>/,starts:{end:"$",contains:d}},{className:"meta",begin:"^([>?]>|[\\w#]+\\(\\w+\\):\\d+:\\d+>|(\\w+-)?\\d+\\.\\d+\\.\\d(p\\d+)?[^>]+>)",starts:{end:"$",contains:d}}];return{name:"Ruby",aliases:["rb","gemspec","podspec","thor","irb"],keywords:a,illegal:/\/\*/,contains:r.concat(g).concat(d)}}}());hljs.registerLanguage("yaml",function(){"use strict";return function(e){var n="true false yes no null",a="[\\w#;/?:@&=+$,.~*\\'()[\\]]+",s={className:"string",relevance:0,variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/\S+/}],contains:[e.BACKSLASH_ESCAPE,{className:"template-variable",variants:[{begin:"{{",end:"}}"},{begin:"%{",end:"}"}]}]},i=e.inherit(s,{variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/[^\s,{}[\]]+/}]}),l={end:",",endsWithParent:!0,excludeEnd:!0,contains:[],keywords:n,relevance:0},t={begin:"{",end:"}",contains:[l],illegal:"\\n",relevance:0},g={begin:"\\[",end:"\\]",contains:[l],illegal:"\\n",relevance:0},b=[{className:"attr",variants:[{begin:"\\w[\\w :\\/.-]*:(?=[ \t]|$)"},{begin:'"\\w[\\w :\\/.-]*":(?=[ \t]|$)'},{begin:"'\\w[\\w :\\/.-]*':(?=[ \t]|$)"}]},{className:"meta",begin:"^---s*$",relevance:10},{className:"string",begin:"[\\|>]([0-9]?[+-])?[ ]*\\n( *)[\\S ]+\\n(\\2[\\S ]+\\n?)*"},{begin:"<%[%=-]?",end:"[%-]?%>",subLanguage:"ruby",excludeBegin:!0,excludeEnd:!0,relevance:0},{className:"type",begin:"!\\w+!"+a},{className:"type",begin:"!<"+a+">"},{className:"type",begin:"!"+a},{className:"type",begin:"!!"+a},{className:"meta",begin:"&"+e.UNDERSCORE_IDENT_RE+"$"},{className:"meta",begin:"\\*"+e.UNDERSCORE_IDENT_RE+"$"},{className:"bullet",begin:"\\-(?=[ ]|$)",relevance:0},e.HASH_COMMENT_MODE,{beginKeywords:n,keywords:{literal:n}},{className:"number",begin:"\\b[0-9]{4}(-[0-9][0-9]){0,2}([Tt \\t][0-9][0-9]?(:[0-9][0-9]){2})?(\\.[0-9]*)?([ \\t])*(Z|[-+][0-9][0-9]?(:[0-9][0-9])?)?\\b"},{className:"number",begin:e.C_NUMBER_RE+"\\b"},t,g,s],c=[...b];return c.pop(),c.push(i),l.contains=c,{name:"YAML",case_insensitive:!0,aliases:["yml","YAML"],contains:b}}}());hljs.registerLanguage("haskell",function(){"use strict";return function(e){var n={variants:[e.COMMENT("--","$"),e.COMMENT("{-","-}",{contains:["self"]})]},i={className:"meta",begin:"{-#",end:"#-}"},a={className:"meta",begin:"^#",end:"$"},s={className:"type",begin:"\\b[A-Z][\\w']*",relevance:0},l={begin:"\\(",end:"\\)",illegal:'"',contains:[i,a,{className:"type",begin:"\\b[A-Z][\\w]*(\\((\\.\\.|,|\\w+)\\))?"},e.inherit(e.TITLE_MODE,{begin:"[_a-z][\\w']*"}),n]};return{name:"Haskell",aliases:["hs"],keywords:"let in if then else case of where do module import hiding qualified type data newtype deriving class instance as default infix infixl infixr foreign export ccall stdcall cplusplus jvm dotnet safe unsafe family forall mdo proc rec",contains:[{beginKeywords:"module",end:"where",keywords:"module where",contains:[l,n],illegal:"\\W\\.|;"},{begin:"\\bimport\\b",end:"$",keywords:"import qualified as hiding",contains:[l,n],illegal:"\\W\\.|;"},{className:"class",begin:"^(\\s*)?(class|instance)\\b",end:"where",keywords:"class family instance where",contains:[s,l,n]},{className:"class",begin:"\\b(data|(new)?type)\\b",end:"$",keywords:"data family type newtype deriving",contains:[i,s,l,{begin:"{",end:"}",contains:l.contains},n]},{beginKeywords:"default",end:"$",contains:[s,l,n]},{beginKeywords:"infix infixl infixr",end:"$",contains:[e.C_NUMBER_MODE,n]},{begin:"\\bforeign\\b",end:"$",keywords:"foreign import export ccall stdcall cplusplus jvm dotnet safe unsafe",contains:[s,e.QUOTE_STRING_MODE,n]},{className:"meta",begin:"#!\\/usr\\/bin\\/env runhaskell",end:"$"},i,a,e.QUOTE_STRING_MODE,e.C_NUMBER_MODE,s,e.inherit(e.TITLE_MODE,{begin:"^[_a-z][\\w']*"}),n,{begin:"->|<-"}]}}}());hljs.registerLanguage("nix",function(){"use strict";return function(e){var n={keyword:"rec with let in inherit assert if else then",literal:"true false or and null",built_in:"import abort baseNameOf dirOf isNull builtins map removeAttrs throw toString derivation"},i={className:"subst",begin:/\$\{/,end:/}/,keywords:n},t={className:"string",contains:[i],variants:[{begin:"''",end:"''"},{begin:'"',end:'"'}]},s=[e.NUMBER_MODE,e.HASH_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,t,{begin:/[a-zA-Z0-9-_]+(\s*=)/,returnBegin:!0,relevance:0,contains:[{className:"attr",begin:/\S+/}]}];return i.contains=s,{name:"Nix",aliases:["nixos"],keywords:n,contains:s}}}());hljs.registerLanguage("bash",function(){"use strict";return function(e){const s={};Object.assign(s,{className:"variable",variants:[{begin:/\$[\w\d#@][\w\d_]*/},{begin:/\$\{/,end:/\}/,contains:[{begin:/:-/,contains:[s]}]}]});const t={className:"subst",begin:/\$\(/,end:/\)/,contains:[e.BACKSLASH_ESCAPE]},n={className:"string",begin:/"/,end:/"/,contains:[e.BACKSLASH_ESCAPE,s,t]};t.contains.push(n);const a={begin:/\$\(\(/,end:/\)\)/,contains:[{begin:/\d+#[0-9a-f]+/,className:"number"},e.NUMBER_MODE,s]},i=e.SHEBANG({binary:"(fish|bash|zsh|sh|csh|ksh|tcsh|dash|scsh)",relevance:10}),c={className:"function",begin:/\w[\w\d_]*\s*\(\s*\)\s*\{/,returnBegin:!0,contains:[e.inherit(e.TITLE_MODE,{begin:/\w[\w\d_]*/})],relevance:0};return{name:"Bash",aliases:["sh","zsh"],keywords:{$pattern:/\b-?[a-z\._]+\b/,keyword:"if then else elif fi for while in do done case esac function",literal:"true false",built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp",_:"-ne -eq -lt -gt -f -d -e -s -l -a"},contains:[i,e.SHEBANG(),c,a,e.HASH_COMMENT_MODE,n,{className:"",begin:/\\"/},{className:"string",begin:/'/,end:/'/},s]}}}());hljs.registerLanguage("shell",function(){"use strict";return function(s){return{name:"Shell Session",aliases:["console"],contains:[{className:"meta",begin:"^\\s{0,3}[/\\w\\d\\[\\]()@-]*[>%$#]",starts:{end:"$",subLanguage:"bash"}}]}}}());hljs.registerLanguage("python",function(){"use strict";return function(e){var n={keyword:"and elif is global as in if from raise for except finally print import pass return exec else break not with class assert yield try while continue del or def lambda async await nonlocal|10",built_in:"Ellipsis NotImplemented",literal:"False None True"},a={className:"meta",begin:/^(>>>|\.\.\.) /},i={className:"subst",begin:/\{/,end:/\}/,keywords:n,illegal:/#/},s={begin:/\{\{/,relevance:0},r={className:"string",contains:[e.BACKSLASH_ESCAPE],variants:[{begin:/(u|b)?r?'''/,end:/'''/,contains:[e.BACKSLASH_ESCAPE,a],relevance:10},{begin:/(u|b)?r?"""/,end:/"""/,contains:[e.BACKSLASH_ESCAPE,a],relevance:10},{begin:/(fr|rf|f)'''/,end:/'''/,contains:[e.BACKSLASH_ESCAPE,a,s,i]},{begin:/(fr|rf|f)"""/,end:/"""/,contains:[e.BACKSLASH_ESCAPE,a,s,i]},{begin:/(u|r|ur)'/,end:/'/,relevance:10},{begin:/(u|r|ur)"/,end:/"/,relevance:10},{begin:/(b|br)'/,end:/'/},{begin:/(b|br)"/,end:/"/},{begin:/(fr|rf|f)'/,end:/'/,contains:[e.BACKSLASH_ESCAPE,s,i]},{begin:/(fr|rf|f)"/,end:/"/,contains:[e.BACKSLASH_ESCAPE,s,i]},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},l={className:"number",relevance:0,variants:[{begin:e.BINARY_NUMBER_RE+"[lLjJ]?"},{begin:"\\b(0o[0-7]+)[lLjJ]?"},{begin:e.C_NUMBER_RE+"[lLjJ]?"}]},t={className:"params",variants:[{begin:/\(\s*\)/,skip:!0,className:null},{begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,contains:["self",a,l,r,e.HASH_COMMENT_MODE]}]};return i.contains=[r,l,a],{name:"Python",aliases:["py","gyp","ipython"],keywords:n,illegal:/(<\/|->|\?)|=>/,contains:[a,l,{beginKeywords:"if",relevance:0},r,e.HASH_COMMENT_MODE,{variants:[{className:"function",beginKeywords:"def"},{className:"class",beginKeywords:"class"}],end:/:/,illegal:/[${=;\n,]/,contains:[e.UNDERSCORE_TITLE_MODE,t,{begin:/->/,endsWithParent:!0,keywords:"None"}]},{className:"meta",begin:/^[\t ]*@/,end:/$/},{begin:/\b(print|exec)\(/}]}}}()); diff --git a/examples/devos/flake.lock b/examples/devos/flake.lock new file mode 100644 index 000000000..5d7d11d52 --- /dev/null +++ b/examples/devos/flake.lock @@ -0,0 +1,558 @@ +{ + "nodes": { + "agenix": { + "inputs": { + "nixpkgs": [ + "nixos" + ] + }, + "locked": { + "lastModified": 1637793790, + "narHash": "sha256-oPXavjxETEWGXq8g7kQHyRLKUmLX2yPtGn+t3V0mrTY=", + "owner": "ryantm", + "repo": "agenix", + "rev": "f85eea0e29fa9a8924571d0e398215e175f80d55", + "type": "github" + }, + "original": { + "owner": "ryantm", + "repo": "agenix", + "type": "github" + } + }, + "beautysh": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", + "poetry2nix": "poetry2nix" + }, + "locked": { + "lastModified": 1630693543, + "narHash": "sha256-7Sly3ReaJZw60Qo0rpfN4jF6zy94nwQz6ENgUUFzJfg=", + "owner": "lovesegfault", + "repo": "beautysh", + "rev": "5609593961b70428f58d5c1b4b25cdda43b0d0bd", + "type": "github" + }, + "original": { + "owner": "lovesegfault", + "repo": "beautysh", + "type": "github" + } + }, + "blank": { + "locked": { + "lastModified": 1625557891, + "narHash": "sha256-O8/MWsPBGhhyPoPLHZAuoZiiHo9q6FLlEeIDEXuj6T4=", + "owner": "divnix", + "repo": "blank", + "rev": "5a5d2684073d9f563072ed07c871d577a6c614a8", + "type": "github" + }, + "original": { + "owner": "divnix", + "repo": "blank", + "type": "github" + } + }, + "bud": { + "inputs": { + "beautysh": "beautysh", + "devshell": [ + "digga", + "devshell" + ], + "nixpkgs": [ + "nixos" + ] + }, + "locked": { + "lastModified": 1640836100, + "narHash": "sha256-My9Lay6BCDwAZgrL4SuVXHkYPHIU7ypnuiS/pd7eg1M=", + "owner": "divnix", + "repo": "bud", + "rev": "b1d8ab3970f4dfb5fb90d7d8a9ab493c75d031fc", + "type": "github" + }, + "original": { + "owner": "divnix", + "repo": "bud", + "type": "github" + } + }, + "darwin": { + "inputs": { + "nixpkgs": [ + "nixos" + ] + }, + "locked": { + "lastModified": 1634994402, + "narHash": "sha256-xmlCVVOYGpZoxgOqsDOVF0B0ASrnbNGVAEzID9qh2xo=", + "owner": "LnL7", + "repo": "nix-darwin", + "rev": "44da835ac40dab5fd231298b59d83487382d2fab", + "type": "github" + }, + "original": { + "owner": "LnL7", + "repo": "nix-darwin", + "type": "github" + } + }, + "deploy": { + "inputs": { + "flake-compat": "flake-compat", + "nixpkgs": [ + "nixos" + ], + "utils": "utils" + }, + "locked": { + "lastModified": 1643787431, + "narHash": "sha256-8IwuVgXulRE3ZWq6z8mytarawC32pKPKR20EyDtSH+w=", + "owner": "serokell", + "repo": "deploy-rs", + "rev": "4154ba1aaaf7333a916384c348d867d03b6f1409", + "type": "github" + }, + "original": { + "owner": "serokell", + "repo": "deploy-rs", + "type": "github" + } + }, + "devshell": { + "locked": { + "lastModified": 1637575296, + "narHash": "sha256-ZY8YR5u8aglZPe27+AJMnPTG6645WuavB+w0xmhTarw=", + "owner": "numtide", + "repo": "devshell", + "rev": "0e56ef21ba1a717169953122c7415fa6a8cd2618", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "devshell", + "type": "github" + } + }, + "digga": { + "inputs": { + "blank": "blank", + "deploy": [ + "deploy" + ], + "devshell": "devshell", + "flake-utils-plus": "flake-utils-plus", + "home-manager": [ + "home" + ], + "latest": "latest", + "nixlib": [ + "nixos" + ], + "nixos-generators": "nixos-generators", + "nixpkgs": [ + "nixos" + ] + }, + "locked": { + "lastModified": 1643510242, + "narHash": "sha256-9C9DyJhQ5bevk0CEEjGct+U9EqUgHg8T70nxz47zjMI=", + "owner": "divnix", + "repo": "digga", + "rev": "33bfb05b8a148d8ad6a842de74e22209bf9fe5d7", + "type": "github" + }, + "original": { + "owner": "divnix", + "repo": "digga", + "type": "github" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1627913399, + "narHash": "sha256-hY8g6H2KFL8ownSiFeMOjwPC8P0ueXpCVEbxgda3pko=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "12c64ca55c1014cdc1b16ed5a804aa8576601ff2", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_2": { + "flake": false, + "locked": { + "lastModified": 1627913399, + "narHash": "sha256-hY8g6H2KFL8ownSiFeMOjwPC8P0ueXpCVEbxgda3pko=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "12c64ca55c1014cdc1b16ed5a804aa8576601ff2", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-utils": { + "locked": { + "lastModified": 1623875721, + "narHash": "sha256-A8BU7bjS5GirpAUv4QA+QnJ4CceLHkcXdRp4xITDB0s=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "f7e004a55b120c02ecb6219596820fcd32ca8772", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils-plus": { + "inputs": { + "flake-utils": "flake-utils_3" + }, + "locked": { + "lastModified": 1639385028, + "narHash": "sha256-oqorKz3mwf7UuDJwlbCEYCB2LfcWLL0DkeCWhRIL820=", + "owner": "gytis-ivaskevicius", + "repo": "flake-utils-plus", + "rev": "be1be083af014720c14f3b574f57b6173b4915d0", + "type": "github" + }, + "original": { + "owner": "gytis-ivaskevicius", + "repo": "flake-utils-plus", + "type": "github" + } + }, + "flake-utils_2": { + "locked": { + "lastModified": 1642700792, + "narHash": "sha256-XqHrk7hFb+zBvRg6Ghl+AZDq03ov6OshJLiSWOoX5es=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "846b2ae0fc4cc943637d3d1def4454213e203cba", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_3": { + "locked": { + "lastModified": 1638122382, + "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_4": { + "locked": { + "lastModified": 1631561581, + "narHash": "sha256-3VQMV5zvxaVLvqqUrNz3iJelLw30mIVSfZmAaauM3dA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "7e5bf3925f6fbdfaf50a2a7ca0be2879c4261d19", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "home": { + "inputs": { + "nixpkgs": [ + "nixos" + ] + }, + "locked": { + "lastModified": 1642653493, + "narHash": "sha256-22mGPjiHUo2Jmze4IjXCJLjeK2mbvvCztHmUyUMr4yw=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "28b9ae40c45c5e7711c353fee1b7af734e293979", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "release-21.11", + "repo": "home-manager", + "type": "github" + } + }, + "latest": { + "locked": { + "lastModified": 1638198142, + "narHash": "sha256-plU9b8r4St6q4U7VHtG9V7oF8k9fIpfXl/KDaZLuY9k=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "8a308775674e178495767df90c419425474582a1", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "latest_2": { + "locked": { + "lastModified": 1643347846, + "narHash": "sha256-O0tyXF//ppRpe9yT1Uu5n34yI2MWDyY6ZiJ4Qn5zIkE=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "5bb20f9dc70e9ee16e21cc404b6508654931ce41", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "naersk": { + "inputs": { + "nixpkgs": [ + "nixos" + ] + }, + "locked": { + "lastModified": 1638203339, + "narHash": "sha256-Sz3iCvbWrVWOD/XfYQeRJgP/7MVYL3/VKsNXvDeWBFc=", + "owner": "nmattia", + "repo": "naersk", + "rev": "c3e56b8a4ffb6d906cdfcfee034581f9a8ece571", + "type": "github" + }, + "original": { + "owner": "nmattia", + "repo": "naersk", + "type": "github" + } + }, + "nixlib": { + "locked": { + "lastModified": 1641688481, + "narHash": "sha256-6L+EU12xLDHby7y8elgFtRKVBxix+7qV8DhVgXqrKZo=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "f697717b3d3a074ffc16c8c8227504f0db292886", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "nixos": { + "locked": { + "lastModified": 1643463207, + "narHash": "sha256-W0azAxucUq84BvWqDPt3gX8kyc8wYvGUynZV9COfByQ=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "03098169624f487eef37186b3214c40e6b6e919d", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "release-21.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixos-generators": { + "inputs": { + "nixlib": "nixlib", + "nixpkgs": "nixpkgs_3" + }, + "locked": { + "lastModified": 1637655461, + "narHash": "sha256-kXZPbclN3gKwjhp2/RYFDFpAsSBwzX1iLF4EcnHZsPQ=", + "owner": "nix-community", + "repo": "nixos-generators", + "rev": "05a3eb158a9c7746a5d463726d7f7cccf07500e4", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixos-generators", + "type": "github" + } + }, + "nixos-hardware": { + "locked": { + "lastModified": 1638182287, + "narHash": "sha256-vBzf+hbTJz2ZdXV/DWirl6wOO7tjdqzTIU+0FANt65U=", + "owner": "nixos", + "repo": "nixos-hardware", + "rev": "6b3f79de09c3de7c91ab51e55e87879f61b6faec", + "type": "github" + }, + "original": { + "owner": "nixos", + "repo": "nixos-hardware", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1643428210, + "narHash": "sha256-ympCeHuXeGitpnegE0raAtWLNg3vZbjj5QbbMvvBGCQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e1b353e890801a759efe9a4c42f6984e47721f0d", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable-small", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1643513770, + "narHash": "sha256-Q64SabfQLuhHQfhpIHS/fLCEO2NUFnI+EKsB5GnfWh8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "66ab3568d67b90275c0720aae8b911bad82c24fe", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1644972330, + "narHash": "sha256-6V2JFpTUzB9G+KcqtUR1yl7f6rd9495YrFECslEmbGw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "19574af0af3ffaf7c9e359744ed32556f34536bd", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nur": { + "locked": { + "lastModified": 1638231901, + "narHash": "sha256-XzuvFTmsXULdWynQWzgaPHikepNhjEpK4o5WXfmRqek=", + "owner": "nix-community", + "repo": "NUR", + "rev": "4e68fb3d8f48e91196deb13f44bcfb421da25afb", + "type": "github" + }, + "original": { + "id": "nur", + "type": "indirect" + } + }, + "nvfetcher": { + "inputs": { + "flake-compat": "flake-compat_2", + "flake-utils": "flake-utils_4", + "nixpkgs": [ + "nixos" + ] + }, + "locked": { + "lastModified": 1634524567, + "narHash": "sha256-v9ZTZj1WNQaaVfs1P1mUPuh518mmwpqszj1EjdeGUmc=", + "owner": "berberman", + "repo": "nvfetcher", + "rev": "807513f4bbd0e3b5863f4c3b91f8ac846ed6da9b", + "type": "github" + }, + "original": { + "owner": "berberman", + "repo": "nvfetcher", + "type": "github" + } + }, + "poetry2nix": { + "inputs": { + "flake-utils": "flake-utils_2", + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1625240517, + "narHash": "sha256-2E1gaOP+bCplhf3kliVQWK5N1NV2h06mkJk2KTiRTJQ=", + "owner": "nix-community", + "repo": "poetry2nix", + "rev": "e40e8ed0e8c11e709e4c8c7c20174facd265a021", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "poetry2nix", + "type": "github" + } + }, + "root": { + "inputs": { + "agenix": "agenix", + "bud": "bud", + "darwin": "darwin", + "deploy": "deploy", + "digga": "digga", + "home": "home", + "latest": "latest_2", + "naersk": "naersk", + "nixos": "nixos", + "nixos-hardware": "nixos-hardware", + "nur": "nur", + "nvfetcher": "nvfetcher" + } + }, + "utils": { + "locked": { + "lastModified": 1637014545, + "narHash": "sha256-26IZAc5yzlD9FlDT54io1oqG/bBoyka+FJk5guaX4x4=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "bba5dcc8e0b20ab664967ad83d24d64cb64ec4f4", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/examples/devos/flake.nix b/examples/devos/flake.nix new file mode 100644 index 000000000..70fe0e8d1 --- /dev/null +++ b/examples/devos/flake.nix @@ -0,0 +1,143 @@ +{ + description = "A highly structured configuration database."; + + nixConfig.extra-experimental-features = "nix-command flakes"; + nixConfig.extra-substituters = "https://nrdxp.cachix.org https://nix-community.cachix.org"; + nixConfig.extra-trusted-public-keys = "nrdxp.cachix.org-1:Fc5PSqY2Jm1TrWfm88l6cvGWwz3s93c6IOifQWnhNW4= nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="; + + inputs = + { + nixos.url = "github:nixos/nixpkgs/release-21.11"; + latest.url = "github:nixos/nixpkgs/nixos-unstable"; + + digga.url = "github:divnix/digga"; + digga.inputs.nixpkgs.follows = "nixos"; + digga.inputs.nixlib.follows = "nixos"; + digga.inputs.home-manager.follows = "home"; + digga.inputs.deploy.follows = "deploy"; + + bud.url = "github:divnix/bud"; + bud.inputs.nixpkgs.follows = "nixos"; + bud.inputs.devshell.follows = "digga/devshell"; + + home.url = "github:nix-community/home-manager/release-21.11"; + home.inputs.nixpkgs.follows = "nixos"; + + darwin.url = "github:LnL7/nix-darwin"; + darwin.inputs.nixpkgs.follows = "nixos"; + + deploy.url = "github:serokell/deploy-rs"; + deploy.inputs.nixpkgs.follows = "nixos"; + + agenix.url = "github:ryantm/agenix"; + agenix.inputs.nixpkgs.follows = "nixos"; + + nvfetcher.url = "github:berberman/nvfetcher"; + nvfetcher.inputs.nixpkgs.follows = "nixos"; + + naersk.url = "github:nmattia/naersk"; + naersk.inputs.nixpkgs.follows = "nixos"; + + nixos-hardware.url = "github:nixos/nixos-hardware"; + }; + + outputs = + { self + , digga + , bud + , nixos + , home + , nixos-hardware + , nur + , agenix + , nvfetcher + , deploy + , ... + } @ inputs: + digga.lib.mkFlake + { + inherit self inputs; + + channelsConfig = { allowUnfree = true; }; + + channels = { + nixos = { + imports = [ (digga.lib.importOverlays ./overlays) ]; + overlays = [ + nur.overlay + agenix.overlay + nvfetcher.overlay + ./pkgs/default.nix + ]; + }; + latest = { }; + }; + + lib = import ./lib { lib = digga.lib // nixos.lib; }; + + sharedOverlays = [ + (final: prev: { + __dontExport = true; + lib = prev.lib.extend (lfinal: lprev: { + our = self.lib; + }); + }) + ]; + + nixos = { + hostDefaults = { + system = "x86_64-linux"; + channelName = "nixos"; + imports = [ (digga.lib.importExportableModules ./modules) ]; + modules = [ + { lib.our = self.lib; } + digga.nixosModules.bootstrapIso + digga.nixosModules.nixConfig + home.nixosModules.home-manager + agenix.nixosModules.age + bud.nixosModules.bud + ]; + }; + + imports = [ (digga.lib.importHosts ./hosts) ]; + hosts = { + /* set host specific properties here */ + NixOS = { }; + }; + importables = rec { + profiles = digga.lib.rakeLeaves ./profiles // { + users = digga.lib.rakeLeaves ./users; + }; + suites = with profiles; rec { + base = [ core users.nixos users.root ]; + }; + }; + }; + + home = { + imports = [ (digga.lib.importExportableModules ./users/modules) ]; + modules = [ ]; + importables = rec { + profiles = digga.lib.rakeLeaves ./users/profiles; + suites = with profiles; rec { + base = [ direnv git ]; + }; + }; + users = { + nixos = { suites, ... }: { imports = suites.base; }; + }; # digga.lib.importers.rakeLeaves ./users/hm; + }; + + devshell = ./shell; + + homeConfigurations = digga.lib.mkHomeConfigurations self.nixosConfigurations; + + deploy.nodes = digga.lib.mkDeployNodes self.nixosConfigurations { }; + + } + // + { + budModules = { devos = import ./shell/bud; }; + } + ; +} diff --git a/hosts/NixOS.nix b/examples/devos/hosts/NixOS.nix similarity index 100% rename from hosts/NixOS.nix rename to examples/devos/hosts/NixOS.nix diff --git a/hosts/bootstrap.nix b/examples/devos/hosts/bootstrap.nix similarity index 100% rename from hosts/bootstrap.nix rename to examples/devos/hosts/bootstrap.nix diff --git a/lib/compat/default.nix b/examples/devos/lib/compat/default.nix similarity index 100% rename from lib/compat/default.nix rename to examples/devos/lib/compat/default.nix diff --git a/lib/compat/nixos/default.nix b/examples/devos/lib/compat/nixos/default.nix similarity index 100% rename from lib/compat/nixos/default.nix rename to examples/devos/lib/compat/nixos/default.nix diff --git a/lib/default.nix b/examples/devos/lib/default.nix similarity index 100% rename from lib/default.nix rename to examples/devos/lib/default.nix diff --git a/modules/hm-system-defaults.nix b/examples/devos/modules/hm-system-defaults.nix similarity index 100% rename from modules/hm-system-defaults.nix rename to examples/devos/modules/hm-system-defaults.nix diff --git a/modules/nix-path.nix b/examples/devos/modules/nix-path.nix similarity index 100% rename from modules/nix-path.nix rename to examples/devos/modules/nix-path.nix diff --git a/overlays/manix.nix b/examples/devos/overlays/manix.nix similarity index 100% rename from overlays/manix.nix rename to examples/devos/overlays/manix.nix diff --git a/overlays/overrides.nix b/examples/devos/overlays/overrides.nix similarity index 100% rename from overlays/overrides.nix rename to examples/devos/overlays/overrides.nix diff --git a/pkgs/_sources/generated.nix b/examples/devos/pkgs/_sources/generated.nix similarity index 100% rename from pkgs/_sources/generated.nix rename to examples/devos/pkgs/_sources/generated.nix diff --git a/pkgs/default.nix b/examples/devos/pkgs/default.nix similarity index 100% rename from pkgs/default.nix rename to examples/devos/pkgs/default.nix diff --git a/pkgs/sources.toml b/examples/devos/pkgs/sources.toml similarity index 100% rename from pkgs/sources.toml rename to examples/devos/pkgs/sources.toml diff --git a/profiles/cachix/default.nix b/examples/devos/profiles/cachix/default.nix similarity index 100% rename from profiles/cachix/default.nix rename to examples/devos/profiles/cachix/default.nix diff --git a/profiles/cachix/nix-community.nix b/examples/devos/profiles/cachix/nix-community.nix similarity index 100% rename from profiles/cachix/nix-community.nix rename to examples/devos/profiles/cachix/nix-community.nix diff --git a/profiles/cachix/nrdxp.nix b/examples/devos/profiles/cachix/nrdxp.nix similarity index 100% rename from profiles/cachix/nrdxp.nix rename to examples/devos/profiles/cachix/nrdxp.nix diff --git a/profiles/core/default.nix b/examples/devos/profiles/core/default.nix similarity index 100% rename from profiles/core/default.nix rename to examples/devos/profiles/core/default.nix diff --git a/profiles/core/starship.toml b/examples/devos/profiles/core/starship.toml similarity index 100% rename from profiles/core/starship.toml rename to examples/devos/profiles/core/starship.toml diff --git a/secrets/secrets.nix b/examples/devos/secrets/secrets.nix similarity index 100% rename from secrets/secrets.nix rename to examples/devos/secrets/secrets.nix diff --git a/examples/devos/shell.nix b/examples/devos/shell.nix new file mode 100644 index 000000000..575a5d822 --- /dev/null +++ b/examples/devos/shell.nix @@ -0,0 +1 @@ +(import ./lib/compat).shellNix diff --git a/shell/bud/default.nix b/examples/devos/shell/bud/default.nix similarity index 100% rename from shell/bud/default.nix rename to examples/devos/shell/bud/default.nix diff --git a/shell/bud/get.bash b/examples/devos/shell/bud/get.bash similarity index 100% rename from shell/bud/get.bash rename to examples/devos/shell/bud/get.bash diff --git a/shell/default.nix b/examples/devos/shell/default.nix similarity index 100% rename from shell/default.nix rename to examples/devos/shell/default.nix diff --git a/shell/devos.nix b/examples/devos/shell/devos.nix similarity index 100% rename from shell/devos.nix rename to examples/devos/shell/devos.nix diff --git a/shell/hooks/default.nix b/examples/devos/shell/hooks/default.nix similarity index 100% rename from shell/hooks/default.nix rename to examples/devos/shell/hooks/default.nix diff --git a/shell/hooks/pre-commit.sh b/examples/devos/shell/hooks/pre-commit.sh similarity index 100% rename from shell/hooks/pre-commit.sh rename to examples/devos/shell/hooks/pre-commit.sh diff --git a/examples/devos/users/modules/.flake-keep b/examples/devos/users/modules/.flake-keep new file mode 100644 index 000000000..e69de29bb diff --git a/users/nixos/default.nix b/examples/devos/users/nixos/default.nix similarity index 100% rename from users/nixos/default.nix rename to examples/devos/users/nixos/default.nix diff --git a/users/profiles/direnv/default.nix b/examples/devos/users/profiles/direnv/default.nix similarity index 100% rename from users/profiles/direnv/default.nix rename to examples/devos/users/profiles/direnv/default.nix diff --git a/users/profiles/git/default.nix b/examples/devos/users/profiles/git/default.nix similarity index 100% rename from users/profiles/git/default.nix rename to examples/devos/users/profiles/git/default.nix diff --git a/users/root/default.nix b/examples/devos/users/root/default.nix similarity index 100% rename from users/root/default.nix rename to examples/devos/users/root/default.nix diff --git a/examples/groupByConfig/devshell/default.nix b/examples/groupByConfig/devshell/default.nix new file mode 100644 index 000000000..40c2d35a0 --- /dev/null +++ b/examples/groupByConfig/devshell/default.nix @@ -0,0 +1,4 @@ +{ self, ... }: +{ + exportedModules = [ ./python.toml ]; +} diff --git a/examples/groupByConfig/devshell/python.toml b/examples/groupByConfig/devshell/python.toml new file mode 100644 index 000000000..f7a17cae7 --- /dev/null +++ b/examples/groupByConfig/devshell/python.toml @@ -0,0 +1,3 @@ +[[commands]] +package = "poetry" +category = "Python" diff --git a/examples/groupByConfig/flake.nix b/examples/groupByConfig/flake.nix new file mode 100644 index 000000000..109cc785c --- /dev/null +++ b/examples/groupByConfig/flake.nix @@ -0,0 +1,27 @@ +{ + description = "A DevOS example. And also a digga test bed."; + + inputs = + { + nixos.url = "github:nixos/nixpkgs/release-21.11"; + digga = { + url = "github:divnix/digga"; + inputs.nixpkgs.follows = "nixos"; + }; + home.url = "github:nix-community/home-manager"; + home.inputs.nixpkgs.follows = "nixos"; + }; + + outputs = inputs @ { self, nixos, digga, home }: + digga.lib.mkFlake { + + inherit self inputs; + + channels.nixos = { }; + + nixos = ./nixos; + home = ./home; + devshell = ./devshell; + + }; +} diff --git a/examples/groupByConfig/home/default.nix b/examples/groupByConfig/home/default.nix new file mode 100644 index 000000000..1b4c3c9cc --- /dev/null +++ b/examples/groupByConfig/home/default.nix @@ -0,0 +1,7 @@ +{ self, ... }: +let + lib = self.inputs.digga.lib; +in +{ + imports = [ (lib.importExportableModules ./modules) ]; +} diff --git a/examples/groupByConfig/home/modules/my-home.nix b/examples/groupByConfig/home/modules/my-home.nix new file mode 100644 index 000000000..4c9637e5e --- /dev/null +++ b/examples/groupByConfig/home/modules/my-home.nix @@ -0,0 +1,45 @@ +{ + programs.git = { + enable = true; + + extraConfig = { + pull.rebase = false; + }; + + aliases = { + a = "add -p"; + co = "checkout"; + cob = "checkout -b"; + f = "fetch -p"; + c = "commit"; + p = "push"; + ba = "branch -a"; + bd = "branch -d"; + bD = "branch -D"; + d = "diff"; + dc = "diff --cached"; + ds = "diff --staged"; + r = "restore"; + rs = "restore --staged"; + st = "status -sb"; + + # reset + soft = "reset --soft"; + hard = "reset --hard"; + s1ft = "soft HEAD~1"; + h1rd = "hard HEAD~1"; + + # logging + lg = + "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"; + plog = + "log --graph --pretty='format:%C(red)%d%C(reset) %C(yellow)%h%C(reset) %ar %C(green)%aN%C(reset) %s'"; + tlog = + "log --stat --since='1 Day Ago' --graph --pretty=oneline --abbrev-commit --date=relative"; + rank = "shortlog -sn --no-merges"; + + # delete merged branches + bdm = "!git branch --merged | grep -v '*' | xargs -n 1 git branch -d"; + }; + }; +} diff --git a/examples/groupByConfig/nixos/Morty.nix b/examples/groupByConfig/nixos/Morty.nix new file mode 100644 index 000000000..f20cd4795 --- /dev/null +++ b/examples/groupByConfig/nixos/Morty.nix @@ -0,0 +1,6 @@ +{ lib, pkgs, config, ... }: { + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; + fileSystems."/" = { device = "/dev/disk/by-label/One"; }; + users.users.root.password = ""; +} diff --git a/examples/groupByConfig/nixos/default.nix b/examples/groupByConfig/nixos/default.nix new file mode 100644 index 000000000..54b42a6e6 --- /dev/null +++ b/examples/groupByConfig/nixos/default.nix @@ -0,0 +1,16 @@ +{ self, inputs, ... }: +let + inherit (inputs.digga.lib) allProfilesTest; +in +{ + hostDefaults.channelName = "nixos"; + hosts = { + Morty.modules = [ ./Morty.nix ]; + Morty.tests = [ allProfilesTest ]; + }; + importables = rec { + suites = rec { + base = [ ]; + }; + }; +} diff --git a/examples/hmOnly/flake.nix b/examples/hmOnly/flake.nix new file mode 100644 index 000000000..891dbde88 --- /dev/null +++ b/examples/hmOnly/flake.nix @@ -0,0 +1,26 @@ +{ + description = "A DevOS example. And also a digga test bed."; + + inputs = + { + nixos.url = "github:nixos/nixpkgs/release-21.11"; + digga.url = "github:divnix/digga"; + digga.inputs.nixpkgs.follows = "nixos"; + digga.inputs.home-manager.follows = "home"; + home.url = "github:nix-community/home-manager/release-21.11"; + home.inputs.nixpkgs.follows = "nixos"; + }; + + outputs = inputs @ { self, nixos, digga, home }: + digga.lib.mkFlake { + + inherit self inputs; + + channels.nixos = { }; + + nixos.hostDefaults.channelName = "nixos"; + + home = ./home; + + }; +} diff --git a/examples/hmOnly/home/default.nix b/examples/hmOnly/home/default.nix new file mode 100644 index 000000000..dca6c3574 --- /dev/null +++ b/examples/hmOnly/home/default.nix @@ -0,0 +1,15 @@ +{ self, inputs, ... }: +let + lib = inputs.digga.lib; +in +{ + imports = [ (lib.importExportableModules ./modules) ]; + modules = [ ]; + importables = rec { + profiles = lib.rakeLeaves ./profiles; + suites = with profiles; { + shell = with shell; [ direnv ]; + }; + }; + users = lib.rakeLeaves ./users; +} diff --git a/examples/hmOnly/home/modules/.flakekeep b/examples/hmOnly/home/modules/.flakekeep new file mode 100644 index 000000000..e69de29bb diff --git a/examples/hmOnly/home/profiles/shell/direnv.nix b/examples/hmOnly/home/profiles/shell/direnv.nix new file mode 100644 index 000000000..2b51c9d23 --- /dev/null +++ b/examples/hmOnly/home/profiles/shell/direnv.nix @@ -0,0 +1,6 @@ +{ + programs.direnv = { + enable = true; + nix-direnv.enable = true; + }; +} diff --git a/examples/hmOnly/home/users/testuser.nix b/examples/hmOnly/home/users/testuser.nix new file mode 100644 index 000000000..34e42c0a5 --- /dev/null +++ b/examples/hmOnly/home/users/testuser.nix @@ -0,0 +1,18 @@ +{ pkgs, suites, ... }: +let + name = "Test User"; + email = "test@example.com"; +in +{ + imports = suites.shell; + + home.packages = [ pkgs.hello ]; + + programs.browserpass.enable = true; + programs.starship.enable = true; + programs.git = { + userName = name; + userEmail = email; + }; +} + diff --git a/flake.lock b/flake.lock index 5d7d11d52..c7488bf9f 100644 --- a/flake.lock +++ b/flake.lock @@ -1,45 +1,5 @@ { "nodes": { - "agenix": { - "inputs": { - "nixpkgs": [ - "nixos" - ] - }, - "locked": { - "lastModified": 1637793790, - "narHash": "sha256-oPXavjxETEWGXq8g7kQHyRLKUmLX2yPtGn+t3V0mrTY=", - "owner": "ryantm", - "repo": "agenix", - "rev": "f85eea0e29fa9a8924571d0e398215e175f80d55", - "type": "github" - }, - "original": { - "owner": "ryantm", - "repo": "agenix", - "type": "github" - } - }, - "beautysh": { - "inputs": { - "flake-utils": "flake-utils", - "nixpkgs": "nixpkgs", - "poetry2nix": "poetry2nix" - }, - "locked": { - "lastModified": 1630693543, - "narHash": "sha256-7Sly3ReaJZw60Qo0rpfN4jF6zy94nwQz6ENgUUFzJfg=", - "owner": "lovesegfault", - "repo": "beautysh", - "rev": "5609593961b70428f58d5c1b4b25cdda43b0d0bd", - "type": "github" - }, - "original": { - "owner": "lovesegfault", - "repo": "beautysh", - "type": "github" - } - }, "blank": { "locked": { "lastModified": 1625557891, @@ -55,65 +15,20 @@ "type": "github" } }, - "bud": { - "inputs": { - "beautysh": "beautysh", - "devshell": [ - "digga", - "devshell" - ], - "nixpkgs": [ - "nixos" - ] - }, - "locked": { - "lastModified": 1640836100, - "narHash": "sha256-My9Lay6BCDwAZgrL4SuVXHkYPHIU7ypnuiS/pd7eg1M=", - "owner": "divnix", - "repo": "bud", - "rev": "b1d8ab3970f4dfb5fb90d7d8a9ab493c75d031fc", - "type": "github" - }, - "original": { - "owner": "divnix", - "repo": "bud", - "type": "github" - } - }, - "darwin": { - "inputs": { - "nixpkgs": [ - "nixos" - ] - }, - "locked": { - "lastModified": 1634994402, - "narHash": "sha256-xmlCVVOYGpZoxgOqsDOVF0B0ASrnbNGVAEzID9qh2xo=", - "owner": "LnL7", - "repo": "nix-darwin", - "rev": "44da835ac40dab5fd231298b59d83487382d2fab", - "type": "github" - }, - "original": { - "owner": "LnL7", - "repo": "nix-darwin", - "type": "github" - } - }, "deploy": { "inputs": { "flake-compat": "flake-compat", "nixpkgs": [ - "nixos" + "latest" ], "utils": "utils" }, "locked": { - "lastModified": 1643787431, - "narHash": "sha256-8IwuVgXulRE3ZWq6z8mytarawC32pKPKR20EyDtSH+w=", + "lastModified": 1632822684, + "narHash": "sha256-lt7eayYmgsD5OQwpb1XYfHpxttn43bWo7G7hIJs+zJw=", "owner": "serokell", "repo": "deploy-rs", - "rev": "4154ba1aaaf7333a916384c348d867d03b6f1409", + "rev": "9a02de4373e0ec272d08a417b269a28ac8b961b4", "type": "github" }, "original": { @@ -137,40 +52,6 @@ "type": "github" } }, - "digga": { - "inputs": { - "blank": "blank", - "deploy": [ - "deploy" - ], - "devshell": "devshell", - "flake-utils-plus": "flake-utils-plus", - "home-manager": [ - "home" - ], - "latest": "latest", - "nixlib": [ - "nixos" - ], - "nixos-generators": "nixos-generators", - "nixpkgs": [ - "nixos" - ] - }, - "locked": { - "lastModified": 1643510242, - "narHash": "sha256-9C9DyJhQ5bevk0CEEjGct+U9EqUgHg8T70nxz47zjMI=", - "owner": "divnix", - "repo": "digga", - "rev": "33bfb05b8a148d8ad6a842de74e22209bf9fe5d7", - "type": "github" - }, - "original": { - "owner": "divnix", - "repo": "digga", - "type": "github" - } - }, "flake-compat": { "flake": false, "locked": { @@ -187,29 +68,13 @@ "type": "github" } }, - "flake-compat_2": { - "flake": false, - "locked": { - "lastModified": 1627913399, - "narHash": "sha256-hY8g6H2KFL8ownSiFeMOjwPC8P0ueXpCVEbxgda3pko=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "12c64ca55c1014cdc1b16ed5a804aa8576601ff2", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, "flake-utils": { "locked": { - "lastModified": 1623875721, - "narHash": "sha256-A8BU7bjS5GirpAUv4QA+QnJ4CceLHkcXdRp4xITDB0s=", + "lastModified": 1638122382, + "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", "owner": "numtide", "repo": "flake-utils", - "rev": "f7e004a55b120c02ecb6219596820fcd32ca8772", + "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", "type": "github" }, "original": { @@ -220,7 +85,7 @@ }, "flake-utils-plus": { "inputs": { - "flake-utils": "flake-utils_3" + "flake-utils": "flake-utils" }, "locked": { "lastModified": 1639385028, @@ -236,63 +101,18 @@ "type": "github" } }, - "flake-utils_2": { - "locked": { - "lastModified": 1642700792, - "narHash": "sha256-XqHrk7hFb+zBvRg6Ghl+AZDq03ov6OshJLiSWOoX5es=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "846b2ae0fc4cc943637d3d1def4454213e203cba", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "flake-utils_3": { - "locked": { - "lastModified": 1638122382, - "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "flake-utils_4": { - "locked": { - "lastModified": 1631561581, - "narHash": "sha256-3VQMV5zvxaVLvqqUrNz3iJelLw30mIVSfZmAaauM3dA=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "7e5bf3925f6fbdfaf50a2a7ca0be2879c4261d19", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "home": { + "home-manager": { "inputs": { "nixpkgs": [ - "nixos" + "nixlib" ] }, "locked": { - "lastModified": 1642653493, - "narHash": "sha256-22mGPjiHUo2Jmze4IjXCJLjeK2mbvvCztHmUyUMr4yw=", + "lastModified": 1637917557, + "narHash": "sha256-3u5bLyGn5NUG3RJA7/v1Bqa/QCFGqp/01Bh/4REf9m4=", "owner": "nix-community", "repo": "home-manager", - "rev": "28b9ae40c45c5e7711c353fee1b7af734e293979", + "rev": "4daff26495ca9ac67476cba8cf15c3e36d91ab18", "type": "github" }, "original": { @@ -318,42 +138,6 @@ "type": "github" } }, - "latest_2": { - "locked": { - "lastModified": 1643347846, - "narHash": "sha256-O0tyXF//ppRpe9yT1Uu5n34yI2MWDyY6ZiJ4Qn5zIkE=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "5bb20f9dc70e9ee16e21cc404b6508654931ce41", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "naersk": { - "inputs": { - "nixpkgs": [ - "nixos" - ] - }, - "locked": { - "lastModified": 1638203339, - "narHash": "sha256-Sz3iCvbWrVWOD/XfYQeRJgP/7MVYL3/VKsNXvDeWBFc=", - "owner": "nmattia", - "repo": "naersk", - "rev": "c3e56b8a4ffb6d906cdfcfee034581f9a8ece571", - "type": "github" - }, - "original": { - "owner": "nmattia", - "repo": "naersk", - "type": "github" - } - }, "nixlib": { "locked": { "lastModified": 1641688481, @@ -369,26 +153,27 @@ "type": "github" } }, - "nixos": { + "nixlib_2": { "locked": { - "lastModified": 1643463207, - "narHash": "sha256-W0azAxucUq84BvWqDPt3gX8kyc8wYvGUynZV9COfByQ=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "03098169624f487eef37186b3214c40e6b6e919d", + "lastModified": 1641688481, + "narHash": "sha256-6L+EU12xLDHby7y8elgFtRKVBxix+7qV8DhVgXqrKZo=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "f697717b3d3a074ffc16c8c8227504f0db292886", "type": "github" }, "original": { - "owner": "nixos", - "ref": "release-21.11", - "repo": "nixpkgs", + "owner": "nix-community", + "repo": "nixpkgs.lib", "type": "github" } }, "nixos-generators": { "inputs": { - "nixlib": "nixlib", - "nixpkgs": "nixpkgs_3" + "nixlib": "nixlib_2", + "nixpkgs": [ + "blank" + ] }, "locked": { "lastModified": 1637655461, @@ -404,146 +189,42 @@ "type": "github" } }, - "nixos-hardware": { - "locked": { - "lastModified": 1638182287, - "narHash": "sha256-vBzf+hbTJz2ZdXV/DWirl6wOO7tjdqzTIU+0FANt65U=", - "owner": "nixos", - "repo": "nixos-hardware", - "rev": "6b3f79de09c3de7c91ab51e55e87879f61b6faec", - "type": "github" - }, - "original": { - "owner": "nixos", - "repo": "nixos-hardware", - "type": "github" - } - }, "nixpkgs": { "locked": { - "lastModified": 1643428210, - "narHash": "sha256-ympCeHuXeGitpnegE0raAtWLNg3vZbjj5QbbMvvBGCQ=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "e1b353e890801a759efe9a4c42f6984e47721f0d", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-unstable-small", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_2": { - "locked": { - "lastModified": 1643513770, - "narHash": "sha256-Q64SabfQLuhHQfhpIHS/fLCEO2NUFnI+EKsB5GnfWh8=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "66ab3568d67b90275c0720aae8b911bad82c24fe", - "type": "github" - }, - "original": { - "owner": "NixOS", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_3": { - "locked": { - "lastModified": 1644972330, - "narHash": "sha256-6V2JFpTUzB9G+KcqtUR1yl7f6rd9495YrFECslEmbGw=", - "owner": "NixOS", + "lastModified": 1638222206, + "narHash": "sha256-Zds9H5WB+hBjWhag5yWWDDfYOtsAZKa+Hj23bjrmbZI=", + "owner": "nixos", "repo": "nixpkgs", - "rev": "19574af0af3ffaf7c9e359744ed32556f34536bd", + "rev": "b1cd9a32c2d877d3ae8f17203cc7895272eec688", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", + "owner": "nixos", + "ref": "release-21.11", "repo": "nixpkgs", "type": "github" } }, - "nur": { - "locked": { - "lastModified": 1638231901, - "narHash": "sha256-XzuvFTmsXULdWynQWzgaPHikepNhjEpK4o5WXfmRqek=", - "owner": "nix-community", - "repo": "NUR", - "rev": "4e68fb3d8f48e91196deb13f44bcfb421da25afb", - "type": "github" - }, - "original": { - "id": "nur", - "type": "indirect" - } - }, - "nvfetcher": { - "inputs": { - "flake-compat": "flake-compat_2", - "flake-utils": "flake-utils_4", - "nixpkgs": [ - "nixos" - ] - }, - "locked": { - "lastModified": 1634524567, - "narHash": "sha256-v9ZTZj1WNQaaVfs1P1mUPuh518mmwpqszj1EjdeGUmc=", - "owner": "berberman", - "repo": "nvfetcher", - "rev": "807513f4bbd0e3b5863f4c3b91f8ac846ed6da9b", - "type": "github" - }, - "original": { - "owner": "berberman", - "repo": "nvfetcher", - "type": "github" - } - }, - "poetry2nix": { - "inputs": { - "flake-utils": "flake-utils_2", - "nixpkgs": "nixpkgs_2" - }, - "locked": { - "lastModified": 1625240517, - "narHash": "sha256-2E1gaOP+bCplhf3kliVQWK5N1NV2h06mkJk2KTiRTJQ=", - "owner": "nix-community", - "repo": "poetry2nix", - "rev": "e40e8ed0e8c11e709e4c8c7c20174facd265a021", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "poetry2nix", - "type": "github" - } - }, "root": { "inputs": { - "agenix": "agenix", - "bud": "bud", - "darwin": "darwin", + "blank": "blank", "deploy": "deploy", - "digga": "digga", - "home": "home", - "latest": "latest_2", - "naersk": "naersk", - "nixos": "nixos", - "nixos-hardware": "nixos-hardware", - "nur": "nur", - "nvfetcher": "nvfetcher" + "devshell": "devshell", + "flake-utils-plus": "flake-utils-plus", + "home-manager": "home-manager", + "latest": "latest", + "nixlib": "nixlib", + "nixos-generators": "nixos-generators", + "nixpkgs": "nixpkgs" } }, "utils": { "locked": { - "lastModified": 1637014545, - "narHash": "sha256-26IZAc5yzlD9FlDT54io1oqG/bBoyka+FJk5guaX4x4=", + "lastModified": 1638122382, + "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", "owner": "numtide", "repo": "flake-utils", - "rev": "bba5dcc8e0b20ab664967ad83d24d64cb64ec4f4", + "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index ed3871782..9952b7810 100644 --- a/flake.nix +++ b/flake.nix @@ -1,5 +1,5 @@ { - description = "A highly structured configuration database."; + description = "DevOS environment configuriguration library."; nixConfig.extra-experimental-features = "nix-command flakes"; nixConfig.extra-substituters = "https://nrdxp.cachix.org https://nix-community.cachix.org"; @@ -7,141 +7,131 @@ inputs = { - nixos.url = "github:nixos/nixpkgs/release-21.11"; + nixpkgs.url = "github:nixos/nixpkgs/release-21.11"; latest.url = "github:nixos/nixpkgs/nixos-unstable"; - - digga.url = "github:divnix/digga"; - digga.inputs.nixpkgs.follows = "nixos"; - digga.inputs.nixlib.follows = "nixos"; - digga.inputs.home-manager.follows = "home"; - digga.inputs.deploy.follows = "deploy"; - - bud.url = "github:divnix/bud"; - bud.inputs.nixpkgs.follows = "nixos"; - bud.inputs.devshell.follows = "digga/devshell"; - - home.url = "github:nix-community/home-manager/release-21.11"; - home.inputs.nixpkgs.follows = "nixos"; - - darwin.url = "github:LnL7/nix-darwin"; - darwin.inputs.nixpkgs.follows = "nixos"; + nixlib.url = "github:nix-community/nixpkgs.lib"; + blank.url = "github:divnix/blank"; deploy.url = "github:serokell/deploy-rs"; - deploy.inputs.nixpkgs.follows = "nixos"; + deploy.inputs.nixpkgs.follows = "latest"; - agenix.url = "github:ryantm/agenix"; - agenix.inputs.nixpkgs.follows = "nixos"; + home-manager.url = "github:nix-community/home-manager/release-21.11"; + home-manager.inputs.nixpkgs.follows = "nixlib"; - nvfetcher.url = "github:berberman/nvfetcher"; - nvfetcher.inputs.nixpkgs.follows = "nixos"; + devshell.url = "github:numtide/devshell"; + flake-utils-plus.url = "github:gytis-ivaskevicius/flake-utils-plus"; - naersk.url = "github:nmattia/naersk"; - naersk.inputs.nixpkgs.follows = "nixos"; - - nixos-hardware.url = "github:nixos/nixos-hardware"; + nixos-generators.url = "github:nix-community/nixos-generators"; + nixos-generators.inputs.nixpkgs.follows = "blank"; }; outputs = { self - , digga - , bud - , nixos - , home - , nixos-hardware - , nur - , agenix - , nvfetcher + , nixlib + , nixpkgs + , latest , deploy + , devshell + , flake-utils-plus + , nixos-generators + , home-manager , ... - } @ inputs: - digga.lib.mkFlake - { - inherit self inputs; - - channelsConfig = { allowUnfree = true; }; - - channels = { - nixos = { - imports = [ (digga.lib.importOverlays ./overlays) ]; - overlays = [ - nur.overlay - agenix.overlay - nvfetcher.overlay - ./pkgs/default.nix - ]; + }@inputs: + let + + tests = import ./src/tests.nix { inherit (nixlib) lib; }; + + internal-modules = import ./src/modules.nix { + inherit (nixlib) lib; + inherit nixos-generators; + }; + + importers = import ./src/importers.nix { + inherit (nixlib) lib; + }; + + generators = import ./src/generators.nix { + inherit (nixlib) lib; + inherit deploy; + }; + + mkFlake = + let + mkFlake' = import ./src/mkFlake { + inherit (nixlib) lib; + inherit (flake-utils-plus.inputs) flake-utils; + inherit deploy devshell home-manager flake-utils-plus internal-modules tests; }; - latest = { }; + in + { + __functor = _: args: (mkFlake' args).flake; + options = args: (mkFlake' args).options; }; - lib = import ./lib { lib = digga.lib // nixos.lib; }; - - sharedOverlays = [ - (final: prev: { - __dontExport = true; - lib = prev.lib.extend (lfinal: lprev: { - our = self.lib; - }); - }) - ]; - - nixos = { - hostDefaults = { - system = "x86_64-linux"; - channelName = "nixos"; - imports = [ (digga.lib.importExportableModules ./modules) ]; - modules = [ - { lib.our = self.lib; } - digga.nixosModules.bootstrapIso - digga.nixosModules.nixConfig - home.nixosModules.home-manager - agenix.nixosModules.age - bud.nixosModules.bud - ]; - }; + # Unofficial Flakes Roadmap - Polyfills + # .. see: https://demo.hedgedoc.org/s/_W6Ve03GK# + # .. also: /ufr-polyfills - imports = [ (digga.lib.importHosts ./hosts) ]; - hosts = { - /* set host specific properties here */ - NixOS = { }; - }; - importables = rec { - profiles = digga.lib.rakeLeaves ./profiles // { - users = digga.lib.rakeLeaves ./users; - }; - suites = with profiles; rec { - base = [ core users.nixos users.root ]; - }; - }; - }; - - home = { - imports = [ (digga.lib.importExportableModules ./users/modules) ]; - modules = [ ]; - importables = rec { - profiles = digga.lib.rakeLeaves ./users/profiles; - suites = with profiles; rec { - base = [ direnv git ]; - }; - }; - users = { - nixos = { suites, ... }: { imports = suites.base; }; - }; # digga.lib.importers.rakeLeaves ./users/hm; - }; + # Super Stupid Flakes (ssf) / System As an Input - Style: + supportedSystems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" ]; + ufrContract = import ./ufr-polyfills/ufrContract.nix; - devshell = ./shell; + # Dependency Groups - Style + checksInputs = { inherit nixpkgs; digga = self; }; + jobsInputs = { inherit nixpkgs; digga = self; }; + devShellInputs = { inherit nixpkgs devshell; }; - homeConfigurations = digga.lib.mkHomeConfigurations self.nixosConfigurations; + # .. we hope you like this style. + # .. it's adopted by a growing number of projects. + # Please consider adopting it if you want to help to improve flakes. - deploy.nodes = digga.lib.mkDeployNodes self.nixosConfigurations { }; + # DEPRECATED - will be removed timely + deprecated = import ./deprecated.nix { + inherit (nixlib) lib; + inherit (self) nixosModules; + inherit flake-utils-plus internal-modules importers; + }; - defaultTemplate = self.templates.bud; - templates.bud.path = ./.; - templates.bud.description = "bud template"; + in - } - // { - budModules = { devos = import ./shell/bud; }; - } - ; + # what you came for ... + lib = { + inherit (flake-utils-plus.inputs.flake-utils.lib) defaultSystems eachSystem eachDefaultSystem filterPackages; + inherit (flake-utils-plus.lib) exportModules exportOverlays exportPackages; + inherit mkFlake; + inherit (tests) mkTest allProfilesTest; + inherit (importers) flattenTree rakeLeaves importOverlays importExportableModules importHosts; + inherit (generators) mkDeployNodes mkHomeConfigurations; + + # DEPRECATED - will be removed soon + inherit (deprecated) + mkSuites + profileMap + mkProfileAttrs + exporters + modules + importModules + importers + ; + + }; + + # a little extra service ... + overlays = import ./overlays { inherit inputs; }; + nixosModules = import ./modules; + + defaultTemplate = self.templates.devos; + templates.devos.path = ./examples/devos; + templates.devos.description = '' + an awesome template for NixOS users, with consideration for common tools like home-manager, devshell, and more. + ''; + + # digga-local use + jobs = ufrContract supportedSystems ./jobs jobsInputs; + checks = ufrContract supportedSystems ./checks checksInputs; + devShell = ufrContract supportedSystems ./shell.nix devShellInputs; + + }; + } diff --git a/jobs/default.nix b/jobs/default.nix new file mode 100644 index 000000000..b479b0be5 --- /dev/null +++ b/jobs/default.nix @@ -0,0 +1,65 @@ +{ system ? builtins.currentSystem +, inputs ? import ../ufr-polyfills/flake.lock.nix ./. +}: +let + + nixpkgs = inputs.nixpkgs; + digga = inputs.digga; + pkgs = import nixpkgs { inherit system; config = { }; overlays = [ ]; }; + + docOptions = digga.lib.mkFlake.options { self = { }; inputs = { }; }; + evaledOptions = (pkgs.lib.evalModules { modules = [ docOptions ]; }).options; + + mkDocPartMd = part: title: intro: + pkgs.writeText "api-reference-${part}.md" '' + # ${title} + ${intro} + + ${( + pkgs.nixosOptionsDoc { options = evaledOptions.${part}; } + ).optionsMDDoc} + ''; + +in +{ + + mkApiReferenceTopLevel = pkgs.writeText "api-reference.md" '' + # Top Level API + `digga`'s top level API. API Containers are documented in their respective sub-chapter: + + - [Channels](./api-reference-channels.md) + - [Home](./api-reference-home.md) + - [Devshell](./api-reference-devshell.md) + - [NixOS](./api-reference-nixos.md) + + ${( pkgs.nixosOptionsDoc { + options = { + inherit (evaledOptions) + channelsConfig + self + inputs + outputsBuilder + supportedSystems + ; + }; + }).optionsMDDoc} + ''; + + mkApiReferenceChannels = mkDocPartMd "channels" "Channels API Container" '' + Configure your channels that you can use throughout your configurations. + + > #### ⚠ Gotcha ⚠ + > Devshell & (non-host-specific) Home-Manager `pkgs` instances are rendered off the + > `nixos.hostDefaults.channelName` (default) channel. + ''; + mkApiReferenceDevshell = mkDocPartMd "devshell" "Devshell API Container" '' + Configure your devshell module collections of your environment. + ''; + mkApiReferenceHome = mkDocPartMd "home" "Home-Manager API Container" '' + Configure your home manager modules, profiles & suites. + ''; + mkApiReferenceNixos = mkDocPartMd "nixos" "NixOS API Container" '' + Configure your nixos modules, profiles & suites. + ''; + +} diff --git a/jobs/flake.lock b/jobs/flake.lock new file mode 100644 index 000000000..c3ea2398a --- /dev/null +++ b/jobs/flake.lock @@ -0,0 +1,197 @@ +{ + "nodes": { + "deploy": { + "inputs": { + "flake-compat": "flake-compat", + "naersk": "naersk", + "nixpkgs": [ + "digga", + "nixpkgs" + ], + "utils": [ + "digga", + "utils" + ] + }, + "locked": { + "lastModified": 1623011836, + "narHash": "sha256-02M4P3eqUdV+ouZb8n1KDR1CXeZQm17cKpjKZKi0c10=", + "owner": "serokell", + "repo": "deploy-rs", + "rev": "70d71b3027b1793b780f1e2435bdbbe1b0cb9ac6", + "type": "github" + }, + "original": { + "owner": "serokell", + "repo": "deploy-rs", + "type": "github" + } + }, + "devshell": { + "locked": { + "lastModified": 1622013274, + "narHash": "sha256-mK/Lv0lCbl07dI5s7tR/7nb79HunKnJik3KyR6yeI2k=", + "owner": "numtide", + "repo": "devshell", + "rev": "e7faf69e6bf8546517cc936c7f6d31c7eb3abcb2", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "devshell", + "type": "github" + } + }, + "digga": { + "inputs": { + "deploy": "deploy", + "devshell": "devshell", + "nixlib": "nixlib", + "nixos-generators": "nixos-generators", + "nixpkgs": [ + "nixpkgs" + ], + "utils": "utils" + }, + "locked": { + "narHash": "sha256-BimhA1sw5W+BnMdLfVrMS+WVDv3vi73OlRCyQI+xQkU=", + "path": "../", + "type": "path" + }, + "original": { + "path": "../", + "type": "path" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1606424373, + "narHash": "sha256-oq8d4//CJOrVj+EcOaSXvMebvuTkmBJuT5tzlfewUnQ=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "99f1c2157fba4bfe6211a321fd0ee43199025dbf", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-utils": { + "locked": { + "lastModified": 1623660459, + "narHash": "sha256-OTmOsh43po7r5F9s9H6lVCBQ2b0FikWbmiwLbMAGRdw=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "98c8d36b1828009b20f12544214683c7489935a1", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "naersk": { + "inputs": { + "nixpkgs": [ + "digga", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1622810282, + "narHash": "sha256-4wmvM3/xfD0hCdNDIXVzRMfL4yB1J+DjH6Zte2xbAxk=", + "owner": "nmattia", + "repo": "naersk", + "rev": "e8061169e1495871b56be97c5c51d310fae01374", + "type": "github" + }, + "original": { + "owner": "nmattia", + "ref": "master", + "repo": "naersk", + "type": "github" + } + }, + "nixlib": { + "locked": { + "lastModified": 1620519687, + "narHash": "sha256-+6Dd72b2CASuXm2W7KRxZIE7AOy/dj4mU28vaF+zxcs=", + "owner": "divnix", + "repo": "nixpkgs.lib", + "rev": "c7b6169809c5f74dd0c34f3d69e9d12ba4d448de", + "type": "github" + }, + "original": { + "owner": "divnix", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "nixos-generators": { + "inputs": { + "nixpkgs": [ + "digga", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1624117213, + "narHash": "sha256-hAoBANafVdM/+8Z6PrlPEKPN6LrdkM4qg2Q/ji0XUns=", + "owner": "nix-community", + "repo": "nixos-generators", + "rev": "c64d3c2153274a6ab355e57f5eedfe6f85073d24", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixos-generators", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1624300589, + "narHash": "sha256-anxKmaq18nWRzrgbPOajbjuq1cqsqgSsj1LTwU+7oQ4=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "38d369643e49043923a6d0e66e60b7fe54291d69", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "root": { + "inputs": { + "digga": "digga", + "nixpkgs": "nixpkgs" + } + }, + "utils": { + "inputs": { + "flake-utils": "flake-utils" + }, + "locked": { + "lastModified": 1624128793, + "narHash": "sha256-yZYvpT6i6iRK0x1a8k/LCoS7JGLVk6Yi1eqfhatnDLk=", + "owner": "gytis-ivaskevicius", + "repo": "flake-utils-plus", + "rev": "785e6f13b8c6131d1eee625a713e8475b2b0512b", + "type": "github" + }, + "original": { + "owner": "gytis-ivaskevicius", + "ref": "staging", + "repo": "flake-utils-plus", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/jobs/flake.nix b/jobs/flake.nix new file mode 100644 index 000000000..fc65026d5 --- /dev/null +++ b/jobs/flake.nix @@ -0,0 +1,33 @@ +{ + description = "Digga Library Jobs"; + + inputs = { + digga.url = "path:../"; + digga.inputs.nixpkgs.follows = "nixpkgs"; + }; + + outputs = inputs @ { self, nixpkgs, digga }: + let + + # Unofficial Flakes Roadmap - Polyfills + # .. see: https://demo.hedgedoc.org/s/_W6Ve03GK# + # .. also: /ufr-polyfills + + # Super Stupid Flakes / System As an Input - Style: + supportedSystems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" ]; + ufrContract = import ../ufr-polyfills/ufrContract.nix; + + # Dependency Groups - Style + jobsInputs = { inherit nixpkgs digga; }; + + # .. we hope you like this style. + # .. it's adopted by a growing number of projects. + # Please consider adopting it if you want to help to improve flakes. + + in + { + + jobs = ufrContract supportedSystems ./. jobsInputs; + + }; +} diff --git a/modules/bootstrap-iso.nix b/modules/bootstrap-iso.nix new file mode 100644 index 000000000..d7a11ca38 --- /dev/null +++ b/modules/bootstrap-iso.nix @@ -0,0 +1,74 @@ +let + getFqdn = config: + let + net = config.networking; + fqdn = + if net.domain != null + then "${net.hostName}.${net.domain}" + else net.hostName; + in + fqdn; + + protoModule = fullHostConfig: { config, lib, modulesPath, suites, self, inputs, ... }@args: { + + imports = [ "${modulesPath}/installer/cd-dvd/installation-cd-minimal.nix" ]; + + isoImage.isoBaseName = "bootstrap-" + (getFqdn config); + isoImage.contents = [{ + source = self; + target = "/devos/"; + }]; + isoImage.storeContents = [ + self.devShell.${config.nixpkgs.system} + # include also closures that are "switched off" by the + # above profile filter on the local config attribute + fullHostConfig.system.build.toplevel + ] ++ builtins.attrValues inputs; + # still pull in tools of deactivated profiles + environment.systemPackages = fullHostConfig.environment.systemPackages; + + # confilcts with networking.wireless which might be slightly + # more useful on a stick + networking.networkmanager.enable = lib.mkForce false; + # confilcts with networking.wireless + networking.wireless.iwd.enable = lib.mkForce false; + + # Set up a link-local boostrap network + # See also: https://github.com/NixOS/nixpkgs/issues/75515#issuecomment-571661659 + networking.usePredictableInterfaceNames = lib.mkForce true; # so prefix matching works + networking.useNetworkd = lib.mkForce true; + networking.useDHCP = lib.mkForce false; + networking.dhcpcd.enable = lib.mkForce false; + systemd.network = { + # https://www.freedesktop.org/software/systemd/man/systemd.network.html + networks."boostrap-link-local" = { + matchConfig = { + Name = "en* wl* ww*"; + }; + networkConfig = { + Description = "Link-local host bootstrap network"; + MulticastDNS = true; + LinkLocalAddressing = "ipv6"; + DHCP = "yes"; + }; + address = [ + # fall back well-known link-local for situations where MulticastDNS is not available + "fe80::47" # 47: n=14 i=9 x=24; n+i+x + ]; + extraConfig = '' + # Unique, yet stable. Based off the MAC address. + IPv6LinkLocalAddressGenerationMode = "eui64" + ''; + }; + }; + }; +in +{ config, ... }: +{ + system.build = { + bootstrapIso = (config.lib.digga.mkBuild + (protoModule config) + ).config.system.build.isoImage; + }; +} + diff --git a/modules/default.nix b/modules/default.nix new file mode 100644 index 000000000..33403434a --- /dev/null +++ b/modules/default.nix @@ -0,0 +1,4 @@ +{ + nixConfig = import ./nix-config.nix; + bootstrapIso = import ./bootstrap-iso.nix; +} diff --git a/modules/nix-config.nix b/modules/nix-config.nix new file mode 100644 index 000000000..8ce0429bc --- /dev/null +++ b/modules/nix-config.nix @@ -0,0 +1,28 @@ +{ lib, ... }: +let + + experimental-features = [ + "flakes" + "nix-command" + ]; + substituters = [ + "https://nrdxp.cachix.org" # quality of life cache from our CI + "https://nix-community.cachix.org" + ]; + trusted-public-keys = [ + "nrdxp.cachix.org-1:Fc5PSqY2Jm1TrWfm88l6cvGWwz3s93c6IOifQWnhNW4=" + "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" + ]; + +in +{ + # package and option is from fup + nix.generateRegistryFromInputs = lib.mkDefault true; + + # missing merge semantics in this option force us to use extra-* for now + nix.extraOptions = '' + extra-experimental-features = ${lib.concatStringsSep " " experimental-features } + extra-substituters = ${lib.concatStringsSep " " substituters } + extra-trusted-public-keys = ${lib.concatStringsSep " " trusted-public-keys } + ''; +} diff --git a/overlays/default.nix b/overlays/default.nix new file mode 100644 index 000000000..a03c1f272 --- /dev/null +++ b/overlays/default.nix @@ -0,0 +1,3 @@ +{ inputs }: { + +} diff --git a/shell.nix b/shell.nix index 575a5d822..66d4ed996 100644 --- a/shell.nix +++ b/shell.nix @@ -1 +1,150 @@ -(import ./lib/compat).shellNix +{ inputs, system ? builtins.currentSystem }: +let + + pkgs = import inputs.nixpkgs { + inherit system; config = { }; + overlays = [ ]; + }; + devshell = import inputs.devshell { inherit pkgs system; }; + + withCategory = category: attrset: attrset // { inherit category; }; + utils = withCategory "utils"; + docs = withCategory "docs"; + + makeDocs = { + name = "make-docs"; + help = "Execute the docs creating jobs and place the results in ./doc"; + command = '' + nix build "$PRJ_ROOT#jobs.${pkgs.system}.mkApiReferenceTopLevel" \ + && cp result "$PRJ_ROOT/doc/api-reference.md" \ + && chmod 755 "$PRJ_ROOT//doc/api-reference.md" + nix build "$PRJ_ROOT#jobs.${pkgs.system}.mkApiReferenceChannels" \ + && cp result "$PRJ_ROOT/doc/api-reference-channels.md" \ + && chmod 755 "$PRJ_ROOT//doc/api-reference-channels.md" + nix build "$PRJ_ROOT#jobs.${pkgs.system}.mkApiReferenceHome" \ + && cp result "$PRJ_ROOT/doc/api-reference-home.md" \ + && chmod 755 "$PRJ_ROOT//doc/api-reference-home.md" + nix build "$PRJ_ROOT#jobs.${pkgs.system}.mkApiReferenceDevshell" \ + && cp result "$PRJ_ROOT/doc/api-reference-devshell.md" \ + && chmod 755 "$PRJ_ROOT//doc/api-reference-devshell.md" + nix build "$PRJ_ROOT#jobs.${pkgs.system}.mkApiReferenceNixos" \ + && cp result "$PRJ_ROOT/doc/api-reference-nixos.md" \ + && chmod 755 "$PRJ_ROOT//doc/api-reference-nixos.md" + ''; + + }; + + test = type: name: withCategory "tests" { + name = "check-${name}"; + help = "Checks ${name} ${type}"; + command = '' + set -e + # set -x + + diggaurl= + lockfile_updated=1 + lockfile_present=1 + tempdigga="\"path:$PRJ_ROOT\"" + + cleanup() { + if is $lockfile_present; then + git checkout -- flake.lock + elif is $lockfile_updated; then + git rm -f flake.lock + fi + # ensure: restore input + [ -z $diggaurl ] || sed -i "s|$tempdigga|$diggaurl|g" flake.nix + } + + digga_fixture() { + # ensure: replace input + diggaurl=$({ grep -o '"github:divnix/digga.*"' flake.nix || true; }) + [ -z $diggaurl ] || sed -i "s|$diggaurl|$tempdigga|g" flake.nix + } + + trap_err() { + local ret=$? + cleanup + echo -e \ + "\033[1m\033[31m""exit $ret: \033[0m\033[1m""command [$BASH_COMMAND] failed""\033[0m" + } + + is () { [ "$1" -eq "0" ]; } + + trap 'trap_err' ERR + + # -------------------------------------------------------------------------------- + + cd $PRJ_ROOT/${type}/${name} + + digga_fixture + + test -f flake.lock && lockfile_present=$? || true + ${pkgs.nixUnstable}/bin/nix flake lock --update-input digga "$@"; lockfile_updated=$?; + ${pkgs.nixUnstable}/bin/nix flake show "$@" + ${pkgs.nixUnstable}/bin/nix flake check "$@" + + cleanup + ''; + }; + +in +devshell.mkShell { + name = "digga"; + packages = with pkgs; [ + fd + nixpkgs-fmt + nixUnstable + ]; + + env = [ + { + name = "NIX_CONFIG"; + value = + ''extra-experimental-features = nix-command flakes + extra-substituters = https://nrdxp.cachix.org https://nix-community.cachix.org + extra-trusted-public-keys = nrdxp.cachix.org-1:Fc5PSqY2Jm1TrWfm88l6cvGWwz3s93c6IOifQWnhNW4= nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=''; + } + ]; + + # tempfix: remove when merged https://github.com/numtide/devshell/pull/123 + devshell.startup.load_profiles = pkgs.lib.mkForce (pkgs.lib.noDepEntry '' + # PATH is devshell's exorbitant privilige: + # fence against its pollution + _PATH=''${PATH} + # Load installed profiles + for file in "$DEVSHELL_DIR/etc/profile.d/"*.sh; do + # If that folder doesn't exist, bash loves to return the whole glob + [[ -f "$file" ]] && source "$file" + done + # Exert exorbitant privilige and leave no trace + export PATH=''${_PATH} + unset _PATH + ''); + + commands = [ + (utils { + command = "git rm --ignore-unmatch -f $PRJ_ROOT/{tests,examples}/*/flake.lock"; + help = "Remove all lock files"; + name = "rm-locks"; + }) + (utils { + name = "fmt"; + help = "Check Nix formatting"; + command = "nixpkgs-fmt \${@} $PRJ_ROOT"; + }) + (utils { + name = "evalnix"; + help = "Check Nix parsing"; + command = "fd --extension nix --exec nix-instantiate --parse --quiet {} >/dev/null"; + }) + + (test "examples" "devos") + (test "examples" "groupByConfig") + (test "examples" "hmOnly") + (test "examples" "all" // { command = "check-devos && check-groupByConfig && check-hmOnly"; }) + (docs { package = pkgs.mdbook; }) + (docs makeDocs) + + ]; +} diff --git a/src/generators.nix b/src/generators.nix new file mode 100644 index 000000000..e72c852b0 --- /dev/null +++ b/src/generators.nix @@ -0,0 +1,74 @@ +{ lib, deploy }: +let + getFqdn = c: + let + net = c.config.networking; + fqdn = + if net.domain != null + then "${net.hostName}.${net.domain}" + else net.hostName; + in + fqdn; + +in +{ + mkHomeConfigurations = nixosConfigurations: + /** + Synopsis: mkHomeConfigurations _nixosConfigurations_ + + Generate the `homeConfigurations` attribute expected by + `home-manager` cli from _nixosConfigurations_ in the form + _user@hostname_. + **/ + let + op = attrs: c: + attrs + // + ( + lib.mapAttrs' + (user: v: { + name = "${user}@${getFqdn c}"; + value = v.home; + }) + c.config.home-manager.users + ) + ; + mkHmConfigs = lib.foldl op { }; + in + mkHmConfigs (builtins.attrValues nixosConfigurations); + + mkDeployNodes = hosts: extraConfig: + /** + Synopsis: mkNodes _nixosConfigurations_ + + Generate the `nodes` attribute expected by deploy-rs + where _nixosConfigurations_ are `nodes`. + + Example input: + ``` + { + hostname-1 = { + fastConnection = true; + sshOpts = [ "-p" "25" ]; + }; + hostname-2 = { + sshOpts = [ "-p" "19999" ]; + sshUser = "root"; + }; + } + ``` + **/ + lib.recursiveUpdate + (lib.mapAttrs + (_: c: + { + hostname = getFqdn c; + profiles.system = { + user = "root"; + path = deploy.lib.${c.config.nixpkgs.system}.activate.nixos c; + }; + } + ) + hosts) + extraConfig; +} diff --git a/src/importers.nix b/src/importers.nix new file mode 100644 index 000000000..039ec9f7b --- /dev/null +++ b/src/importers.nix @@ -0,0 +1,144 @@ +{ lib }: +let + flattenTree = + /** + Synopsis: flattenTree _tree_ + + Flattens a _tree_ of the shape that is produced by rakeLeaves. + + Output Format: + An attrset with names in the spirit of the Reverse DNS Notation form + that fully preserve information about grouping from nesting. + + Example input: + ``` + { + a = { + b = { + c = ; + }; + }; + } + ``` + + Example output: + ``` + { + "a.b.c" = ; + } + ``` + **/ + tree: + let + op = sum: path: val: + let + pathStr = builtins.concatStringsSep "." path; # dot-based reverse DNS notation + in + if builtins.isPath val then + # builtins.trace "${toString val} is a path" + (sum // { + "${pathStr}" = val; + }) + else if builtins.isAttrs val then + # builtins.trace "${builtins.toJSON val} is an attrset" + # recurse into that attribute set + (recurse sum path val) + else + # ignore that value + # builtins.trace "${toString path} is something else" + sum + ; + + recurse = sum: path: val: + builtins.foldl' + (sum: key: op sum (path ++ [ key ]) val.${key}) + sum + (builtins.attrNames val) + ; + in + recurse { } [ ] tree; + + rakeLeaves = + /** + Synopsis: rakeLeaves _path_ + + Recursively collect the nix files of _path_ into attrs. + + Output Format: + An attribute set where all `.nix` files and directories with `default.nix` in them + are mapped to keys that are either the file with .nix stripped or the folder name. + All other directories are recursed further into nested attribute sets with the same format. + + Example file structure: + ``` + ./core/default.nix + ./base.nix + ./main/dev.nix + ./main/os/default.nix + ``` + + Example output: + ``` + { + core = ./core; + base = base.nix; + main = { + dev = ./main/dev.nix; + os = ./main/os; + }; + } + ``` + **/ + dirPath: + let + seive = file: type: + # Only rake `.nix` files or directories + (type == "regular" && lib.hasSuffix ".nix" file) || (type == "directory") + ; + + collect = file: type: { + name = lib.removeSuffix ".nix" file; + value = + let + path = dirPath + "/${file}"; + in + if (type == "regular") + || (type == "directory" && builtins.pathExists (path + "/default.nix")) + then path + # recurse on directories that don't contain a `default.nix` + else rakeLeaves path; + }; + + files = lib.filterAttrs seive (builtins.readDir dirPath); + in + lib.filterAttrs (n: v: v != { }) (lib.mapAttrs' collect files); + +in +{ + inherit rakeLeaves flattenTree; + + importOverlays = dir: + { + # Meant to output a module that sets the overlays option + # overlays order matters. mkAfter ensures those in-house + # overlays are loaded later (after external ones), so the latter + # can be modified via internal overlays + overlays = lib.mkAfter (builtins.attrValues (flattenTree (rakeLeaves dir))); + }; + + importExportableModules = dir: + { + # Meant to output a module that sets the modules option + exportedModules = builtins.attrValues (flattenTree (rakeLeaves dir)); + }; + + importHosts = dir: + { + # Meant to output a module that sets the hosts option (including constructed host names) + hosts = lib.mapAttrs + (n: v: { modules = [ v ]; }) + (flattenTree (rakeLeaves dir)); + }; + +} + diff --git a/src/mkFlake/default.nix b/src/mkFlake/default.nix new file mode 100644 index 000000000..e5ee31d4f --- /dev/null +++ b/src/mkFlake/default.nix @@ -0,0 +1,28 @@ +{ lib, deploy, devshell, home-manager, flake-utils-plus, flake-utils, internal-modules, tests } @ injectedDeps: + +{ self, inputs, ... } @ args: +let + # avoid infinite recursions w.r.t. using self or inputs in imports + injectedDeps' = injectedDeps // { inherit self inputs; }; + + options' = import ./options.nix injectedDeps'; + fupAdapter' = import ./fup-adapter.nix injectedDeps'; + defaultOutputsBuilder' = import ./outputs-builder.nix injectedDeps'; + + evaled = lib.evalModules { modules = [ args options' ]; }; + + defaultOutputsBuilder = defaultOutputsBuilder' evaled.config; + + extraArgs = removeAttrs args (builtins.attrNames evaled.options); + +in +{ + + flake = fupAdapter' { + inherit (evaled) config; + inherit extraArgs defaultOutputsBuilder; + }; + + options = options'; + +} diff --git a/src/mkFlake/fup-adapter.nix b/src/mkFlake/fup-adapter.nix new file mode 100644 index 000000000..9499f0975 --- /dev/null +++ b/src/mkFlake/fup-adapter.nix @@ -0,0 +1,109 @@ +# constructor dependencies +{ lib, self, inputs, flake-utils-plus, internal-modules, ... }: + +{ + # evaluated digga configuration + config + # extra arguments that are passed down to fup +, extraArgs + # pass a custom default fup outputs builder +, defaultOutputsBuilder +}: + +let + + sharedOverlays = [ + (final: prev: { + __dontExport = true; + lib = prev.lib.extend (lfinal: lprev: { + # digga lib can be accessed in packages as lib.digga + digga = lib; + }); + }) + ]; + + defaultHostModules = [ + (internal-modules.hmNixosDefaults { + specialArgs = config.home.importables // { inherit self inputs; }; + modules = config.home.modules ++ config.home.exportedModules; + }) + (internal-modules.globalDefaults { + hmUsers = config.home.users; + }) + ({ ... }@args: { + lib.specialArgs = args.specialArgs or (builtins.trace '' + WARNING: specialArgs is not accessibly by the module system which means you + are likely using NixOS 20.09. Profiles testing and custom builds (ex: iso) + are not supported in 20.09 and using them could result in infinite + recursion errors. It is recommended to update to 21.05 to use either feature. + '' + { }); + }) + internal-modules.customBuilds + ]; + + unifyOverlays = channels: map (o: if builtins.isFunction (o null null) then o channels else o); + + stripChannel = channel: removeAttrs channel [ + # arguments in our channels api that shouldn't be passed to fup + "overlays" + ]; + + # evalArgs sets channelName and system to null by default + # but for proper default handling in fup, null args have to be removed + stripHost = args: removeAttrs (lib.filterAttrs (_: arg: arg != null) args) [ + # arguments in our hosts/hostDefaults api that shouldn't be passed to fup + "externalModules" # TODO: remove deprecated option + "exportedModules" + "tests" + ]; + + diggaFupArgs = { + inherit (config) + channelsConfig + supportedSystems; + inherit self inputs sharedOverlays; + + hosts = builtins.mapAttrs (_: stripHost) config.nixos.hosts; + + channels = builtins.mapAttrs + (name: channel: + stripChannel (channel // { + # pass channels if "overlay" has three arguments + overlaysBuilder = channels: unifyOverlays channels channel.overlays; + }) + ) + config.channels; + + hostDefaults = flake-utils-plus.lib.mergeAny (stripHost config.nixos.hostDefaults) { + # add `self` & `inputs` as specialargs so their libs can be used in imports + specialArgs = config.nixos.importables // { inherit self inputs; }; + modules = config.nixos.hostDefaults.exportedModules ++ defaultHostModules; + }; + + nixosModules = flake-utils-plus.lib.exportModules config.nixos.hostDefaults.exportedModules; + + homeModules = flake-utils-plus.lib.exportModules config.home.exportedModules; + + devshellModules = flake-utils-plus.lib.exportModules config.devshell.exportedModules; + + overlays = flake-utils-plus.lib.exportOverlays { + # since we can't detect overlays owned by self + # we have to filter out ones exported by the inputs + # optimally we would want a solution for NixOS/nix#4740 + inherit (self) pkgs; + inherit inputs; + }; + + outputsBuilder = channels: + flake-utils-plus.lib.mergeAny (defaultOutputsBuilder channels) (config.outputsBuilder channels); + + }; + +in +flake-utils-plus.lib.mkFlake + ( + flake-utils-plus.lib.mergeAny + diggaFupArgs + extraArgs # for overlays list order + ) diff --git a/src/mkFlake/options.nix b/src/mkFlake/options.nix new file mode 100644 index 000000000..5078d0d6d --- /dev/null +++ b/src/mkFlake/options.nix @@ -0,0 +1,492 @@ +# constructor dependencies +{ lib, devshell, flake-utils, self, inputs, ... }: + +with lib; + +{ config, ... }: +let + cfg = config; + + # ############# + # Resolver + # ############# + + /** + Synopsis: maybeImport + + Returns an imported path or string or the object otherwise. + + Use when you want to allow specifying an object directly or a path to it. + It saves the end user the additional import statement. + **/ + maybeImport = obj: + if (builtins.isPath obj || builtins.isString obj) then + import obj + else obj + ; + + /** + Synopsis: maybeImportDevshellToml + + Returns an imported path or string if the filename ends in `toml` or the object or path otherwise. + + Use only for devshell modules, as an apply function. + **/ + maybeImportDevshellToml = obj: + if ((builtins.isPath obj || builtins.isString obj) && lib.hasSuffix ".toml" obj) then + devshell.lib.importTOML obj + else obj + ; + + /** + Synopsis: pathToOr + + Type resolver: types maybeImport's . + + Use in type declarations. + **/ + pathToOr = elemType: with types; coercedTo path maybeImport elemType; + + /** + Synopsis: coercedListOf + + Type resolver & list flattner: flattens a (evtl. arbitrarily nested) list of type . + + Use in type declarations. + **/ + coercedListOf = elemType: with types; + coercedTo anything (x: flatten (singleton x)) (listOf elemType); + + + # ############# + # Custom Types + # ############# + + nixosTestType = pathToOr (mkOptionType { + name = "test"; + check = x: builtins.isFunction x || builtins.isAttrs x; + description = "valid NixOS test"; + }); + + moduleType = mkOptionType { + name = "module"; + inherit (types.submodule { }) check; + description = "valid module"; + }; + + devshellModuleType = with types; coercedTo path maybeImportDevshellToml moduleType; + + overlayType = pathToOr (mkOptionType { + name = "overlay"; + check = builtins.isFunction; + description = "valid Nixpkgs overlay"; + }); + + systemType = (types.enum config.supportedSystems) // { + description = "system defined in `supportedSystems`"; + }; + + channelType = (types.enum (builtins.attrNames config.channels)) // { + description = "channel defined in `channels`"; + }; + + flakeType = with types; (addCheck attrs lib.isStorePath) // { + description = "nix flake"; + }; + + userType = with types; pathToOr moduleType // { + description = "HM user config"; + }; + + overlaysType = with types; coercedListOf overlayType; + modulesType = with types; coercedListOf moduleType; + nixosTestsType = with types; coercedListOf nixosTestType; + devshellModulesType = with types; coercedListOf devshellModuleType; + legacyProfilesType = with types; listOf path; + legacySuitesType = with types; functionTo attrs; + suitesType = with types; attrsOf (coercedListOf path); + usersType = with types; attrsOf userType; + inputsType = with types; attrsOf flakeType; + + # ############# + # Options + # ############# + + systemOpt = { + system = mkOption { + type = with types; nullOr systemType; + default = null; + description = '' + system for this host + ''; + }; + }; + + channelNameOpt = required: { + channelName = mkOption + { + description = '' + Channel this host should follow + ''; + } + // + ( + if required then { + type = with types; channelType; + } else { + type = with types; nullOr channelType; + default = null; + } + ); + }; + + nixosTestOpt = { + tests = mkOption { + type = with types; nixosTestsType; + default = [ ]; + description = '' + tests to run + ''; + example = literalExample '' + [ + { + name = "testname1"; + machine = { ... }; + testScript = ''' + # ... + '''; + } + ({ corutils, writers, ... }: { + name = "testname2"; + machine = { ... }; + testScript = ''' + # ... + '''; + }) + ./path/to/test.nix + ]; + ''; + }; + }; + + modulesOpt = { + modules = mkOption { + type = with types; pathToOr modulesType; + default = [ ]; + description = '' + modules to include + ''; + }; + }; + + exportedModulesOpt' = name: { + type = with types; pathToOr modulesType; + default = [ ]; + description = '' + modules to include in all hosts and export to ${name}Modules output + ''; + }; + + exportedModulesOpt = name: { exportedModules = mkOption (exportedModulesOpt' name); }; + exportedDevshellModulesOpt = { + exportedModules = mkOption ( + (exportedModulesOpt' "devshell") // { + type = with types; devshellModulesType; + } + ); + }; + + # This is only needed for hostDefaults + # modules in each host don't get exported + regularModulesOpt = { + modules = mkOption { + type = with types; pathToOr modulesType; + default = [ ]; + description = '' + modules to include that won't be exported + meant importing modules from external flakes + ''; + }; + }; + + externalModulesDeprecationMessage = '' + The `externalModules` option has been removed. + Any modules that should be exported should be defined with the `exportedModules` + option and all other modules should just go into the `modules` option. + ''; + legacyExternalModulesMod = { config, options, ... }: { + options = { + externalModules = mkOption { + type = with types; modulesType; + default = [ ]; + description = externalModulesDeprecationMessage; + }; + }; + config = mkIf (config.externalModules != [ ]) { + modules = throw '' + ERROR: ${externalModulesDeprecationMessage} + ''; + }; + }; + + hostDefaultsOpt = name: { + hostDefaults = mkOption { + type = with types; hostDefaultsType name; + default = { }; + description = '' + Defaults for all hosts. + the modules passed under hostDefaults will be exported + to the '${name}Modules' flake output. + They will also be added to all hosts. + ''; + }; + }; + + hostsOpt = name: { + hosts = mkOption { + type = with types; hostType; + default = { }; + description = '' + configurations to include in the ${name}Configurations output + ''; + }; + }; + + inputOpt = name: { + input = mkOption { + type = flakeType; + default = self.inputs.${name}; + defaultText = "self.inputs."; + description = '' + nixpkgs flake input to use for this channel + ''; + }; + }; + + overlaysOpt = { + overlays = mkOption { + type = with types; pathToOr overlaysType; + default = [ ]; + description = escape [ "<" ">" ] '' + overlays to apply to this channel + these will get exported under the 'overlays' flake output + as / and any overlay pulled from ''\${inputs} + will be filtered out + ''; + }; + }; + + patchesOpt = { + patches = mkOption { + type = with types; listOf path; + default = [ ]; + description = '' + patches to apply to this channel + ''; + }; + }; + + configOpt = { + config = mkOption { + type = with types; pathToOr attrs; + default = { }; + apply = lib.recursiveUpdate cfg.channelsConfig; + description = '' + nixpkgs config for this channel + ''; + }; + }; + + suitesDeprecationMessage = '' + WARNING: The 'suites' and `profiles` options have been deprecated, you can now create + both with the importables option. `rakeLeaves` can be used to create profiles and + by passing a module or `rec` set to `importables`, suites can access profiles. + Example: + ``` + importables = rec { + profiles = digga.lib.rakeLeaves ./profiles; + suites = with profiles; { }; + } + ``` + See https://github.com/divnix/digga/pull/30 for more details + ''; + legacyImportablesMod = { config, options, ... }: { + config = { + importables = mkIf options.suites.isDefined { + suites = builtins.trace suitesDeprecationMessage config.suites; + }; + }; + options = with types; { + # TODO: remove in favor of importables + profiles = mkOption { + type = pathToOr legacyProfilesType; + default = [ ]; + description = suitesDeprecationMessage; + }; + # TODO: remove in favor of importables + suites = mkOption { + type = pathToOr legacySuitesType; + apply = suites: lib.mkSuites { + inherit suites; + inherit (config) profiles; + }; + description = suitesDeprecationMessage; + }; + }; + }; + + importablesOpt = { + importables = mkOption { + type = with types; submoduleWith { + modules = [{ + freeformType = attrs; + options = { + suites = mkOption { + type = nullOr (pathToOr suitesType); + default = null; + description = '' + collections of profiles + ''; + }; + }; + }]; + }; + default = { }; + description = '' + Packages of paths to be passed to modules as `specialArgs`. + ''; + }; + }; + + usersOpt = { + users = mkOption { + type = with types; usersType; + default = { }; + description = '' + HM users that can be deployed portably without a host. + ''; + }; + }; + + # ############# + # Aggreagate types + # ############# + + hostType = with types; attrsOf (submoduleWith { + modules = [ + # per-host modules not exported, no external modules + { options = systemOpt // (channelNameOpt false) // modulesOpt // nixosTestOpt; } + ]; + }); + + hostDefaultsType = name: with types; submoduleWith { + modules = [ + { options = systemOpt // (channelNameOpt true) // regularModulesOpt // (exportedModulesOpt name); } + legacyExternalModulesMod + ]; + }; + + nixosType = with types; submoduleWith { + specialArgs = { inherit self inputs; }; + modules = [ + { options = (hostsOpt "nixos") // (hostDefaultsOpt "nixos") // importablesOpt; } + legacyImportablesMod + ]; + }; + + homeType = with types; submoduleWith { + specialArgs = { inherit self inputs; }; + modules = [ + { options = regularModulesOpt // (exportedModulesOpt "home") // importablesOpt // usersOpt; } + legacyExternalModulesMod + legacyImportablesMod + ]; + }; + + devshellType = with types; submoduleWith { + specialArgs = { inherit self inputs; }; + modules = [ + { options = regularModulesOpt // exportedDevshellModulesOpt; } + legacyExternalModulesMod + ]; + }; + + channelsType = with types; attrsOf (submoduleWith { + modules = [ + ({ name, ... }: { options = overlaysOpt // configOpt // (inputOpt name) // patchesOpt; }) + ]; + }); + + outputsBuilderType = with types; functionTo attrs; + +in +{ + # this does not get propagated to submodules + # to allow passing flake outputs directly to mkFlake + config._module.check = false; + + options = with types; { + self = mkOption { + type = flakeType; + readOnly = true; + description = "The flake to create the DevOS outputs for"; + }; + inputs = mkOption { + type = inputsType; + readOnly = true; + description = "The flake's inputs"; + }; + supportedSystems = mkOption { + type = listOf str; + default = flake-utils.lib.defaultSystems; + description = '' + The systems supported by this flake + ''; + }; + channelsConfig = mkOption { + type = pathToOr attrs; + default = { }; + description = '' + nixpkgs config for all channels + ''; + }; + channels = mkOption { + type = pathToOr channelsType; + default = { }; + description = '' + nixpkgs channels to create + ''; + }; + outputsBuilder = mkOption { + type = pathToOr outputsBuilderType; + default = channels: { }; + defaultText = "channels: { }"; + description = '' + builder for flake system-spaced outputs + The builder gets passed an attrset of all channels + ''; + }; + nixos = mkOption { + type = pathToOr nixosType; + default = { }; + description = '' + hosts, modules, suites, and profiles for NixOS + ''; + }; + home = mkOption { + type = pathToOr homeType; + default = { }; + description = '' + hosts, modules, suites, and profiles for home-manager + ''; + }; + devshell = mkOption { + type = pathToOr devshellType; + default = { }; + description = '' + Modules to include in your DevOS shell. the `modules` argument + will be exported under the `devshellModules` output + ''; + }; + }; +} diff --git a/src/mkFlake/outputs-builder.nix b/src/mkFlake/outputs-builder.nix new file mode 100644 index 000000000..0b7063128 --- /dev/null +++ b/src/mkFlake/outputs-builder.nix @@ -0,0 +1,142 @@ +# constructor dependencies +{ lib, self, inputs, deploy, devshell, home-manager, flake-utils-plus, tests, ... }: +config: channels: +let + + pkgs = channels.${config.nixos.hostDefaults.channelName}; + system = pkgs.system; + + mkPortableHomeManagerConfiguration = + { username + , configuration + , pkgs + , system ? pkgs.system + }: + let + homeDirectoryPrefix = + if pkgs.stdenv.hostPlatform.isDarwin then "/Users" else "/home"; + homeDirectory = "${homeDirectoryPrefix}/${username}"; + in + home-manager.lib.homeManagerConfiguration { + inherit username homeDirectory pkgs system; + + extraModules = config.home.modules ++ config.home.exportedModules; + extraSpecialArgs = config.home.importables // { inherit self inputs; }; + + configuration = { + imports = [ configuration ]; + } // ( + if pkgs.stdenv.hostPlatform.isLinux + then { targets.genericLinux.enable = true; } + else { } + ); + }; + + homeConfigurationsPortable = + builtins.mapAttrs + (n: v: mkPortableHomeManagerConfiguration { + username = n; + configuration = v; + inherit pkgs system; + }) + config.home.users; + +in +{ + + inherit homeConfigurationsPortable; + + packages = flake-utils-plus.lib.exportPackages self.overlays channels; + + devShell = + let + eval = import "${devshell}/modules" pkgs; + configuration = { + name = lib.mkDefault config.nixos.hostDefaults.channelName; + imports = config.devshell.modules ++ config.devshell.exportedModules; + }; + in + (eval { + inherit configuration; + extraSpecialArgs = { inherit self inputs; }; + }).shell; + + checks = + ( + # for self.homeConfigurations if present & non empty + if ( + (builtins.hasAttr "homeConfigurations" self) && + (self.homeConfigurations != { }) + ) then + let + seive = _: v: v.system == system; # only test for the appropriate system + collectActivationPackages = n: v: { name = "user-" + n; value = v.activationPackage; }; + in + lib.filterAttrs seive (lib.mapAttrs' collectActivationPackages self.homeConfigurations) + else { } + ) + // + ( + # for portableHomeConfigurations if present & non empty + if ( + (homeConfigurationsPortable != { }) + ) then + let + collectActivationPackages = n: v: { name = "user-" + n; value = v.activationPackage; }; + in + lib.mapAttrs' collectActivationPackages homeConfigurationsPortable + else { } + ) + // + ( + # for self.deploy if present & non-empty + if ( + (builtins.hasAttr "deploy" self) && + (self.deploy != { }) + ) then + let + deployChecks = deploy.lib.${system}.deployChecks self.deploy; + renameOp = n: v: { name = "deploy-" + n; value = deployChecks.${n}; }; + in + lib.mapAttrs' renameOp deployChecks + else { } + ) + // + ( + # for self.nixosConfigurations if present & non-empty + if ( + (builtins.hasAttr "nixosConfigurations" self) && + (self.nixosConfigurations != { }) + ) then + let + systemSieve = _: host: host.config.nixpkgs.system == system; + hostConfigsOnThisSystem = lib.filterAttrs systemSieve self.nixosConfigurations; + + createCustomTestOp = n: host: test: + lib.warnIf (!(test ? name)) '' + '${n}' has a test without a name. To distinguish tests in the flake output + all nixos tests must have names. + '' + { + name = "customTestFor-${n}-${test.name}"; + value = tests.mkTest host test; + }; + + createCustomTestsOp = n: host: + let + op = createCustomTestOp n host; + in + builtins.listToAttrs (map op config.nixos.hosts.${n}.tests); + + customTests = + if (hostConfigsOnThisSystem != [ ]) + then lib.foldl (a: b: a // b) { } (lib.attrValues (lib.mapAttrs createCustomTestsOp hostConfigsOnThisSystem)) + else { }; + + in + customTests + else { } + ) + ; + +} diff --git a/src/modules.nix b/src/modules.nix new file mode 100644 index 000000000..44fff1734 --- /dev/null +++ b/src/modules.nix @@ -0,0 +1,68 @@ +{ lib, nixos-generators }: +{ + customBuilds = + { lib, pkgs, config, baseModules, modules, ... }@args: + { + # created in modules system for access to specialArgs and modules + lib.digga.mkBuild = buildModule: + import "${toString pkgs.path}/nixos/lib/eval-config.nix" { + inherit (pkgs) system; + inherit baseModules; + modules = modules ++ [ buildModule ]; + # Newer versions of module system pass specialArgs to modules + # so try to pass that to eval if possible. + specialArgs = args.specialArgs or { }; + }; + system.build = + let + builds = lib.mapAttrs + (format: module: + let build = config.lib.digga.mkBuild module; + in + build // build.config.system.build.${build.config.formatAttr} + ) + (if (lib.versionAtLeast config.system.stateVersion "22.05") then + builtins.removeAttrs nixos-generators.nixosModules [ "vm" ] + else nixos-generators); + in + # ensure these builds can be overriden by other modules + lib.mkDefault builds; + }; + + hmNixosDefaults = { specialArgs, modules }: + { options, ... }: { + config = lib.optionalAttrs (options ? home-manager) { + home-manager = { + # always use the system nixpkgs from the host's channel + useGlobalPkgs = true; + # and use the possible future default (see manual) + useUserPackages = lib.mkDefault true; + + extraSpecialArgs = specialArgs; + sharedModules = modules; + }; + }; + }; + + globalDefaults = { hmUsers }: + { config, pkgs, self, ... }: { + users.mutableUsers = lib.mkDefault false; + + hardware.enableRedistributableFirmware = lib.mkDefault true; + + # digga lib can be accessed in modules directly as config.lib.digga + lib = { + inherit (pkgs.lib) digga; + }; + + _module.args = { + inherit hmUsers; + hosts = throw '' + The `hosts` module argument has been removed, you should instead use + `self.nixosConfigurations`, with the `self` module argument. + ''; + }; + + system.configurationRevision = lib.mkIf (self ? rev) self.rev; + }; +} diff --git a/src/tests.nix b/src/tests.nix new file mode 100644 index 000000000..a244a61d1 --- /dev/null +++ b/src/tests.nix @@ -0,0 +1,48 @@ +{ lib }: +let + + maybeImport = obj: + if (builtins.isPath obj || builtins.isString obj) then + import obj + else obj + ; + + maybeCallTest = pkgs: obj: + if lib.isFunction obj then + pkgs.callPackage obj { } + else obj + ; + + + mkTest = host: test: + let + pkgs = host._module.args.pkgs; + nixosTesting = + (import "${toString pkgs.path}/nixos/lib/testing-python.nix" { + inherit pkgs; + inherit (pkgs) system; + inherit (host.config.lib) specialArgs; + extraConfigurations = host._module.args.modules; + }); + in + nixosTesting.makeTest (maybeCallTest pkgs (maybeImport test)); + + allProfilesTest = { + name = "allProfiles"; + + machine = { suites ? null, ... }: { + imports = + let + allProfiles = lib.foldl + (lhs: rhs: lhs ++ rhs) [ ] + (builtins.attrValues suites); + in + allProfiles; + }; + + testScript = '' + machines[0].systemctl("is-system-running --wait") + ''; + }; +in +{ inherit mkTest allProfilesTest; } diff --git a/ufr-polyfills/UnofficialFlakesRoadmap.md b/ufr-polyfills/UnofficialFlakesRoadmap.md new file mode 100644 index 000000000..4f6d10958 --- /dev/null +++ b/ufr-polyfills/UnofficialFlakesRoadmap.md @@ -0,0 +1,7 @@ +# Hey! + +This project is committed to the [Unofficial Flakes Roadmap (ufr)](https://demo.hedgedoc.org/s/_W6Ve03GK#). + + +_The future of flakes is bright again._ + diff --git a/ufr-polyfills/eachSystem.nix b/ufr-polyfills/eachSystem.nix new file mode 100644 index 000000000..6c7338c4e --- /dev/null +++ b/ufr-polyfills/eachSystem.nix @@ -0,0 +1,12 @@ +# Builds a map from value to =value for each system. +# .. adopted from: https://github.com/numtide/flake-utils +# +systems: f: +let + op = attrs: system: + attrs // { + ${system} = f system; + }; +in +builtins.foldl' op { } systems + diff --git a/ufr-polyfills/flake.lock.nix b/ufr-polyfills/flake.lock.nix new file mode 100644 index 000000000..ce9f1e0a0 --- /dev/null +++ b/ufr-polyfills/flake.lock.nix @@ -0,0 +1,115 @@ +# Adapted from https://github.com/edolstra/flake-compat/blob/master/default.nix +# +# This version only gives back the inputs. In that mode, flake becomes little +# more than a niv replacement. +src: +let + lockFilePath = src + "/flake.lock"; + + lockFile = builtins.fromJSON (builtins.readFile lockFilePath); + + # Emulate builtins.fetchTree + # + # TODO: only implement polyfill if the builtin doesn't exist? + fetchTree = + info: + if info.type == "github" then + { + outPath = fetchTarball { + url = "https://api.${info.host or "github.com"}/repos/${info.owner}/${info.repo}/tarball/${info.rev}"; + sha256 = info.narHash; + }; + rev = info.rev; + shortRev = builtins.substring 0 7 info.rev; + lastModified = info.lastModified; + narHash = info.narHash; + } + else if info.type == "git" then + { + outPath = + builtins.fetchGit + ({ url = info.url; sha256 = info.narHash; } + // (if info ? rev then { inherit (info) rev; } else { }) + // (if info ? ref then { inherit (info) ref; } else { }) + ); + lastModified = info.lastModified; + narHash = info.narHash; + } // (if info ? rev then { + rev = info.rev; + shortRev = builtins.substring 0 7 info.rev; + } else { }) + else if info.type == "path" then + { + outPath = builtins.path { path = info.path; }; + narHash = info.narHash; + } + else if info.type == "tarball" then + { + outPath = fetchTarball { + url = info.url; + sha256 = info.narHash; + }; + narHash = info.narHash; + } + else if info.type == "gitlab" then + { + inherit (info) rev narHash lastModified; + outPath = fetchTarball { + url = "https://${info.host or "gitlab.com"}/api/v4/projects/${info.owner}%2F${info.repo}/repository/archive.tar.gz?sha=${info.rev}"; + sha256 = info.narHash; + }; + shortRev = builtins.substring 0 7 info.rev; + } + else + # FIXME: add Mercurial, tarball inputs. + throw "flake input has unsupported input type '${info.type}'"; + + allNodes = + builtins.mapAttrs + (key: node: + let + sourceInfo = + if key == lockFile.root + then { } + else fetchTree (node.info or { } // removeAttrs node.locked [ "dir" ]); + + inputs = builtins.mapAttrs + (inputName: inputSpec: allNodes.${resolveInput inputSpec}) + (node.inputs or { }); + + # Resolve a input spec into a node name. An input spec is + # either a node name, or a 'follows' path from the root + # node. + resolveInput = inputSpec: + if builtins.isList inputSpec + then getInputByPath lockFile.root inputSpec + else inputSpec; + + # Follow an input path (e.g. ["dwarffs" "nixpkgs"]) from the + # root node, returning the final node. + getInputByPath = nodeName: path: + if path == [ ] + then nodeName + else + getInputByPath + # Since this could be a 'follows' input, call resolveInput. + (resolveInput lockFile.nodes.${nodeName}.inputs.${builtins.head path}) + (builtins.tail path); + + result = sourceInfo // { inherit inputs; inherit sourceInfo; }; + in + if node.flake or true then + result + else + sourceInfo + ) + lockFile.nodes; + + result = + if lockFile.version >= 5 && lockFile.version <= 7 + then allNodes.${lockFile.root}.inputs + else throw "lock file '${lockFilePath}' has unsupported version ${toString lockFile.version}"; + +in +result + diff --git a/ufr-polyfills/ufrContract.nix b/ufr-polyfills/ufrContract.nix new file mode 100644 index 000000000..ac743fd08 --- /dev/null +++ b/ufr-polyfills/ufrContract.nix @@ -0,0 +1,11 @@ +let + eachSystem = import ./eachSystem.nix; +in + +supportedSystems: +imprt: inputs: +eachSystem supportedSystems (system: + import imprt { + inherit inputs system; # The super stupid flakes contract `{ inputs, system }` + } +)