Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nixpkgs/NixOS manuals: devmode feature #243062

Merged
merged 3 commits into from
Jul 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions doc/common.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
outputPath = "share/doc/nixpkgs";
indexPath = "manual.html";
}
8 changes: 8 additions & 0 deletions doc/contributing/contributing-to-documentation.chapter.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ $ nix-shell

If the build succeeds, the manual will be in `./result/share/doc/nixpkgs/manual.html`.

## devmode {#sec-contributing-devmode}

The shell in the manual source directory makes available a command, `devmode`.
It is a daemon, that:
1. watches the manual's source for changes and when they occur — rebuilds
2. HTTP serves the manual, injecting a script that triggers reload on changes
3. opens the manual in the default browser

## Syntax {#sec-contributing-markup}

As per [RFC 0072](https://github.com/NixOS/rfcs/pull/72), all new documentation content should be written in [CommonMark](https://commonmark.org/) Markdown dialect.
Expand Down
8 changes: 5 additions & 3 deletions doc/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ let
inherit (pkgs) lib;
inherit (lib) hasPrefix removePrefix;

common = import ./common.nix;

lib-docs = import ./doc-support/lib-function-docs.nix {
inherit pkgs nixpkgs;
libsets = [
Expand Down Expand Up @@ -132,15 +134,15 @@ in pkgs.stdenv.mkDerivation {
'';

installPhase = ''
dest="$out/share/doc/nixpkgs"
dest="$out/${common.outputPath}"
mkdir -p "$(dirname "$dest")"
mv out "$dest"
mv "$dest/index.html" "$dest/manual.html"
mv "$dest/index.html" "$dest/${common.indexPath}"

cp ${epub} "$dest/nixpkgs-manual.epub"

mkdir -p $out/nix-support/
echo "doc manual $dest manual.html" >> $out/nix-support/hydra-build-products
echo "doc manual $dest ${common.indexPath}" >> $out/nix-support/hydra-build-products
echo "doc manual $dest nixpkgs-manual.epub" >> $out/nix-support/hydra-build-products
'';
}
20 changes: 20 additions & 0 deletions doc/shell.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
let
pkgs = import ../. {
config = {};
overlays = [];
};

common = import ./common.nix;
inherit (common) outputPath indexPath;

web-devmode = import ../pkgs/tools/nix/web-devmode.nix {
inherit pkgs;
buildArgs = "./.";
open = "/${outputPath}/${indexPath}";
};
in
pkgs.mkShell {
packages = [
web-devmode
];
}
4 changes: 4 additions & 0 deletions nixos/doc/manual/common.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
outputPath = "share/doc/nixos";
indexPath = "index.html";
}
2 changes: 2 additions & 0 deletions nixos/doc/manual/contributing-to-this-manual.chapter.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ $ nix-build nixos/release.nix -A manual.x86_64-linux

If the build succeeds, the manual will be in `./result/share/doc/nixos/index.html`.

There's also [a convenient development daemon](https://nixos.org/manual/nixpkgs/unstable/#sec-contributing-devmode).

**Contributing to the man pages**

The man pages are written in [DocBook] which is XML.
Expand Down
16 changes: 9 additions & 7 deletions nixos/doc/manual/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ let

lib = pkgs.lib;

common = import ./common.nix;

manpageUrls = pkgs.path + "/doc/manpage-urls.json";

# We need to strip references to /nix/store/* from options,
Expand Down Expand Up @@ -78,11 +80,11 @@ let
substituteInPlace ./nixos-options.md \
--replace \
'@NIXOS_OPTIONS_JSON@' \
${optionsDoc.optionsJSON}/share/doc/nixos/options.json
${optionsDoc.optionsJSON}/${common.outputPath}/options.json
substituteInPlace ./development/writing-nixos-tests.section.md \
--replace \
'@NIXOS_TEST_OPTIONS_JSON@' \
${testOptionsDoc.optionsJSON}/share/doc/nixos/options.json
${testOptionsDoc.optionsJSON}/${common.outputPath}/options.json
sed -e '/@PYTHON_MACHINE_METHODS@/ {' -e 'r ${testDriverMachineDocstrings}/machine-methods.md' -e 'd' -e '}' \
-i ./development/writing-nixos-tests.section.md
'';
Expand All @@ -99,7 +101,7 @@ in rec {
}
''
# Generate the HTML manual.
dst=$out/share/doc/nixos
dst=$out/${common.outputPath}
mkdir -p $dst

cp ${../../../doc/style.css} $dst/style.css
Expand All @@ -120,7 +122,7 @@ in rec {
--toc-depth 1 \
--chunk-toc-depth 1 \
./manual.md \
$dst/index.html
$dst/${common.indexPath}

mkdir -p $out/nix-support
echo "nix-build out $out" >> $out/nix-support/hydra-build-products
Expand All @@ -131,7 +133,7 @@ in rec {
manual = manualHTML;

# Index page of the NixOS manual.
manualHTMLIndex = "${manualHTML}/share/doc/nixos/index.html";
manualHTMLIndex = "${manualHTML}/${common.outputPath}/${common.indexPath}";

manualEpub = runCommand "nixos-manual-epub"
{ nativeBuildInputs = [ buildPackages.libxml2.bin buildPackages.libxslt.bin buildPackages.zip ];
Expand Down Expand Up @@ -162,7 +164,7 @@ in rec {
}
''
# Generate the epub manual.
dst=$out/share/doc/nixos
dst=$out/${common.outputPath}

xsltproc \
--param chapter.autolabel 0 \
Expand Down Expand Up @@ -197,7 +199,7 @@ in rec {
mkdir -p $out/share/man/man5
nixos-render-docs -j $NIX_BUILD_CORES options manpage \
--revision ${lib.escapeShellArg revision} \
${optionsJSON}/share/doc/nixos/options.json \
${optionsJSON}/${common.outputPath}/options.json \
$out/share/man/man5/configuration.nix.5
'';

Expand Down
20 changes: 20 additions & 0 deletions nixos/doc/manual/shell.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
let
pkgs = import ../../.. {
config = {};
overlays = [];
};

common = import ./common.nix;
inherit (common) outputPath indexPath;

web-devmode = import ../../../pkgs/tools/nix/web-devmode.nix {
inherit pkgs;
buildArgs = "../../release.nix -A manualHTML.${builtins.currentSystem}";
open = "/${outputPath}/${indexPath}";
};
in
pkgs.mkShell {
packages = [
web-devmode
];
}
117 changes: 117 additions & 0 deletions pkgs/tools/nix/web-devmode.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
{
pkgs,
# arguments to `nix-build`, e.g. `"foo.nix -A bar"`
buildArgs,
# what path to open a browser at
open,
}: let
inherit (pkgs) lib;

error_page = pkgs.writeShellScriptBin "error_page" ''
echo "<!DOCTYPE html>
<html>
<head>
<style>
@media (prefers-color-scheme: dark) {
:root { filter: invert(100%); }
}
</style>
</head>
<body><pre>$1</pre></body>
</html>"
'';

# The following would have been simpler:
# 1. serve from `$serve`
# 2. pass each build a `--out-link $serve/result`
# But that way live-server does not seem to detect changes and therefore no
# auto-reloads occur.
# Instead, we copy the contents of each build to the `$serve` directory.
# Using rsync here, instead of `cp`, to get as close to an atomic
# directory copy operation as possible. `--delay-updates` should
# also go towards that.
build_and_copy = pkgs.writeShellScriptBin "build_and_copy" ''
set -euxo pipefail

set +e
stderr=$(2>&1 nix-build --out-link $out_link ${buildArgs})
exit_status=$?
set -e

if [ $exit_status -eq 0 ];
then
# setting permissions to be able to clean up
${lib.getBin pkgs.rsync}/bin/rsync \
--recursive \
--chmod=u=rwX \
--delete-before \
--delay-updates \
$out_link/ \
$serve/
else
set +x
${lib.getBin error_page}/bin/error_page "$stderr" > $error_page_absolute
set -x

${lib.getBin pkgs.findutils}/bin/find $serve \
-type f \
! -name $error_page_relative \
-delete
fi
'';

# https://watchexec.github.io/
watcher = pkgs.writeShellScriptBin "watcher" ''
set -euxo pipefail

${lib.getBin pkgs.watchexec}/bin/watchexec \
--shell=none \
--restart \
--print-events \
${lib.getBin build_and_copy}/bin/build_and_copy
'';

# A Rust alternative to live-server exists, but it was not in nixpkgs.
# `--no-css-inject`: without this it seems that only CSS is auto-reloaded.
# https://www.npmjs.com/package/live-server
server = pkgs.writeShellScriptBin "server" ''
set -euxo pipefail

${lib.getBin pkgs.nodePackages_latest.live-server}/bin/live-server \
--host=127.0.0.1 \
--verbose \
--no-css-inject \
--entry-file=$error_page_relative \
--open=${open} \
$serve
'';

devmode =
pkgs.writeShellScriptBin "devmode"
''
set -euxo pipefail

function handle_exit {
rm -rf "$tmpdir"
}

tmpdir=$(mktemp -d)
pennae marked this conversation as resolved.
Show resolved Hide resolved
trap handle_exit EXIT

export out_link="$tmpdir/result"
export serve="$tmpdir/serve"
mkdir $serve
export error_page_relative=error.html
export error_page_absolute=$serve/$error_page_relative
${lib.getBin error_page}/bin/error_page "building …" > $error_page_absolute

${lib.getBin pkgs.parallel}/bin/parallel \
--will-cite \
--line-buffer \
--tagstr '{/}' \
::: \
"${lib.getBin watcher}/bin/watcher" \
"${lib.getBin server}/bin/server"
'';
in
devmode