summaryrefslogtreecommitdiffstats
path: root/doc
diff options
context:
space:
mode:
authorpennae <82953136+pennae@users.noreply.github.com>2023-07-03 20:48:23 +0200
committerGitHub <noreply@github.com>2023-07-03 20:48:23 +0200
commit06140b7ecf42262f214e4ad846557181277603fe (patch)
tree0a7a06834d3abf7cf1078895f9721263d30f1c0d /doc
parent09176ef50189ab857c9f44d13723f39a771ed17b (diff)
parentfc1b58b593bf8257a7757e69b9a70c2ca3337e20 (diff)
Merge pull request #239636 from pennae/nixpkgs-manual-nrd
doc: dedocbookify nixpkgs manual
Diffstat (limited to 'doc')
-rw-r--r--doc/.gitignore11
-rw-r--r--doc/Makefile114
-rw-r--r--doc/build-aux/pandoc-filters/docbook-reader/citerefentry-to-rst-role.lua23
-rw-r--r--doc/build-aux/pandoc-filters/docbook-writer/labelless-link-is-xref.lua34
-rw-r--r--doc/build-aux/pandoc-filters/docbook-writer/rst-roles.lua44
-rw-r--r--doc/build-aux/pandoc-filters/link-manpages.nix28
-rw-r--r--doc/build-aux/pandoc-filters/myst-reader/roles.lua36
-rw-r--r--doc/build-aux/pandoc-filters/myst-writer/roles.lua25
-rw-r--r--doc/builders.md12
-rw-r--r--doc/builders/images.md13
-rw-r--r--doc/builders/images.xml15
-rw-r--r--doc/builders/packages/dlib.section.md2
-rw-r--r--doc/builders/packages/index.md27
-rw-r--r--doc/builders/packages/index.xml29
-rw-r--r--doc/builders/special.md11
-rw-r--r--doc/builders/special.xml13
-rw-r--r--doc/contributing.md10
-rw-r--r--doc/contributing/staging-workflow.dot16
-rw-r--r--doc/contributing/staging-workflow.svg102
-rw-r--r--doc/contributing/submitting-changes.chapter.md23
-rw-r--r--doc/default.nix162
-rw-r--r--doc/doc-support/default.nix87
-rw-r--r--doc/doc-support/lib-function-docs.nix24
-rw-r--r--doc/doc-support/lib-function-locations.nix38
-rw-r--r--doc/doc-support/parameters.xml19
-rw-r--r--doc/doc-support/xmlformat.conf72
-rw-r--r--doc/functions.md11
-rw-r--r--doc/functions.xml14
-rw-r--r--doc/functions/library.md.in5
-rw-r--r--doc/functions/library.xml14
-rw-r--r--doc/hooks/index.md33
-rw-r--r--doc/hooks/index.xml37
-rw-r--r--doc/languages-frameworks/index.md45
-rw-r--r--doc/languages-frameworks/index.xml47
-rw-r--r--doc/lib.md6
-rw-r--r--doc/manual.md.in14
-rw-r--r--doc/manual.xml49
-rw-r--r--doc/shell.nix3
-rw-r--r--doc/stdenv.md9
-rw-r--r--doc/stdenv/stdenv.chapter.md11
-rw-r--r--doc/using-nixpkgs.md7
-rw-r--r--doc/using/configuration.chapter.md6
42 files changed, 480 insertions, 821 deletions
diff --git a/doc/.gitignore b/doc/.gitignore
deleted file mode 100644
index b08285995f66..000000000000
--- a/doc/.gitignore
+++ /dev/null
@@ -1,11 +0,0 @@
-*.chapter.xml
-*.section.xml
-.version
-functions/library/generated
-functions/library/locations.xml
-highlightjs
-manual-full.xml
-out
-result
-result-*
-media
diff --git a/doc/Makefile b/doc/Makefile
deleted file mode 100644
index d5c0eeef69e2..000000000000
--- a/doc/Makefile
+++ /dev/null
@@ -1,114 +0,0 @@
-MD_TARGETS=$(addsuffix .xml, $(basename $(shell find . -type f -regex '.*\.md$$' -not -name README.md)))
-
-PANDOC ?= pandoc
-
-pandoc_media_dir = media
-# NOTE: Keep in sync with conversion script (/maintainers/scripts/db-to-md.sh).
-# TODO: Remove raw-attribute when we can get rid of DocBook altogether.
-pandoc_commonmark_enabled_extensions = +attributes+fenced_divs+footnotes+bracketed_spans+definition_lists+pipe_tables+raw_attribute
-# Not needed:
-# - docbook-reader/citerefentry-to-rst-role.lua (only relevant for DocBook → MarkDown/rST/MyST)
-pandoc_flags = --extract-media=$(pandoc_media_dir) \
- --lua-filter=$(PANDOC_LUA_FILTERS_DIR)/diagram-generator.lua \
- --lua-filter=build-aux/pandoc-filters/myst-reader/roles.lua \
- --lua-filter=$(PANDOC_LINK_MANPAGES_FILTER) \
- --lua-filter=build-aux/pandoc-filters/docbook-writer/rst-roles.lua \
- --lua-filter=build-aux/pandoc-filters/docbook-writer/labelless-link-is-xref.lua \
- -f commonmark$(pandoc_commonmark_enabled_extensions)+smart
-
-.PHONY: all
-all: validate format out/html/index.html out/epub/manual.epub
-
-.PHONY: render-md
-render-md: ${MD_TARGETS}
-
-.PHONY: debug
-debug:
- nix-shell --run "xmloscopy --docbook5 ./manual.xml ./manual-full.xml"
-
-.PHONY: format
-format: doc-support/result
- find . -iname '*.xml' -type f | while read f; do \
- echo $$f ;\
- xmlformat --config-file "doc-support/result/xmlformat.conf" -i $$f ;\
- done
-
-.PHONY: fix-misc-xml
-fix-misc-xml:
- find . -iname '*.xml' -type f \
- -exec ../nixos/doc/varlistentry-fixer.rb {} ';'
-
-.PHONY: clean
-clean:
- rm -f ${MD_TARGETS} doc-support/result .version manual-full.xml functions/library/locations.xml functions/library/generated
- rm -rf ./out/ ./highlightjs ./media
-
-.PHONY: validate
-validate: manual-full.xml doc-support/result
- jing doc-support/result/docbook.rng manual-full.xml
-
-out/html/index.html: doc-support/result manual-full.xml style.css highlightjs
- mkdir -p out/html
- xsltproc \
- --nonet --xinclude \
- --output $@ \
- doc-support/result/xhtml.xsl \
- ./manual-full.xml
-
- mkdir -p out/html/highlightjs/
- cp -r highlightjs out/html/
-
- cp -r $(pandoc_media_dir) out/html/
- cp ./overrides.css out/html/
- cp ./style.css out/html/style.css
-
- mkdir -p out/html/images/callouts
- cp doc-support/result/xsl/docbook/images/callouts/*.svg out/html/images/callouts/
- chmod u+w -R out/html/
-
-out/epub/manual.epub: epub.xml
- mkdir -p out/epub/scratch
- xsltproc --nonet \
- --output out/epub/scratch/ \
- doc-support/result/epub.xsl \
- ./epub.xml
-
- echo "application/epub+zip" > mimetype
- zip -0Xq "out/epub/manual.epub" mimetype
- rm mimetype
- cd "out/epub/scratch/" && zip -Xr9D "../manual.epub" *
- rm -rf "out/epub/scratch/"
-
-highlightjs: doc-support/result
- mkdir -p highlightjs
- cp -r doc-support/result/highlightjs/highlight.pack.js highlightjs/
- cp -r doc-support/result/highlightjs/LICENSE highlightjs/
- cp -r doc-support/result/highlightjs/mono-blue.css highlightjs/
- cp -r doc-support/result/highlightjs/loader.js highlightjs/
-
-
-manual-full.xml: ${MD_TARGETS} .version functions/library/locations.xml functions/library/generated *.xml **/*.xml **/**/*.xml
- xmllint --nonet --xinclude --noxincludenode manual.xml --output manual-full.xml
-
-.version: doc-support/result
- ln -rfs ./doc-support/result/version .version
-
-doc-support/result: doc-support/default.nix
- (cd doc-support; nix-build)
-
-functions/library/locations.xml: doc-support/result
- ln -rfs ./doc-support/result/function-locations.xml functions/library/locations.xml
-
-functions/library/generated: doc-support/result
- ln -rfs ./doc-support/result/function-docs functions/library/generated
-
-%.section.xml: %.section.md
- $(PANDOC) $^ -t docbook \
- $(pandoc_flags) \
- -o $@
-
-%.chapter.xml: %.chapter.md
- $(PANDOC) $^ -t docbook \
- --top-level-division=chapter \
- $(pandoc_flags) \
- -o $@
diff --git a/doc/build-aux/pandoc-filters/docbook-reader/citerefentry-to-rst-role.lua b/doc/build-aux/pandoc-filters/docbook-reader/citerefentry-to-rst-role.lua
deleted file mode 100644
index 281e85af2717..000000000000
--- a/doc/build-aux/pandoc-filters/docbook-reader/citerefentry-to-rst-role.lua
+++ /dev/null
@@ -1,23 +0,0 @@
---[[
-Converts Code AST nodes produced by pandoc’s DocBook reader
-from citerefentry elements into AST for corresponding role
-for reStructuredText.
-
-We use subset of MyST syntax (CommonMark with features from rST)
-so let’s use the rST AST for rST features.
-
-Reference: https://www.sphinx-doc.org/en/master/usage/restructuredtext/roles.html#role-manpage
-]]
-
-function Code(elem)
- elem.classes = elem.classes:map(function (x)
- if x == 'citerefentry' then
- elem.attributes['role'] = 'manpage'
- return 'interpreted-text'
- else
- return x
- end
- end)
-
- return elem
-end
diff --git a/doc/build-aux/pandoc-filters/docbook-writer/labelless-link-is-xref.lua b/doc/build-aux/pandoc-filters/docbook-writer/labelless-link-is-xref.lua
deleted file mode 100644
index fa97729a28bc..000000000000
--- a/doc/build-aux/pandoc-filters/docbook-writer/labelless-link-is-xref.lua
+++ /dev/null
@@ -1,34 +0,0 @@
---[[
-Converts Link AST nodes with empty label to DocBook xref elements.
-
-This is a temporary script to be able use cross-references conveniently
-using syntax taken from MyST, while we still use docbook-xsl
-for generating the documentation.
-
-Reference: https://myst-parser.readthedocs.io/en/latest/using/syntax.html#targets-and-cross-referencing
-]]
-
-local function starts_with(start, str)
- return str:sub(1, #start) == start
-end
-
-local function escape_xml_arg(arg)
- amps = arg:gsub('&', '&amp;')
- amps_quotes = amps:gsub('"', '&quot;')
- amps_quotes_lt = amps_quotes:gsub('<', '&lt;')
-
- return amps_quotes_lt
-end
-
-function Link(elem)
- has_no_content = #elem.content == 0
- targets_anchor = starts_with('#', elem.target)
- has_no_attributes = elem.title == '' and elem.identifier == '' and #elem.classes == 0 and #elem.attributes == 0
-
- if has_no_content and targets_anchor and has_no_attributes then
- -- xref expects idref without the pound-sign
- target_without_hash = elem.target:sub(2, #elem.target)
-
- return pandoc.RawInline('docbook', '<xref linkend="' .. escape_xml_arg(target_without_hash) .. '" />')
- end
-end
diff --git a/doc/build-aux/pandoc-filters/docbook-writer/rst-roles.lua b/doc/build-aux/pandoc-filters/docbook-writer/rst-roles.lua
deleted file mode 100644
index 5c1b034d0792..000000000000
--- a/doc/build-aux/pandoc-filters/docbook-writer/rst-roles.lua
+++ /dev/null
@@ -1,44 +0,0 @@
---[[
-Converts AST for reStructuredText roles into corresponding
-DocBook elements.
-
-Currently, only a subset of roles is supported.
-
-Reference:
- List of roles:
- https://www.sphinx-doc.org/en/master/usage/restructuredtext/roles.html
- manpage:
- https://tdg.docbook.org/tdg/5.1/citerefentry.html
- file:
- https://tdg.docbook.org/tdg/5.1/filename.html
-]]
-
-function Code(elem)
- if elem.classes:includes('interpreted-text') then
- local tag = nil
- local content = elem.text
- if elem.attributes['role'] == 'manpage' then
- tag = 'citerefentry'
- local title, volnum = content:match('^(.+)%((%w+)%)$')
- if title == nil then
- -- No volnum in parentheses.
- title = content
- end
- content = '<refentrytitle>' .. title .. '</refentrytitle>' .. (volnum ~= nil and ('<manvolnum>' .. volnum .. '</manvolnum>') or '')
- elseif elem.attributes['role'] == 'file' then
- tag = 'filename'
- elseif elem.attributes['role'] == 'command' then
- tag = 'command'
- elseif elem.attributes['role'] == 'option' then
- tag = 'option'
- elseif elem.attributes['role'] == 'var' then
- tag = 'varname'
- elseif elem.attributes['role'] == 'env' then
- tag = 'envar'
- end
-
- if tag ~= nil then
- return pandoc.RawInline('docbook', '<' .. tag .. '>' .. content .. '</' .. tag .. '>')
- end
- end
-end
diff --git a/doc/build-aux/pandoc-filters/link-manpages.nix b/doc/build-aux/pandoc-filters/link-manpages.nix
deleted file mode 100644
index 2589a7c34251..000000000000
--- a/doc/build-aux/pandoc-filters/link-manpages.nix
+++ /dev/null
@@ -1,28 +0,0 @@
-{ pkgs ? import ../../.. {} }:
-let
- inherit (pkgs) lib;
- manpageURLs = lib.importJSON (pkgs.path + "/doc/manpage-urls.json");
-in pkgs.writeText "link-manpages.lua" ''
- --[[
- Adds links to known man pages that aren't already in a link.
- ]]
-
- local manpage_urls = {
- ${lib.concatStringsSep "\n" (lib.mapAttrsToList (man: url:
- " [${builtins.toJSON man}] = ${builtins.toJSON url},") manpageURLs)}
- }
-
- traverse = 'topdown'
-
- -- Returning false as the second value aborts processing of child elements.
- function Link(elem)
- return elem, false
- end
-
- function Code(elem)
- local is_man_role = elem.classes:includes('interpreted-text') and elem.attributes['role'] == 'manpage'
- if is_man_role and manpage_urls[elem.text] ~= nil then
- return pandoc.Link(elem, manpage_urls[elem.text]), false
- end
- end
-''
diff --git a/doc/build-aux/pandoc-filters/myst-reader/roles.lua b/doc/build-aux/pandoc-filters/myst-reader/roles.lua
deleted file mode 100644
index f4ef6d390b40..000000000000
--- a/doc/build-aux/pandoc-filters/myst-reader/roles.lua
+++ /dev/null
@@ -1,36 +0,0 @@
---[[
-Replaces Str AST nodes containing {role}, followed by a Code node
-by a Code node with attrs that would be produced by rST reader
-from the role syntax.
-
-This is to emulate MyST syntax in Pandoc.
-(MyST is a CommonMark flavour with rST features mixed in.)
-
-Reference: https://myst-parser.readthedocs.io/en/latest/syntax/syntax.html#roles-an-in-line-extension-point
-]]
-
-function Inlines(inlines)
- for i = #inlines-1,1,-1 do
- local first = inlines[i]
- local second = inlines[i+1]
- local correct_tags = first.tag == 'Str' and second.tag == 'Code'
- if correct_tags then
- -- docutils supports alphanumeric strings separated by [-._:]
- -- We are slightly more liberal for simplicity.
- -- Allow preceding punctuation (eg '('), otherwise '({file}`...`)'
- -- does not match. Also allow anything followed by a non-breaking space
- -- since pandoc emits those after certain abbreviations (e.g. e.g.).
- local prefix, role = first.text:match('^(.*){([-._+:%w]+)}$')
- if role ~= nil and (prefix == '' or prefix:match("^.*[%p ]$") ~= nil) then
- if prefix == '' then
- inlines:remove(i)
- else
- first.text = prefix
- end
- second.attributes['role'] = role
- second.classes:insert('interpreted-text')
- end
- end
- end
- return inlines
-end
diff --git a/doc/build-aux/pandoc-filters/myst-writer/roles.lua b/doc/build-aux/pandoc-filters/myst-writer/roles.lua
deleted file mode 100644
index 0136bc550652..000000000000
--- a/doc/build-aux/pandoc-filters/myst-writer/roles.lua
+++ /dev/null
@@ -1,25 +0,0 @@
---[[
-Replaces Code nodes with attrs that would be produced by rST reader
-from the role syntax by a Str AST node containing {role}, followed by a Code node.
-
-This is to emulate MyST syntax in Pandoc.
-(MyST is a CommonMark flavour with rST features mixed in.)
-
-Reference: https://myst-parser.readthedocs.io/en/latest/syntax/syntax.html#roles-an-in-line-extension-point
-]]
-
-function Code(elem)
- local role = elem.attributes['role']
-
- if elem.classes:includes('interpreted-text') and role ~= nil then
- elem.classes = elem.classes:filter(function (c)
- return c ~= 'interpreted-text'
- end)
- elem.attributes['role'] = nil
-
- return {
- pandoc.Str('{' .. role .. '}'),
- elem,
- }
- end
-end
diff --git a/doc/builders.md b/doc/builders.md
new file mode 100644
index 000000000000..2e959422405b
--- /dev/null
+++ b/doc/builders.md
@@ -0,0 +1,12 @@
+# Builders {#part-builders}
+
+```{=include=} chapters
+builders/fetchers.chapter.md
+builders/trivial-builders.chapter.md
+builders/testers.chapter.md
+builders/special.md
+builders/images.md
+hooks/index.md
+languages-frameworks/index.md
+builders/packages/index.md
+```
diff --git a/doc/builders/images.md b/doc/builders/images.md
new file mode 100644
index 000000000000..5596784bfa48
--- /dev/null
+++ b/doc/builders/images.md
@@ -0,0 +1,13 @@
+# Images {#chap-images}
+
+This chapter describes tools for creating various types of images.
+
+```{=include=} sections
+images/appimagetools.section.md
+images/dockertools.section.md
+images/ocitools.section.md
+images/snaptools.section.md
+images/portableservice.section.md
+images/makediskimage.section.md
+images/binarycache.section.md
+```
diff --git a/doc/builders/images.xml b/doc/builders/images.xml
deleted file mode 100644
index a4661ab5a7af..000000000000
--- a/doc/builders/images.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<chapter xmlns="http://docbook.org/ns/docbook"
- xmlns:xi="http://www.w3.org/2001/XInclude"
- xml:id="chap-images">
- <title>Images</title>
- <para>
- This chapter describes tools for creating various types of images.
- </para>
- <xi:include href="images/appimagetools.section.xml" />
- <xi:include href="images/dockertools.section.xml" />
- <xi:include href="images/ocitools.section.xml" />
- <xi:include href="images/snaptools.section.xml" />
- <xi:include href="images/portableservice.section.xml" />
- <xi:include href="images/makediskimage.section.xml" />
- <xi:include href="images/binarycache.section.xml" />
-</chapter>
diff --git a/doc/builders/packages/dlib.section.md b/doc/builders/packages/dlib.section.md
index 022195310a71..bd5b1a20a4d4 100644
--- a/doc/builders/packages/dlib.section.md
+++ b/doc/builders/packages/dlib.section.md
@@ -1,6 +1,6 @@
# DLib {#dlib}
-[DLib](http://dlib.net/) is a modern, C++-based toolkit which provides several machine learning algorithms.
+[DLib](http://dlib.net/) is a modern, C++\-based toolkit which provides several machine learning algorithms.
## Compiling without AVX support {#compiling-without-avx-support}
diff --git a/doc/builders/packages/index.md b/doc/builders/packages/index.md
new file mode 100644
index 000000000000..1f4435702406
--- /dev/null
+++ b/doc/builders/packages/index.md
@@ -0,0 +1,27 @@
+# Packages {#chap-packages}
+
+This chapter contains information about how to use and maintain the Nix expressions for a number of specific packages, such as the Linux kernel or X.org.
+
+```{=include=} sections
+citrix.section.md
+dlib.section.md
+eclipse.section.md
+elm.section.md
+emacs.section.md
+firefox.section.md
+fish.section.md
+fuse.section.md
+ibus.section.md
+kakoune.section.md
+linux.section.md
+locales.section.md
+etc-files.section.md
+nginx.section.md
+opengl.section.md
+shell-helpers.section.md
+steam.section.md
+cataclysm-dda.section.md
+urxvt.section.md
+weechat.section.md
+xorg.section.md
+```
diff --git a/doc/builders/packages/index.xml b/doc/builders/packages/index.xml
deleted file mode 100644
index 206e1e49f1f8..000000000000
--- a/doc/builders/packages/index.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<chapter xmlns="http://docbook.org/ns/docbook"
- xmlns:xi="http://www.w3.org/2001/XInclude"
- xml:id="chap-packages">
- <title>Packages</title>
- <para>
- This chapter contains information about how to use and maintain the Nix expressions for a number of specific packages, such as the Linux kernel or X.org.
- </para>
- <xi:include href="citrix.section.xml" />
- <xi:include href="dlib.section.xml" />
- <xi:include href="eclipse.section.xml" />
- <xi:include href="elm.section.xml" />
- <xi:include href="emacs.section.xml" />
- <xi:include href="firefox.section.xml" />
- <xi:include href="fish.section.xml" />
- <xi:include href="fuse.section.xml" />
- <xi:include href="ibus.section.xml" />
- <xi:include href="kakoune.section.xml" />
- <xi:include href="linux.section.xml" />
- <xi:include href="locales.section.xml" />
- <xi:include href="etc-files.section.xml" />
- <xi:include href="nginx.section.xml" />
- <xi:include href="opengl.section.xml" />
- <xi:include href="shell-helpers.section.xml" />
- <xi:include href="steam.section.xml" />
- <xi:include href="cataclysm-dda.section.xml" />
- <xi:include href="urxvt.section.xml" />
- <xi:include href="weechat.section.xml" />
- <xi:include href="xorg.section.xml" />
-</chapter>
diff --git a/doc/builders/special.md b/doc/builders/special.md
new file mode 100644
index 000000000000..6d07fa87f3f3
--- /dev/null
+++ b/doc/builders/special.md
@@ -0,0 +1,11 @@
+# Special builders {#chap-special}
+
+This chapter describes several special builders.
+
+```{=include=} sections
+special/fhs-environments.section.md
+special/makesetuphook.section.md
+special/mkshell.section.md
+special/darwin-builder.section.md
+special/vm-tools.section.md
+```
diff --git a/doc/builders/special.xml b/doc/builders/special.xml
deleted file mode 100644
index 18cf6cfd39c7..000000000000
--- a/doc/builders/special.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<chapter xmlns="http://docbook.org/ns/docbook"
- xmlns:xi="http://www.w3.org/2001/XInclude"
- xml:id="chap-special">
- <title>Special builders</title>
- <para>
- This chapter describes several special builders.
- </para>
- <xi:include href="special/fhs-environments.section.xml" />
- <xi:include href="special/makesetuphook.section.xml" />
- <xi:include href="special/mkshell.section.xml" />
- <xi:include href="special/darwin-builder.section.xml" />
- <xi:include href="special/vm-tools.section.xml" />
-</chapter>
diff --git a/doc/contributing.md b/doc/contributing.md
new file mode 100644
index 000000000000..3215dbe32bec
--- /dev/null
+++ b/doc/contributing.md
@@ -0,0 +1,10 @@
+# Contributing to Nixpkgs {#part-contributing}
+
+```{=include=} chapters
+contributing/quick-start.chapter.md
+contributing/coding-conventions.chapter.md
+contributing/submitting-changes.chapter.md
+contributing/vulnerability-roundup.chapter.md
+contributing/reviewing-contributions.chapter.md
+contributing/contributing-to-documentation.chapter.md
+```
diff --git a/doc/contributing/staging-workflow.dot b/doc/contributing/staging-workflow.dot
new file mode 100644
index 000000000000..faca7a1cad4c
--- /dev/null
+++ b/doc/contributing/staging-workflow.dot
@@ -0,0 +1,16 @@
+digraph {
+ "small changes" [shape=none]
+ "mass-rebuilds and other large changes" [shape=none]
+ "critical security fixes" [shape=none]
+ "broken staging-next fixes" [shape=none]
+
+ "small changes" -> master
+ "mass-rebuilds and other large changes" -> staging
+ "critical security fixes" -> master
+ "broken staging-next fixes" -> "staging-next"
+
+ "staging-next" -> master [color="#E85EB0"] [label="stabilization ends"] [fontcolor="#E85EB0"]
+ "staging" -> "staging-next" [color="#E85EB0"] [label="stabilization starts"] [fontcolor="#E85EB0"]
+
+ master -> "staging-next" -> staging [color="#5F5EE8"] [label="every six hours (GitHub Action)"] [fontcolor="#5F5EE8"]
+}
diff --git a/doc/contributing/staging-workflow.svg b/doc/contributing/staging-workflow.svg
new file mode 100644
index 000000000000..1a174a78830e
--- /dev/null
+++ b/doc/contributing/staging-workflow.svg
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<!-- Generated by graphviz version 7.1.0 (0)
+ -->
+<!-- Pages: 1 -->
+<svg width="743pt" height="291pt"
+ viewBox="0.00 0.00 743.00 291.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 287)">
+<polygon fill="white" stroke="none" points="-4,4 -4,-287 739,-287 739,4 -4,4"/>
+<!-- small changes -->
+<g id="node1" class="node">
+<title>small changes</title>
+<text text-anchor="middle" x="59" y="-261.3" font-family="Times,serif" font-size="14.00">small changes</text>
+</g>
+<!-- master -->
+<g id="node5" class="node">
+<title>master</title>
+<ellipse fill="none" stroke="black" cx="139" cy="-192" rx="43.59" ry="18"/>
+<text text-anchor="middle" x="139" y="-188.3" font-family="Times,serif" font-size="14.00">master</text>
+</g>
+<!-- small changes&#45;&gt;master -->
+<g id="edge1" class="edge">
+<title>small changes&#45;&gt;master</title>
+<path fill="none" stroke="black" d="M77.96,-247.17C88.42,-237.89 101.55,-226.23 112.96,-216.11"/>
+<polygon fill="black" stroke="black" points="114.99,-218.99 120.14,-209.74 110.34,-213.76 114.99,-218.99"/>
+</g>
+<!-- mass&#45;rebuilds and other large changes -->
+<g id="node2" class="node">
+<title>mass&#45;rebuilds and other large changes</title>
+<text text-anchor="middle" x="588" y="-101.3" font-family="Times,serif" font-size="14.00">mass&#45;rebuilds and other large changes</text>
+</g>
+<!-- staging -->
+<g id="node6" class="node">
+<title>staging</title>
+<ellipse fill="none" stroke="black" cx="438" cy="-18" rx="45.49" ry="18"/>
+<text text-anchor="middle" x="438" y="-14.3" font-family="Times,serif" font-size="14.00">staging</text>
+</g>
+<!-- mass&#45;rebuilds and other large changes&#45;&gt;staging -->
+<g id="edge2" class="edge">
+<title>mass&#45;rebuilds and other large changes&#45;&gt;staging</title>
+<path fill="none" stroke="black" d="M587.48,-87.47C586.26,-76.55 582.89,-62.7 574,-54 553.19,-33.63 522.2,-24.65 495.05,-20.86"/>
+<polygon fill="black" stroke="black" points="495.53,-17.39 485.2,-19.71 494.72,-24.35 495.53,-17.39"/>
+</g>
+<!-- critical security fixes -->
+<g id="node3" class="node">
+<title>critical security fixes</title>
+<text text-anchor="middle" x="219" y="-261.3" font-family="Times,serif" font-size="14.00">critical security fixes</text>
+</g>
+<!-- critical security fixes&#45;&gt;master -->
+<g id="edge3" class="edge">
+<title>critical security fixes&#45;&gt;master</title>
+<path fill="none" stroke="black" d="M200.04,-247.17C189.58,-237.89 176.45,-226.23 165.04,-216.11"/>
+<polygon fill="black" stroke="black" points="167.66,-213.76 157.86,-209.74 163.01,-218.99 167.66,-213.76"/>
+</g>
+<!-- broken staging&#45;next fixes -->
+<g id="node4" class="node">
+<title>broken staging&#45;next fixes</title>
+<text text-anchor="middle" x="414" y="-188.3" font-family="Times,serif" font-size="14.00">broken staging&#45;next fixes</text>
+</g>
+<!-- staging&#45;next -->
+<g id="node7" class="node">
+<title>staging&#45;next</title>
+<ellipse fill="none" stroke="black" cx="272" cy="-105" rx="68.79" ry="18"/>
+<text text-anchor="middle" x="272" y="-101.3" font-family="Times,serif" font-size="14.00">staging&#45;next</text>
+</g>
+<!-- broken staging&#45;next fixes&#45;&gt;staging&#45;next -->
+<g id="e