diff --git a/README.md b/README.md index 465c410..ee492c5 100644 --- a/README.md +++ b/README.md @@ -15,22 +15,56 @@ Collection of Cardano related Nix packages and NixOS modules, with a special foc } ``` -This example NixOS configuration will run `cardano-node` and related services on the `preview` network. +This will configure `cardano-node` and `ogmios` on the `preview` network. -#### Read the [Documentation](https://mlabs-haskell.github.io/cardano.nix/) +### Read the [Documentation](https://mlabs-haskell.github.io/cardano.nix/) -### Development +## Setup -To get started, [install nix with flakes enabled](https://zero-to-nix.com/start/install). Enter the development shell and a list of useful tools will be displayed +Install nix and enable flakes, eg. with [Determinate nix installer](https://github.com/DeterminateSystems/nix-installer). -```bash -$ nix develop +Use the project's binary cache to skip builds. Edit `/etc/nix/nix.conf` (or related settings in NixOS config) and merge the new values separated by spaces into the options: + +``` +substituters = ... https://cache.staging.mlabs.city/cardano-nix +trusted-public-keys = ... cardano-nix:BQ7QKgoQQAuL3Kh6pfIJ8oxrihUbUSxf6tN9SxyW608= +``` + +Don't edit `~/.config/nix/nix.conf` in your home directory. Don't add users to `trusted-users` because it is [insecure](https://nixos.org/manual/nix/stable/command-ref/conf-file.html?highlight=trusted-user#conf-trusted-users). + +### Development Shell + +Development is supported on linux systems. Virtual machines are run with `qemu` so `kvm` is recommended. + +`cardano.nix` provides a devshell that includes various tools to build, test, run and update the project: + +``` +❯ nix develop ... ❄️ Welcome to the cardano.nix devshell ❄️ -... + +[documentation] + + docs-build - build documentation + docs-serve - serve documentation web page + +[general commands] + + menu - prints this menu + +[tests] + + build-all - build all packages and checks with `devour-flake` + check - run `nix flake check` + run-vm-test - list and run virtual machine integration tests + +[tools] + + fmt - format the source tree + update-pre-commit-hooks - update git pre-commit hooks ``` -See the [Development Documentation](https://mlabs-haskell.github.io/cardano.nix/development/develop/) for more information. +A `.envrc` is also provided, using [direnv]() and [nix-direnv](https://github.com/nix-community/nix-direnv) is suggested. ### Running Integration Tests diff --git a/docs/default.nix b/docs/default.nix index f745f5e..c4111ea 100644 --- a/docs/default.nix +++ b/docs/default.nix @@ -6,173 +6,85 @@ }: let rootConfig = config; in { - perSystem = { - config, - lib, - pkgs, - ... - }: let - inherit (pkgs) stdenv python311Packages; + imports = [ + ./render.nix + ]; - my-mkdocs = let - inherit (python311Packages) mkdocs; - in - pkgs.runCommand "my-mkdocs" + renderDocs = { + enable = true; + sidebarOptions = [ { - buildInputs = [ - mkdocs - python311Packages.mkdocs-material - ]; - } '' - mkdir -p $out/bin - - cat < $out/bin/mkdocs - #!${pkgs.bash}/bin/bash - set -euo pipefail - export PYTHONPATH=$PYTHONPATH - exec ${mkdocs}/bin/mkdocs "\$@" - MKDOCS - - chmod +x $out/bin/mkdocs - ''; - - eachOptions = removeAttrs rootConfig.flake.nixosModules ["default"]; - - eachOptionsDoc = - lib.mapAttrs' ( - name: value: - lib.nameValuePair - # take foo.options and turn it into just foo - (builtins.head (lib.splitString "." name)) - (pkgs.nixosOptionsDoc { - # By default `nixosOptionsDoc` will ignore internal options but we want to show them - # This hack will make all the options not internal and visible and optionally append to the - # description a new field which is then corrected rendered as it was a native field - transformOptions = opt: - opt - // { - internal = false; - visible = true; - description = '' - ${opt.description} - ${lib.optionalString opt.internal "*Internal:* true"} - ''; - }; - options = - (lib.evalModules { - modules = (import "${inputs.nixpkgs}/nixos/modules/module-list.nix") ++ [value]; - specialArgs = {inherit pkgs;}; - }) - .options - .cardano; - }) - ) - eachOptions; - - statements = - lib.concatStringsSep "\n" - (lib.mapAttrsToList (n: v: '' - path=$out/${n}.md - cat ${v.optionsCommonMark} >> $path - '') - eachOptionsDoc); - - githubUrl = "https://github.com/mlabs-haskell/cardano.nix/tree/main"; - - options-doc = pkgs.runCommand "nixos-options" {} '' - mkdir $out - ${statements} - # Fixing links to storage to files in github - find $out -type f | xargs -n1 sed -i -e "s,${self.outPath},${githubUrl},g" -e "s,file://https://,https://,g" - ''; - - docsPath = "./docs/reference/module-options"; - - index = { - nav = [ - { - "Reference" = [{"NixOS Module Options" = lib.mapAttrsToList (n: _: "reference/module-options/${n}.md") eachOptionsDoc;}]; - } - ]; - }; - - indexYAML = - pkgs.runCommand "index.yaml" { - nativeBuildInputs = [pkgs.yq-go]; - index = builtins.toFile "index.json" (builtins.unsafeDiscardStringContext (builtins.toJSON index)); - } '' - yq -o yaml $index >$out - ''; - - mergedMkdocsYaml = - pkgs.runCommand "mkdocs.yaml" { - nativeBuildInputs = [pkgs.yq-go]; - } '' - yq '. *+ load("${indexYAML}")' ${./mkdocs.yml} -o yaml >$out - ''; - in { - packages = { - docs = stdenv.mkDerivation { - src = ../.; # FIXME: use config.flake-root.package here - name = "cardano-nix-docs"; - - nativeBuildInputs = [my-mkdocs]; - - buildPhase = '' - ln -s ${options-doc} ${docsPath} - # mkdocs expect mkdocs one level upper than `docs/`, but we want to keep it in `docs/` - cp ${mergedMkdocsYaml} mkdocs.yml - mkdocs build -f mkdocs.yml -d site - ''; - - installPhase = '' - mv site $out - rm $out/default.nix # Clean nwanted side-effect of mkdocs - ''; - - passthru.serve = config.packages.docs-serve; - }; - - docs-serve = pkgs.writeShellScriptBin "docs-serve" '' - set -euo pipefail - - # link in options reference - rm -f ${docsPath} - ln -s ${options-doc} ${docsPath} - rm -f mkdocs.yml - ln -s ${mergedMkdocsYaml} mkdocs.yml - - BASEDIR="$(${lib.getExe config.flake-root.package})" - cd $BASEDIR - - cat <) builds. [NixOS](https://zero-to-nix.com/concepts/nixos) is a Linux distribution with a [declarative configuration](https://zero-to-nix.com/concepts/nixos#configuration) system providing [atomic](https://zero-to-nix.com/concepts/nixos#atomicity) updates and [rollbacks](https://zero-to-nix.com/concepts/nixos#rollbacks). These features are responsible for the increased reliability of a NixOS system, making it an attractive DevOps toolset for deploying Cardano services. +[Nix](https://zero-to-nix.com/concepts/nix) is a [declarative](https://zero-to-nix.com/concepts/declarative) package manager ensuring hash-based [dependency pinning](https://zero-to-nix.com/concepts/pinning) and [reproducible](https://zero-to-nix.com/concepts/reproducibility) builds. [NixOS](https://zero-to-nix.com/concepts/nixos) is a Linux distribution with a [declarative configuration](https://zero-to-nix.com/concepts/nixos#configuration) system providing [atomic](https://zero-to-nix.com/concepts/nixos#atomicity) updates and [rollbacks](https://zero-to-nix.com/concepts/nixos#rollbacks). These features are responsible for the increased reliability of a NixOS system, making it an attractive DevOps toolset for deploying Cardano services. ### What? diff --git a/docs/render.nix b/docs/render.nix new file mode 100644 index 0000000..eac6df0 --- /dev/null +++ b/docs/render.nix @@ -0,0 +1,263 @@ +{ + config, + inputs, + lib, + ... +}: let + cfg = config.renderDocs; + + inherit (lib) mkOption mkEnableOption mkIf; + inherit (lib.types) bool str listOf deferredModule submodule path; + + sidebarType = submodule { + options = { + anchor = mkOption { + type = str; + description = '' + Text to display in TOC for this options group + ''; + }; + modules = mkOption { + type = listOf deferredModule; + description = '' + List of modules to scan/render options + ''; + }; + namespaces = mkOption { + type = listOf str; + description = '' + List of dotted attribute paths to render + ''; + }; + }; + }; + fixupType = submodule { + options = { + storePath = mkOption { + type = path; + description = '' + Path to be replaced + ''; + }; + githubUrl = mkOption { + type = str; + description = '' + Public URL to replace storage paths for definitions in rendered docs + ''; + }; + }; + }; +in { + options.renderDocs = { + enable = mkEnableOption "Document rendering"; + packageName = mkOption { + type = str; + default = "docs"; + description = '' + Name of package with generated documentation (in flake outputs) + ''; + }; + + sidebarOptions = mkOption { + type = listOf sidebarType; + default = []; + description = '' + List of reference sections + ''; + }; + + fixups = mkOption { + type = listOf fixupType; + default = []; + }; + + invisible = mkOption { + type = bool; + default = false; + description = '' + render invisible options as well + ''; + }; + }; + + config = mkIf cfg.enable { + perSystem = { + config, + lib, + pkgs, + ... + }: let + inherit (pkgs) stdenv mkdocs python311Packages; + + my-mkdocs = + pkgs.runCommand "my-mkdocs" + { + buildInputs = [ + mkdocs + python311Packages.mkdocs-material + ]; + } '' + mkdir -p $out/bin + + cat < $out/bin/mkdocs + #!${pkgs.bash}/bin/bash + set -euo pipefail + export PYTHONPATH=$PYTHONPATH + exec ${mkdocs}/bin/mkdocs "\$@" + MKDOCS + + chmod +x $out/bin/mkdocs + ''; + + eachOptionsDoc = builtins.listToAttrs (builtins.map ( + { + anchor, + modules, + namespaces, + ... + }: + lib.nameValuePair + anchor + (pkgs.nixosOptionsDoc { + # By default `nixosOptionsDoc` will ignore internal options but we want to show them + # This hack will make all the options not internal and visible and optionally append to the + # description a new field which is then corrected rendered as it was a native field + transformOptions = opt: + opt + // lib.optionalAttrs cfg.invisible { + internal = false; + visible = true; + } + // { + description = '' + ${lib.optionalString (opt.description != null) opt.description} + ${lib.optionalString (opt.internal && cfg.invisible) "*Internal:* true"} + ''; + } + // ( + if (lib.length (lib.splitString "\n" opt.default.text or "") > 20) + then { + default._type = "literalMD"; + default.text = '' +
This value is long. Click to expand. + ```nix + ${opt.default.text} + ``` +
+ ''; + } + else {} + ); + options = let + evaluated = lib.evalModules { + modules = (import "${inputs.nixpkgs}/nixos/modules/module-list.nix") ++ modules; + specialArgs = {inherit pkgs;}; + }; + in + lib.foldr (path: acc: lib.recursiveUpdate acc (lib.attrByPath (lib.splitString "." path) {} evaluated.options)) {} namespaces; + }) + ) + cfg.sidebarOptions); + + statements = + lib.concatStringsSep "\n" + (lib.mapAttrsToList (n: v: '' + path=$out/${n}.md + cat ${v.optionsCommonMark} | sed 's/\\> $path + '') + eachOptionsDoc); + + options-doc = pkgs.runCommand "nixos-options" {} '' + mkdir $out + ${statements} + # Replace `/nix/store` related paths with public urls + find $out -type f | xargs -n1 sed -i ${lib.concatMapStrings (x: " -e 's,${x.storePath},${x.githubUrl},g'") cfg.fixups} -e "s,file://https://,https://,g" + ''; + + docsPath = "./docs/reference/module-options"; + + index = { + nav = [ + { + "NixOS Module Reference" = lib.mapAttrsToList (n: _: {${n} = "reference/module-options/${n}.md";}) eachOptionsDoc; + } + ]; + }; + + indexYAML = + pkgs.runCommand "index.yaml" { + nativeBuildInputs = [pkgs.yq-go]; + index = builtins.toFile "index.json" (builtins.unsafeDiscardStringContext (builtins.toJSON index)); + } '' + yq -o yaml $index >$out + ''; + + mergedMkdocsYaml = + pkgs.runCommand "mkdocs.yaml" { + nativeBuildInputs = [pkgs.yq-go]; + } '' + yq '. *+ load("${indexYAML}")' ${./mkdocs.yml} -o yaml >$out + ''; + in { + packages.${cfg.packageName} = stdenv.mkDerivation { + src = ../.; # FIXME: use config.flake-root.package here + name = "cardano-nix-docs"; + + nativeBuildInputs = [my-mkdocs]; + + buildPhase = '' + ln -s ${options-doc} ${docsPath} + # mkdocs expect mkdocs one level upper than `docs/`, but we want to keep it in `docs/` + cp ${mergedMkdocsYaml} mkdocs.yml + mkdocs build -f mkdocs.yml -d site + ''; + + installPhase = '' + mv site $out + rm $out/default.nix # Clean nwanted side-effect of mkdocs + ''; + + passthru.serve = pkgs.writeShellScriptBin "serve" '' + set -euo pipefail + + # link in options reference + rm -f ${docsPath} + ln -s ${options-doc} ${docsPath} + rm -f mkdocs.yml + ln -s ${mergedMkdocsYaml} mkdocs.yml + + BASEDIR="$(${lib.getExe config.flake-root.package})" + cd $BASEDIR + + cat <