Subject: [bug#54199] [PATCH] doc: Add 'Working on Shepherd' section.

From: Attila Lendvai <[email-masked]>
Date: Mon, 28 Feb 2022 19:51:16 +0100

---
 doc/contributing.texi | 91 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 91 insertions(+)

diff --git a/doc/contributing.texi b/doc/contributing.texi
index 207efc4ee6..d36b6e66e0 100644
--- a/doc/contributing.texi
+++ b/doc/contributing.texi
@@ -29,6 +29,7 @@ choice.
 * Tracking Bugs and Patches::   Keeping it all organized.
 * Commit Access::               Pushing to the official repository.
 * Updating the Guix Package::   Updating the Guix package definition.
+* Working on Shepherd::         Modifying and testing Shepherd.
 * Translating Guix::            Make Guix speak your native language.
 @end menu
 
@@ -1697,6 +1698,96 @@ This check can be disabled, @emph{at your own peril}, by setting the
 this variable is set, the updated package source is also added to the
 store.  This is used as part of the release process of Guix.
 
+@node Working on Shepherd
+@section Working on Shepherd
+
+This chapter documents how to modify and test GNU@tie{}Shepherd
+(@pxref{Shepherd Services}) in the Guix environment.
+
+There are two @emph{manifestations} of Shepherd in a Guix System:
+
+@table @code
+
+@item @emph{The Shepherd process}
+The init process first started by the kernel (i.e. running as PID 1).
+This is a Guile executable that is executing the @code{main} function of
+the Shepherd codebase.  Among other things, this is the process
+responsible for starting and stopping Guix System services (i.e. daemon
+processes).
+
+@item @emph{The Shepherd API}
+The Scheme code of Shepherd, which is a dependency of certain packages
+and the Guix codebase itself.  A typical example of this is the Scheme
+code implementing a Guix System service, e.g. the OpenSSH server service
+(see @code{openssh-shepherd-service}).
+
+@end table
+
+Modifying the latter results in the recompilation of several dependant
+packages, and it takes too long to be a reasonable edit-compile-test
+cycle.  But starting up a VM that merely uses a customized Shepherd init
+process is a relatively quick operation.
+
+Luckily, not all changes to Shepherd require the recompilation of all
+its dependencies.  The rule of thumb here is that:
+
+@itemize
+
+@item
+if you are making changes to the public API of Shepherd (i.e. anything
+that may have compile-time effects on dependant packages, like adding or
+removing public functions, or changing public macros, etc.), then you
+will need to go through a full recompilation, so that the the Guix
+codebase, and the dependant packages can observe the changes while they
+are being compiled.
+
+@item
+if you're only working on Shepherd's implementation (e.g. making
+Shepherd's error handling more bullet proof), then it's enough to only
+recompile Shepherd itself, and use the resulting package as the one that
+gets started as the init process.
+
+@end itemize
+
+The @ref{Shepherd Services, @code{shepherd-configuration}} section
+documents how you can replace the Shepherd process by specifying a
+custom Shepherd package for an @code{operating-system} object.  To get a
+customized Shepherd package, you can simply make a copy of it in
+@file{gnu/packages/admin.scm}, and change the @code{source} and
+@code{version} field along these lines:
+
+@lisp
+(define-public shepherd-dev-pid-1
+  (package
+    (name "shepherd")
+    (version "dev-pid-1")
+    (source (git-checkout
+             (url "file:///my/path/shepherd/")))
+    ...
+    ))
+@end lisp
+
+To modify and use a new Shepherd API, you can change the @code{source}
+and @code{version} field of the @code{shepherd} package in
+@file{gnu/packages/admin.scm} along these lines:
+
+@lisp
+(define-public shepherd     ; do not change this
+  (package
+    (name "shepherd")
+    (version "dev")
+    (source (git-checkout
+             (url "file:///my/path/shepherd/")
+             (commit "[a commit hash]")))
+    ...
+    ))
+@end lisp
+
+To avoid excessive recompilation times, we pick a specific commit in the
+latter, and only update it as needed.  But the former will pick up any
+newly recorded commit when we issue a @command{guix system vm
+/path/to/my-test.scm}.
+
 @cindex translation
 @cindex l10n
 @cindex i18n
-- 
2.34.0