From 6353f4af51d8a96763672734cc631ad41961b299 Mon Sep 17 00:00:00 2001 From: Arun Isaac Date: Mon, 28 Feb 2022 17:34:41 +0530 Subject: doc: Add Tutorial. * Makefile (doc_snippets): New variable. ($(doc_html)): Depend on $(doc_snippets). * doc/forge.skb: Import (skribilo source lisp). (Tutorial): New chapter. * doc/snippets/tutorial.scm: New file. --- Makefile | 3 +- doc/forge.skb | 96 ++++++++++++++++++++++++++++++++++++++++++++++- doc/snippets/tutorial.scm | 53 ++++++++++++++++++++++++++ 3 files changed, 150 insertions(+), 2 deletions(-) create mode 100644 doc/snippets/tutorial.scm diff --git a/Makefile b/Makefile index 2fe0dd3..ef632bb 100644 --- a/Makefile +++ b/Makefile @@ -24,6 +24,7 @@ sources = $(wildcard forge/*.scm) $(wildcard forge/*/*.scm) doc_skribilo_config = doc/skribilo.scm doc_skribilo_config_go = $(doc_skribilo_config:.scm=.go) doc_sources = doc/forge.skb +doc_snippets = $(wildcard doc/snippets/*.scm) doc_html = $(doc_sources:.skb=.html) .PHONY: all html clean @@ -34,7 +35,7 @@ all: ; html: $(doc_html) -$(doc_html): $(doc_sources) $(sources) $(doc_skribilo_config_go) +$(doc_html): $(doc_sources) $(doc_snippets) $(sources) $(doc_skribilo_config_go) rm -rf $@ mkdir -p $@ GUILE_LOAD_PATH=$(CURDIR):$(GUILE_LOAD_PATH) GUILE_LOAD_COMPILED_PATH=$(CURDIR):$(GUILE_LOAD_COMPILED_PATH) $(SKRIBILO) --target=html $< --output=$@/index.html diff --git a/doc/forge.skb b/doc/forge.skb index ee158e3..b8cb1fe 100644 --- a/doc/forge.skb +++ b/doc/forge.skb @@ -17,7 +17,8 @@ ;;; along with guix-forge. If not, see ;;; . -(use-modules (doc skribilo)) +(use-modules (skribilo source lisp) + (doc skribilo)) (document :title [guix-forge] (toc) @@ -53,6 +54,99 @@ email. guix-forge acknowledges this and prefers to support git's ,(ref :url "https://drewdevault.com/2018/07/02/Email-driven-git.html" :text "email driven workflow") with project discussion, bug reports and patches all happening over email.]))) + (chapter :title [Tutorial] + (p [In this tutorial, you will learn how to set up guix-forge to +host continuous integration for a project. For the purposes of this +tutorial, we will set up continuous integration for the ,(ref :url +[https://github.com/aconchillo/guile-json] :text [guile-json]) +project.]) + (p [First, we clone the upstream guile-json repository into a +local bare clone at ,(file [/srv/git/guile-json]).]) + (prog [$ git clone --bare https://github.com/aconchillo/guile-json /srv/git/guile-json +Cloning into bare repository '/srv/git/guile-json'... +remote: Enumerating objects: 1216, done. +remote: Counting objects: 100% (162/162), done. +remote: Compressing objects: 100% (107/107), done. +remote: Total 1216 (delta 96), reused 106 (delta 54), pack-reused 1054 +Receiving objects: 100% (1216/1216), 276.10 KiB \| 3.89 MiB/s, done. +Resolving deltas: 100% (742/742), done.] + :line #f) + (p [Now that we have a git repository to work with, we start +writing our Guix system configuration. We begin with a bunch of ,(code +[use-modules]) statements importing all required modules.]) + (prog (source :language scheme + :file "doc/snippets/tutorial.scm" + :start 0 :stop 9) + :line #f) + (p [Then, we define the G-expression that will be run as a +continuous integration job on every commit. This G-expression uses +,(code [invoke]) from ,(code [(guix build utils)]). Hence, we make it +available to the G-expression using ,(code +[with-imported-modules]). In addition, it needs a number of packages +which we make available using ,(code [with-packages]). And finally, +within the body of the G-expression, we have commands cloning the git +repository, building the source and running the tests.]) + (prog (source :language scheme + :file "doc/snippets/tutorial.scm" + :start 11 :stop 22) + :line #f) + (p [Now, we configure a ,(code []) record that +holds metadata about the project and wires up the G-expression we just +defined into a continuous integration job.]) + (prog (source :language scheme + :file "doc/snippets/tutorial.scm" + :start 24 :stop 32) + :line #f) + (p [The ,(code [name]) and ,(code [description]) fields are +hopefully self-explanatory. The ,(code [user]) field specifies the +user who will own the git repository at the path specified by ,(code +[repository]). That user will therefore be able to push into the +repository through ssh or similar. The ,(file [post-receive-hook]) in +the repository will be managed by guix-forge to trigger a continuous +integration run on every commit.]) + (p [And finally, we put everything together in an ,(code +[operating-system]) declaration. Notice the forge service configured +with ,(code [guile-json-project]) and the laminar service configured +with a port for the web interface to listen on.]) + (prog (source :language scheme + :file "doc/snippets/tutorial.scm" + :start 34) + :line #f) + (p [Now that we have a complete ,(code [operating-system]) +definition, let's use the following command to build a +container. After a lot of building, a container script should pop +out.]) + (prog [$ guix system container --network --share=/srv/git/guile-json tutorial.scm +/gnu/store/ilg7c2hpkxhwircxpz22qhjsqp3i9har-run-container] + :line #f) + (p [The ,(code [--network]) flag specifies that the container +should share the network namespace of the host. To us, this means that +all ports opened by the container will be visible on the host without +any port forwarding or complicated configuration. The ,(code +[--share=/srv/git/guile-json]) option shares the git repository we +cloned earlier, with the container.]) + (p [To start the container, simply run the container script as +root.]) + (prog [# /gnu/store/ilg7c2hpkxhwircxpz22qhjsqp3i9har-run-container] + :line #f) + (p [Now, you can see the status of laminar and running jobs +through its web interface listening on ,(ref +:url "http://localhost:8080"). You can list and queue jobs on the +command-line like so:]) + (prog [$ laminarc show-jobs +guile-json +$ laminarc queue guile-json +guile-json:1] + :line #f) + (p [That's it! You just set up your own continuous integration +system and took the first steps to owning your code!]) + (p [You could easily use the same configuration to configure a +Guix system instead of a container. To do so, you will have to take +care of defining the bootloader, file systems and other settings as +per your needs. The overall configuration used in this tutorial is +repeated below for your reference.]) + (prog (source :language scheme + :file "doc/snippets/tutorial.scm"))) (chapter :title [Reference] (description (record-documentation "forge/forge.scm" ' diff --git a/doc/snippets/tutorial.scm b/doc/snippets/tutorial.scm new file mode 100644 index 0000000..bbe8575 --- /dev/null +++ b/doc/snippets/tutorial.scm @@ -0,0 +1,53 @@ +(use-modules (gnu) + (gnu packages autotools) + (gnu packages gawk) + (gnu packages guile) + (gnu packages pkg-config) + (gnu packages version-control) + (gnu services ci) + (forge forge) + (forge laminar) + (forge utils)) + +(define guile-json-tests + (with-imported-modules '((guix build utils)) + (with-packages (list autoconf automake coreutils + gawk git-minimal gnu-make grep + guile-3.0 sed pkg-config) + #~(begin + (use-modules (guix build utils)) + (invoke "git" "clone" "/srv/git/guile-json" ".") + (invoke "autoreconf" "--verbose" "--install" "--force") + (invoke "./configure") + (invoke "make") + (invoke "make" "check"))))) + +(define guile-json-project + (forge-project + (name "guile-json") + (user "vetri") + (repository "/srv/git/guile-json") + (description "JSON module for Guile") + (ci-jobs (list (forge-laminar-job + (name "guile-json") + (run guile-json-tests)))))) + +(operating-system + (host-name "tutorial") + (timezone "UTC") + (bootloader (bootloader-configuration + (bootloader grub-bootloader))) + (file-systems %base-file-systems) + (users (cons* (user-account + (name "vetri") + (group "users") + (home-directory "/home/vetri")) + %base-user-accounts)) + (packages %base-packages) + (services (cons* (service forge-service-type + (forge-configuration + (projects (list guile-json-project)))) + (service laminar-service-type + (laminar-configuration + (bind-http "localhost:8080"))) + %base-services))) -- cgit v1.2.3