[PATCH] Gitolite service

DoneSubmitted by Christopher Baines.
Details
4 participants
  • Clément Lassieur
  • Oleg Pykhalov
  • Christopher Baines
  • Nils Gillmann
Owner
unassigned
Severity
normal
C
C
Christopher Baines wrote on 13 Mar 2018 22:35
(address . guix-patches@gnu.org)
87woyfzmir.fsf@cbaines.net
Tags: moreinfo
About a month ago, I managed to write a somewhat working Gitoliteservice. This still needs a bit of work, as the service needs cleaningup, and the documentation writing. I also need to actually try using itfor real, rather than just assuming it'll work because of the systemtest.
Anyway, I haven't got around to doing any of these things in theintervening month, so here is a bug to track adding a Gitolite service,and I'll send the current patches I've got.
-----BEGIN PGP SIGNATURE-----
iQKTBAEBCgB9FiEEPonu50WOcg2XVOCyXiijOwuE9XcFAlqoRDxfFIAAAAAALgAoaXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldDNFODlFRUU3NDU4RTcyMEQ5NzU0RTBCMjVFMjhBMzNCMEI4NEY1NzcACgkQXiijOwuE9XchzxAAnvJ+nsDRzwk0oHCyemWfu9qLdKWxz9eysu0mh755ChGHCYtk41MbJ+QZFLOBjzM7dvJ4Lmv0ctlRpw/7pA5CY10IcvgEzPuDXNhN6UnMAnPBKSxdHnQ2NZI8fYHCvXiU6wHI4e+v/cuY+v7FMhW8ip9vS9Ie6As1v6fmY19Cf239hB3X4KBw59nOgIz+urztxCY6EqIKwauqO3dot515xYGxdMVza+gbWKSuFGEEUXAOT68uU9HazCeD1D8g6ElAJfH+ejcRI2Kl6FbyzmWSGyNH4/ROJVP8YkvuS72oRzntxsZZ1r8MCbxKJSKjffyK2a/X6ra28XnU5wr7/UdfQ6OAQ9sDq849zyCQLo2xQFau1S3czL6Z9Vhi/Fxq+Yv9lvOfT1HzzXvQVamhWxyDvI43q+XbEmKooN15sK9h7081NN0OQC+tFGUqNY/XGLgGtTQMChbB2Q4XA+FxIXuIpH2mcAkC+ZrJY3kp35+qgGGL52TSxTDMKyA+ob6TVNqbXl4cOPaH+Q7FSGdR2bYpXUDteCh4Nc99/+Bz2ORXSjs6uJoe7qamFJjIrrUzwioTHR0o052rFUNuvafySdi7AbaFSSUWlvRsAWeWeeBbY8Y0YUIRa/BGyCiEuh6jmH3GrGk/8wxQNLujzttGhcAl3TY1O4t8d5siFLm4sAFPvas==Pqym-----END PGP SIGNATURE-----
C
C
Christopher Baines wrote on 13 Mar 2018 22:39
[PATCH 2/2] WIP: gitolite package changes to make the service work.
(address . 30809@debbugs.gnu.org)
20180313213933.11268-2-mail@cbaines.net
--- gnu/packages/version-control.scm | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-)
Toggle diff (58 lines)diff --git a/gnu/packages/version-control.scm b/gnu/packages/version-control.scmindex a3f4a4dd4..4af41b37e 100644--- a/gnu/packages/version-control.scm+++ b/gnu/packages/version-control.scm@@ -958,9 +958,9 @@ also walk each side of a merge and test those changes individually.") ;; Avoid references to the store in authorized_keys. ;; This works because gitolite-shell is in the PATH.- (substitute* "src/triggers/post-compile/ssh-authkeys"- (("\\$glshell \\$user")- "gitolite-shell $user"))+ ;; (substitute* "src/triggers/post-compile/ssh-authkeys"+ ;; (("\\$glshell \\$user")+ ;; "gitolite-shell $user")) #t))) (replace 'install (lambda* (#:key outputs #:allow-other-keys)@@ -975,9 +975,36 @@ also walk each side of a merge and test those changes individually.") (symlink (string-append sharedir "/" script) (string-append bindir "/" script))) '("gitolite" "gitolite-shell"))- #t))))))+ #t)))+ (add-after 'install 'wrap-scripts+ (lambda* (#:key inputs outputs #:allow-other-keys)+ (wrap-program (string-append (assoc-ref outputs "out")+ "/share/gitolite/gitolite-shell")+ `("PATH" ":" prefix+ (,(string-append (assoc-ref inputs "git")+ "/bin"))))+ (wrap-program (string-append (assoc-ref outputs "out")+ "/bin/gitolite")+ `("PATH" ":" prefix+ (,(string-append (assoc-ref outputs "out")+ "/bin")+ ,(string-append (assoc-ref inputs "coreutils")+ "/bin")+ ,(string-append (assoc-ref inputs "findutils")+ "/bin")+ ,(string-append (assoc-ref inputs "openssh")+ "/bin")+ ,(string-append (assoc-ref inputs "git")+ "/bin")+ ,(string-append (assoc-ref inputs "inetutils")+ "/bin"))))))))) (inputs- `(("perl" ,perl)))+ `(("perl" ,perl)+ ("git" ,git)+ ("openssh" ,openssh)+ ("coreutils" ,coreutils)+ ("findutils" ,findutils)+ ("inetutils" ,inetutils))) ;; git and openssh are propagated because trying to patch the source via ;; regexp matching is too brittle and prone to false positives. (propagated-inputs-- 2.16.2
C
C
Christopher Baines wrote on 13 Mar 2018 22:39
[PATCH 1/2] services: Add gitolite.
(address . 30809@debbugs.gnu.org)
20180313213933.11268-1-mail@cbaines.net
--- gnu/services/version-control.scm | 158 ++++++++++++++++++++++++++++++++++++++- gnu/tests/version-control.scm | 103 ++++++++++++++++++++++++- 2 files changed, 259 insertions(+), 2 deletions(-)
Toggle diff (300 lines)diff --git a/gnu/services/version-control.scm b/gnu/services/version-control.scmindex afead87ec..60c3f8b81 100644--- a/gnu/services/version-control.scm+++ b/gnu/services/version-control.scm@@ -40,7 +40,23 @@ git-http-configuration git-http-configuration?- git-http-nginx-location-configuration))+ git-http-nginx-location-configuration++ <gitolite-configuration>+ gitolite-configuration+ gitolite-configuration-package+ gitolite-configuration-user+ gitolite-configuration-rc-file+ gitolite-configuration-admin-pubkey++ <gitolite-rc-file>+ gitolite-rc-file+ gitolite-rc-file-umask+ gitolite-rc-file-git-config-keys+ gitolite-rc-file-roles+ gitolite-rc-file-enable++ gitolite-service-type)) ;;; Commentary: ;;;@@ -197,3 +213,143 @@ access to exported repositories under @file{/srv/git}." "") (list "fastcgi_param GIT_PROJECT_ROOT " git-root ";") "fastcgi_param PATH_INFO $1;"))))))++ +;;;+;;; Gitolite+;;;++(define-record-type* <gitolite-rc-file>+ gitolite-rc-file make-gitolite-rc-file+ gitolite-rc-file?+ (umask gitolite-rc-file-umask+ (default #o0077))+ (git-config-keys gitolite-rc-file-git-config-keys+ (default ".*"))+ (roles gitolite-rc-file-roles+ (default '(("READERS" . 1)+ ("WRITERS" . 1))))+ (enable gitolite-rc-file-enable+ (default '("help"+ "desc"+ "info"+ "perms"+ "writable"+ "ssh-authkeys"+ "git-config"+ "daemon"+ "gitweb"))))++(define-gexp-compiler (gitolite-rc-file-compiler+ (file <gitolite-rc-file>) system target)+ (match file+ (($ <gitolite-rc-file> umask git-config-keys roles enable)+ (apply text-file* "gitolite.rc"+ `("%RC = (\n"+ " UMASK => " ,(format #f "~4,'0o" umask) ",\n"+ " GIT_CONFIG_KEYS => '" ,git-config-keys "',\n"+ " ROLES => {\n"+ ,@(map (match-lambda+ ((role . value)+ (simple-format #f " ~A => ~A,\n" role value)))+ roles)+ " },\n"+ "\n"+ " ENABLE => [\n"+ ,@(map (lambda (value)+ (simple-format #f " '~A',\n" value))+ enable)+ " ],\n"+ ");\n"+ "\n"+ "1;\n")))))++(define-record-type* <gitolite-configuration>+ gitolite-configuration make-gitolite-configuration+ gitolite-configuration?+ (package gitolite-configuration-package+ (default gitolite))+ (user gitolite-configuration-user+ (default "git"))+ (rc-file gitolite-configuration-rc-file+ (default (gitolite-rc-file)))+ (admin-pubkey gitolite-configuration-admin-pubkey+ (default #f)))++(define (gitolite-accounts config)+ (let ((user (gitolite-configuration-user config)))+ ;; User group and account to run Gitolite.+ (list (user-group (name user) (system? #t))+ (user-account+ (name user)+ (group user)+ (system? #t)+ (comment "Gitolite daemon user")+ (home-directory "/var/lib/gitolite")))))++(define gitolite-setup+ (match-lambda+ (($ <gitolite-configuration> package user rc-file admin-pubkey)+ #~(begin+ (use-modules (ice-9 match)+ (guix build utils))+ (if (not (file-exists? "/var/lib/gitolite/.gitolite"))+ (let ((user-info (getpwnam #$user)))+ (simple-format #t "guix: gitolite: installing ~A\n"+ #$rc-file)+ (symlink #$rc-file "/var/lib/gitolite/.gitolite.rc")++ ;; The key must be writable, so copy it from the store+ (copy-file #$admin-pubkey "/var/lib/gitolite/id_rsa.pub")++ (chmod "/var/lib/gitolite/id_rsa.pub" #o500)+ (chown "/var/lib/gitolite/id_rsa.pub"+ (passwd:uid user-info)+ (passwd:gid user-info))++ ;; Set the git configuration, to avoid gitolite trying to use+ ;; the hostname command, as the network might not be up yet+ (with-output-to-file "/var/lib/gitolite/.gitconfig"+ (lambda ()+ (display "[user]+ name = GNU Guix+ email = guix@localhost+")))++ (match (primitive-fork)+ (0+ ;; Exit with a non-zero status code if an exception is thrown.+ (dynamic-wind+ (const #t)+ (lambda ()+ (setenv "HOME" (passwd:dir user-info))+ (setenv "USER" #$user)+ (setgid (passwd:gid user-info))+ (setuid (passwd:uid user-info))+ (primitive-exit+ (system* #$(file-append package "/bin/gitolite")+ "setup"+ "-pk" "/var/lib/gitolite/id_rsa.pub")))+ (lambda ()+ (primitive-exit 1))))+ (pid (waitpid pid)))++ (delete-file "/var/lib/gitolite/id_rsa.pub")))))))++(define (gitolite-activation config)+ (if (gitolite-configuration-admin-pubkey config)+ (gitolite-setup config)+ #~(display+ "guix: Skipping gitolite setup as the admin-pubkey has not been provided\n")))++(define gitolite-service-type+ (service-type+ (name 'gitolite)+ (extensions+ (list (service-extension activation-service-type+ gitolite-activation)+ (service-extension account-service-type+ gitolite-accounts)))+ (default-value (gitolite-configuration))+ (description+ "")))diff --git a/gnu/tests/version-control.scm b/gnu/tests/version-control.scmindex 802473973..c6dc0457c 100644--- a/gnu/tests/version-control.scm+++ b/gnu/tests/version-control.scm@@ -27,14 +27,17 @@ #:use-module (gnu services) #:use-module (gnu services version-control) #:use-module (gnu services cgit)+ #:use-module (gnu services ssh) #:use-module (gnu services web) #:use-module (gnu services networking) #:use-module (gnu packages version-control)+ #:use-module (gnu packages ssh) #:use-module (guix gexp) #:use-module (guix store) #:use-module (guix modules) #:export (%test-cgit- %test-git-http))+ %test-git-http+ %test-gitolite)) (define README-contents "Hello! This is what goes inside the 'README' file.")@@ -306,3 +309,101 @@ HTTP-PORT." (name "git-http") (description "Connect to a running Git HTTP server.") (value (run-git-http-test))))++ +;;;+;;; Gitolite.+;;;++(define %gitolite-test-admin-keypair+ (computed-file+ "gitolite-test-admin-keypair"+ (with-imported-modules (source-module-closure+ '((guix build utils)))+ #~(begin+ (use-modules (ice-9 match) (srfi srfi-26)+ (guix build utils))++ (mkdir #$output)+ (invoke #$(file-append openssh "/bin/ssh-keygen")+ "-f" (string-append #$output "/id_rsa")+ "-t" "rsa"+ "-q"+ "-N" "")))))++(define %gitolite-os+ (simple-operating-system+ (dhcp-client-service)+ (service openssh-service-type)+ (service gitolite-service-type+ (gitolite-configuration+ (admin-pubkey+ (file-append %gitolite-test-admin-keypair "/id_rsa.pub"))))))++(define (run-gitolite-test)+ (define os+ (marionette-operating-system+ %gitolite-os+ #:imported-modules '((gnu services herd)+ (guix combinators))))++ (define vm+ (virtual-machine+ (operating-system os)+ (port-forwardings `((2222 . 22)))))++ (define test+ (with-imported-modules '((gnu build marionette)+ (guix build utils))+ #~(begin+ (use-modules (srfi srfi-64)+ (rnrs io ports)+ (gnu build marionette)+ (guix build utils))++ (define marionette+ (make-marionette (list #$vm)))++ (mkdir #$output)+ (chdir #$output)++ (test-begin "gitolite")++ ;; Wait for sshd to be up and running.+ (test-eq "service running"+ 'running!+ (marionette-eval+ '(begin+ (use-modules (gnu services herd))+ (start-service 'ssh-daemon)+ 'running!)+ marionette))++ (display #$%gitolite-test-admin-keypair)++ (setenv "GIT_SSH_VARIANT" "ssh")+ (setenv "GIT_SSH_COMMAND"+ (string-join+ '(#$(file-append openssh "/bin/ssh")+ "-i" #$(file-append %gitolite-test-admin-keypair "/id_rsa")+ "-o" "UserKnownHostsFile=/dev/null"+ "-o" "StrictHostKeyChecking=no")))++ ;; Make sure we can clone the repo from the host.+ (test-eq "clone"+ #t+ (invoke #$(file-append git "/bin/git")+ "clone" "-v"+ "ssh://git@localhost:2222/gitolite-admin"+ "/tmp/clone"))++ (test-end)+ (exit (= (test-runner-fail-count (test-runner-current)) 0)))))++ (gexp->derivation "gitolite" test))++(define %test-gitolite+ (system-test+ (name "gitolite")+ (description "Connect to a running Git HTTP server.")+ (value (run-gitolite-test))))-- 2.16.2
C
C
Christopher Baines wrote on 13 Jul 2018 21:41
[PATCH 2/2] services: Add Gitolite.
(address . 30809@debbugs.gnu.org)
20180713194101.14891-2-mail@cbaines.net
* gnu/services/version-control.scm (<gitolite-configuration>,<gitolite-rc-file>): New record types.(gitolite-accounts, gitolite-setup, gitolite-activation): New procedures.(gitolite-service-type): New variables.* gnu/tests/version-control.scm (%gitolite-test-admin-keypair, %gitolite-os,%test-gitolite): New variables.(run-gitolite-test): New procedure.* doc/guix.texi (Version Control): Document the gitolite service.--- doc/guix.texi | 91 +++++++++++++++++ gnu/services/version-control.scm | 169 ++++++++++++++++++++++++++++++- gnu/tests/version-control.scm | 103 ++++++++++++++++++- 3 files changed, 361 insertions(+), 2 deletions(-)
Toggle diff (413 lines)diff --git a/doc/guix.texi b/doc/guix.texiindex 7ce364b0a..a54dd6800 100644--- a/doc/guix.texi+++ b/doc/guix.texi@@ -20127,6 +20127,97 @@ could instantiate a cgit service like this: (cgitrc ""))) @end example +@subsubheading Gitolite Service++@cindex Gitolite service+@cindex Git, hosting+@uref{http://gitolite.com/gitolite/, Gitolite} is a tool for hosting Git+repositories on a central server.++Gitolite can handle multiple repositories and users, and supports flexible+configuration of the permissions for the users on the repositories.++The following example will configure Gitolite using the default @code{git}+user, and the SSH public key located at @code{~/.ssh/id_rsa.pub}. A public key+is necessary to setup Gitolite initially, but can be omitted once Gitolite is+setup.++@example+(service gitolite-service-type+ (gitolite-configuration+ (admin-pubkey (plain-file+ "id_rsa.pub"+ "ssh-rsa AAAA... guix@@example.com"))))+@end example++Gitolite is configured through a special admin repository which you can clone,+for example, if you setup Gitolite on @code{example.com}, you would run the+following command to clone the admin repository.++@example+git clone git@@example.com:gitolite-admin+@end example++@deftp {Data Type} gitolite-configuration+Data type representing the configuration for @code{gitolite-service-type}.++@table @asis+@item @code{package} (default: @var{gitolite})+Gitolite package to use.++@item @code{user} (default: @var{git})+User to use for Gitolite. This will be user that you use when accessing+Gitolite over SSH.++@item @code{rc-file} (default: @var{(gitolite-rc-file)})+A ``file-like'' object (@pxref{G-Expressions, file-like objects}),+representing the configuration for Gitolite.++@item @code{admin-pubkey} (default: @var{#f})+A ``file-like'' object (@pxref{G-Expressions, file-like objects}) used to+setup Gitolite. This can be omitted once Gitolite has successfully been+setup.++The following G-exp would use the @file{~/.ssh/id_rsa.pub} file.++@example+(local-file "~/.ssh/id_rsa.pub")+@end example++To specify the SSH key as a string, use the @code{plain-file} function.++@example+(plain-file "id_rsa.pub" "ssh-rsa AAAA... guix@@example.com")+@end example++@end table+@end deftp++@deftp {Data Type} gitolite-rc-file+Data type representing the Gitolite RC file.++@table @asis+@item @code{umask} (default: @code{#o0077})+This controls the permissions Gitolite sets on the repositories and their+contents.++A value like @code{#o0027} will give read access to the group used by Gitolite+(by default: @code{git}). This is necessary when using Gitolite with software+like cgit or gitweb.++@item @code{git-config-keys} (default: @code{""})+Gitolite allows you to set git config values using the "config" keyword. This+setting allows control over the config keys to accept.++@item @code{roles} (default: @code{'(("READERS" . 1) ("WRITERS" . ))})+Set the role names allowed to be used by users running the perms command.++@item @code{enable} (default: @code{'("help" "desc" "info" "perms" "writable" "ssh-authkeys" "git-config" "daemon" "gitweb")})+This setting controls the commands and features to enable within Gitolite.++@end table+@end deftp+ @node Game Services @subsubsection Game Servicesdiff --git a/gnu/services/version-control.scm b/gnu/services/version-control.scmindex 58274c8be..1000207ed 100644--- a/gnu/services/version-control.scm+++ b/gnu/services/version-control.scm@@ -40,7 +40,23 @@ git-http-configuration git-http-configuration?- git-http-nginx-location-configuration))+ git-http-nginx-location-configuration++ <gitolite-configuration>+ gitolite-configuration+ gitolite-configuration-package+ gitolite-configuration-user+ gitolite-configuration-rc-file+ gitolite-configuration-admin-pubkey++ <gitolite-rc-file>+ gitolite-rc-file+ gitolite-rc-file-umask+ gitolite-rc-file-git-config-keys+ gitolite-rc-file-roles+ gitolite-rc-file-enable++ gitolite-service-type)) ;;; Commentary: ;;;@@ -197,3 +213,154 @@ access to exported repositories under @file{/srv/git}." "") (list "fastcgi_param GIT_PROJECT_ROOT " git-root ";") "fastcgi_param PATH_INFO $1;"))))))++ +;;;+;;; Gitolite+;;;++(define-record-type* <gitolite-rc-file>+ gitolite-rc-file make-gitolite-rc-file+ gitolite-rc-file?+ (umask gitolite-rc-file-umask+ (default #o0077))+ (git-config-keys gitolite-rc-file-git-config-keys+ (default ""))+ (roles gitolite-rc-file-roles+ (default '(("READERS" . 1)+ ("WRITERS" . 1))))+ (enable gitolite-rc-file-enable+ (default '("help"+ "desc"+ "info"+ "perms"+ "writable"+ "ssh-authkeys"+ "git-config"+ "daemon"+ "gitweb"))))++(define-gexp-compiler (gitolite-rc-file-compiler+ (file <gitolite-rc-file>) system target)+ (match file+ (($ <gitolite-rc-file> umask git-config-keys roles enable)+ (apply text-file* "gitolite.rc"+ `("%RC = (\n"+ " UMASK => " ,(format #f "~4,'0o" umask) ",\n"+ " GIT_CONFIG_KEYS => '" ,git-config-keys "',\n"+ " ROLES => {\n"+ ,@(map (match-lambda+ ((role . value)+ (simple-format #f " ~A => ~A,\n" role value)))+ roles)+ " },\n"+ "\n"+ " ENABLE => [\n"+ ,@(map (lambda (value)+ (simple-format #f " '~A',\n" value))+ enable)+ " ],\n"+ ");\n"+ "\n"+ "1;\n")))))++(define-record-type* <gitolite-configuration>+ gitolite-configuration make-gitolite-configuration+ gitolite-configuration?+ (package gitolite-configuration-package+ (default gitolite))+ (user gitolite-configuration-user+ (default "git"))+ (rc-file gitolite-configuration-rc-file+ (default (gitolite-rc-file)))+ (admin-pubkey gitolite-configuration-admin-pubkey+ (default #f)))++(define (gitolite-accounts config)+ (let ((user (gitolite-configuration-user config)))+ ;; User group and account to run Gitolite.+ (list (user-group (name user) (system? #t))+ (user-account+ (name user)+ (group user)+ (system? #t)+ (comment "Gitolite user")+ (home-directory "/var/lib/gitolite")))))++(define gitolite-setup+ (match-lambda+ (($ <gitolite-configuration> package user rc-file admin-pubkey)+ #~(begin+ (use-modules (ice-9 match)+ (guix build utils))+ (if (not (file-exists? "/var/lib/gitolite/.gitolite"))+ (let ((user-info (getpwnam #$user)))+ (simple-format #t "guix: gitolite: installing ~A\n"+ #$rc-file)+ (symlink #$rc-file "/var/lib/gitolite/.gitolite.rc")++ ;; The key must be writable, so copy it from the store+ (copy-file #$admin-pubkey "/var/lib/gitolite/id_rsa.pub")++ (chmod "/var/lib/gitolite/id_rsa.pub" #o500)+ (chown "/var/lib/gitolite/id_rsa.pub"+ (passwd:uid user-info)+ (passwd:gid user-info))++ ;; Set the git configuration, to avoid gitolite trying to use+ ;; the hostname command, as the network might not be up yet+ (with-output-to-file "/var/lib/gitolite/.gitconfig"+ (lambda ()+ (display "[user]+ name = GNU Guix+ email = guix@localhost+")))++ (match (primitive-fork)+ (0+ ;; Exit with a non-zero status code if an exception is thrown.+ (dynamic-wind+ (const #t)+ (lambda ()+ (setenv "HOME" (passwd:dir user-info))+ (setenv "USER" #$user)+ (setgid (passwd:gid user-info))+ (setuid (passwd:uid user-info))+ (primitive-exit+ (system* #$(file-append package "/bin/gitolite")+ "setup"+ "-pk" "/var/lib/gitolite/id_rsa.pub")))+ (lambda ()+ (primitive-exit 1))))+ (pid (waitpid pid)))++ (delete-file "/var/lib/gitolite/id_rsa.pub")))))))++(define (gitolite-activation config)+ (if (gitolite-configuration-admin-pubkey config)+ (gitolite-setup config)+ #~(display+ "guix: Skipping gitolite setup as the admin-pubkey has not been provided\n")))++(define gitolite-service-type+ (service-type+ (name 'gitolite)+ (extensions+ (list (service-extension activation-service-type+ gitolite-activation)+ (service-extension account-service-type+ gitolite-accounts)+ (service-extension profile-service-type+ ;; The Gitolite package in Guix uses+ ;; gitolite-shell in the authorized_keys file, so+ ;; gitolite-shell needs to be on the PATH for+ ;; gitolite to work.+ (lambda (config)+ (list+ (gitolite-configuration-package config))))))+ (default-value (gitolite-configuration))+ (description+ "Setup @command{gitolite}, a Git hosting tool providing access over SSH..+By default, the @code{git} user is used, but this is configurable.+Additionally, Gitolite can integrate with with tools like gitweb or cgit to+provide a web interface to view selected repositories.")))diff --git a/gnu/tests/version-control.scm b/gnu/tests/version-control.scmindex 3b935a1b4..e4cd3fc3f 100644--- a/gnu/tests/version-control.scm+++ b/gnu/tests/version-control.scm@@ -27,14 +27,17 @@ #:use-module (gnu services) #:use-module (gnu services version-control) #:use-module (gnu services cgit)+ #:use-module (gnu services ssh) #:use-module (gnu services web) #:use-module (gnu services networking) #:use-module (gnu packages version-control)+ #:use-module (gnu packages ssh) #:use-module (guix gexp) #:use-module (guix store) #:use-module (guix modules) #:export (%test-cgit- %test-git-http))+ %test-git-http+ %test-gitolite)) (define README-contents "Hello! This is what goes inside the 'README' file.")@@ -300,3 +303,101 @@ HTTP-PORT." (name "git-http") (description "Connect to a running Git HTTP server.") (value (run-git-http-test))))++ +;;;+;;; Gitolite.+;;;++(define %gitolite-test-admin-keypair+ (computed-file+ "gitolite-test-admin-keypair"+ (with-imported-modules (source-module-closure+ '((guix build utils)))+ #~(begin+ (use-modules (ice-9 match) (srfi srfi-26)+ (guix build utils))++ (mkdir #$output)+ (invoke #$(file-append openssh "/bin/ssh-keygen")+ "-f" (string-append #$output "/id_rsa")+ "-t" "rsa"+ "-q"+ "-N" "")))))++(define %gitolite-os+ (simple-operating-system+ (dhcp-client-service)+ (service openssh-service-type)+ (service gitolite-service-type+ (gitolite-configuration+ (admin-pubkey+ (file-append %gitolite-test-admin-keypair "/id_rsa.pub"))))))++(define (run-gitolite-test)+ (define os+ (marionette-operating-system+ %gitolite-os+ #:imported-modules '((gnu services herd)+ (guix combinators))))++ (define vm+ (virtual-machine+ (operating-system os)+ (port-forwardings `((2222 . 22)))))++ (define test+ (with-imported-modules '((gnu build marionette)+ (guix build utils))+ #~(begin+ (use-modules (srfi srfi-64)+ (rnrs io ports)+ (gnu build marionette)+ (guix build utils))++ (define marionette+ (make-marionette (list #$vm)))++ (mkdir #$output)+ (chdir #$output)++ (test-begin "gitolite")++ ;; Wait for sshd to be up and running.+ (test-eq "service running"+ 'running!+ (marionette-eval+ '(begin+ (use-modules (gnu services herd))+ (start-service 'ssh-daemon)+ 'running!)+ marionette))++ (display #$%gitolite-test-admin-keypair)++ (setenv "GIT_SSH_VARIANT" "ssh")+ (setenv "GIT_SSH_COMMAND"+ (string-join+ '(#$(file-append openssh "/bin/ssh")+ "-i" #$(file-append %gitolite-test-admin-keypair "/id_rsa")+ "-o" "UserKnownHostsFile=/dev/null"+ "-o" "StrictHostKeyChecking=no")))++ ;; Make sure we can clone the repo from the host.+ (test-eq "clone"+ #t+ (invoke #$(file-append git "/bin/git")+ "clone" "-v"+ "ssh://git@localhost:2222/gitolite-admin"+ "/tmp/clone"))++ (test-end)+ (exit (= (test-runner-fail-count (test-runner-current)) 0)))))++ (gexp->derivation "gitolite" test))++(define %test-gitolite+ (system-test+ (name "gitolite")+ (description "Clone the Gitolite admin repository.")+ (value (run-gitolite-test))))-- 2.17.1
C
C
Christopher Baines wrote on 13 Jul 2018 21:41
[PATCH 1/2] gnu: Modify the gitolite package to support the Guix service.
(address . 30809@debbugs.gnu.org)
20180713194101.14891-1-mail@cbaines.net
Previously the gitolite package worked, but there were problems using it forthe service where you might have a minimal PATH. This commit patches thesource and scripts where possible to use store paths, and also wraps thegitolite script to handle the harder dependencies.
* gnu/packages/version-control.scm (gitolite)[arguments]: Add more patching tothe patch-scripts phase, and add two new phases (patch-source andwrap-scripts).[inputs]: Add coreutils, findutils and inetutils.--- gnu/packages/version-control.scm | 53 ++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-)
Toggle diff (80 lines)diff --git a/gnu/packages/version-control.scm b/gnu/packages/version-control.scmindex 2bd59ae95..3bbc586e1 100644--- a/gnu/packages/version-control.scm+++ b/gnu/packages/version-control.scm@@ -1026,12 +1026,42 @@ also walk each side of a merge and test those changes individually.") ((" perl -") (string-append " " perl " -"))) + (substitute* (find-files "src/triggers" ".*")+ ((" sed ")+ (string-append " " (which "sed") " ")))++ (substitute*+ '("src/triggers/post-compile/update-gitweb-access-list"+ "src/triggers/post-compile/ssh-authkeys-split"+ "src/triggers/upstream")+ ((" grep ")+ (string-append " " (which "grep") " ")))+ ;; Avoid references to the store in authorized_keys. ;; This works because gitolite-shell is in the PATH. (substitute* "src/triggers/post-compile/ssh-authkeys" (("\\$glshell \\$user") "gitolite-shell $user")) #t)))+ (add-before 'install 'patch-source+ (lambda* (#:key inputs #:allow-other-keys)+ ;; Gitolite uses cat to test the readability of the+ ;; pubkey+ (substitute* "src/lib/Gitolite/Setup.pm"+ (("\"cat ")+ (string-append "\"" (which "cat") " "))+ (("\"ssh-keygen")+ (string-append "\"" (which "ssh-keygen"))))++ (substitute* "src/lib/Gitolite/Common.pm"+ (("\"ssh-keygen")+ (string-append "\"" (which "ssh-keygen")))+ (("\"logger\"")+ (string-append "\""+ (assoc-ref inputs "inetutils")+ "/bin/logger\"")))++ #t)) (replace 'install (lambda* (#:key outputs #:allow-other-keys) (let* ((output (assoc-ref outputs "out"))@@ -1045,9 +1075,28 @@ also walk each side of a merge and test those changes individually.") (symlink (string-append sharedir "/" script) (string-append bindir "/" script))) '("gitolite" "gitolite-shell"))- #t))))))+ #t)))+ (add-after 'install 'wrap-scripts+ (lambda* (#:key inputs outputs #:allow-other-keys)+ (wrap-program (string-append (assoc-ref outputs "out")+ "/bin/gitolite")+ `("PATH" ":" prefix+ (,(string-append (assoc-ref outputs "out")+ "/bin")+ ,(string-append (assoc-ref inputs "coreutils")+ "/bin")+ ;; find is used in quite a few places+ ,(string-append (assoc-ref inputs "findutils")+ "/bin")+ ,(string-append (assoc-ref inputs "git")+ "/bin"))))++ #t))))) (inputs- `(("perl" ,perl)))+ `(("perl" ,perl)+ ("coreutils" ,coreutils)+ ("findutils" ,findutils)+ ("inetutils" ,inetutils))) ;; git and openssh are propagated because trying to patch the source via ;; regexp matching is too brittle and prone to false positives. (propagated-inputs-- 2.17.1
C
C
Christopher Baines wrote on 13 Jul 2018 22:01
Fwd: [bug#30809] [PATCH 2/2] services: Add Gitolite.
(address . 30809@debbugs.gnu.org)
87zhyuewgz.fsf@cbaines.net
Christopher Baines <mail@cbaines.net> writes:
Toggle quote (14 lines)> * gnu/services/version-control.scm (<gitolite-configuration>,> <gitolite-rc-file>): New record types.> (gitolite-accounts, gitolite-setup, gitolite-activation): New procedures.> (gitolite-service-type): New variables.> * gnu/tests/version-control.scm (%gitolite-test-admin-keypair, %gitolite-os,> %test-gitolite): New variables.> (run-gitolite-test): New procedure.> * doc/guix.texi (Version Control): Document the gitolite service.> ---> doc/guix.texi | 91 +++++++++++++++++> gnu/services/version-control.scm | 169 ++++++++++++++++++++++++++++++-> gnu/tests/version-control.scm | 103 ++++++++++++++++++-> 3 files changed, 361 insertions(+), 2 deletions(-)
So, this patch has been sitting around for a while, but I've got aroundto writing some docs now, and making the service compatible with thepackage, and I think it's ready.
I've CC'ed both David and Clément, as I see you've been involved inpackaging Gitolite before, so maybe this will interest you.
-----BEGIN PGP SIGNATURE-----
iQKTBAEBCgB9FiEEPonu50WOcg2XVOCyXiijOwuE9XcFAltJBR1fFIAAAAAALgAoaXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldDNFODlFRUU3NDU4RTcyMEQ5NzU0RTBCMjVFMjhBMzNCMEI4NEY1NzcACgkQXiijOwuE9XdQ1g//cX/8vFbSlNhf+M/JD3HdAMHf9A5lVz9OOmXHXMNbjFSzfB4gCEkGws/tB3tV2DcbIysezItqEe9SDyVSa/5DBevJ+uplsbRMSdFto1bOcCijPROjNExHznXlcGWLX4cvl7ZujmF5UnkZ0QpHTgT3/RmhpCuGdoHsdIRDMWCKo5I/fyKz+UgJxvlKdIcqIKfctX1sjLQxIfc2ZicpdffhUcAvQJIeqsIL9Q+4BcgEK29d27EDsYKZhS8A6mKboyFviUloeZZLw98J6hz8rFnfqlnAcm1Ea8/SKMPVUbuBb15L2NYam6LbP3WEhRuOS5IJucYdFgceBUaRV/VMhGbyVVCaj1AFl9V+qMluLFOY431782aRRiNSLoYpizQ6hbVZq9iAFCcafLOS8jEkZ7ixb5Jg63Dr64W1LKnEUMolVK0ryTHYHscJjrmOIbWXWOKqfSGAZKU3p5eYfft0ioSli6HSrzIW/a7i8Tq7Y0Ovk9StewtD63ivGBeWuuowvL/vgAIwic/nGY0vFySbUy87RixwonVhhJS0y4n8G9aI+HLTzwX4CV0WbpGPddiV/LaCKjziXjmxWFaV65a6udx2dgsSNzEmGmxlNhDIn3s6+UOxr+5oBh9fYLgBBWFiH/a8MHSKfbI2SZ0I8YesMDlyWMmWOPyeBHOC2fz0RWutW/k==mJzs-----END PGP SIGNATURE-----
O
O
Oleg Pykhalov wrote on 14 Jul 2018 01:15
Re: [bug#30809] [PATCH 2/2] services: Add Gitolite.
(name . Christopher Baines)(address . mail@cbaines.net)(address . 30809@debbugs.gnu.org)
87wotyg226.fsf@gmail.com
Hello Christopher,
Not a full review, just want to note issue in the documentation and saythank you. The gitolite service works for me.
Christopher Baines <mail@cbaines.net> writes:
Toggle quote (14 lines)> * gnu/services/version-control.scm (<gitolite-configuration>,> <gitolite-rc-file>): New record types.> (gitolite-accounts, gitolite-setup, gitolite-activation): New procedures.> (gitolite-service-type): New variables.> * gnu/tests/version-control.scm (%gitolite-test-admin-keypair, %gitolite-os,> %test-gitolite): New variables.> (run-gitolite-test): New procedure.> * doc/guix.texi (Version Control): Document the gitolite service.> ---> doc/guix.texi | 91 +++++++++++++++++> gnu/services/version-control.scm | 169 ++++++++++++++++++++++++++++++-> gnu/tests/version-control.scm | 103 ++++++++++++++++++-> 3 files changed, 361 insertions(+), 2 deletions(-)
[…]
Toggle quote (6 lines)> +The following G-exp would use the @file{~/.ssh/id_rsa.pub} file.> +> +@example> +(local-file "~/.ssh/id_rsa.pub")> +@end example
‘~/.ssh/id_rsa.pub’ doesn't work for me, because with ‘./pre-inst-envguix system vm ./test.scm’ it will be expanded to‘/home/natsu/src/guix/~/.ssh/id_rsa.pub’.
Specifing full path ‘/home/natsu/.ssh/id_rsa.pub’ is required for me.
[…]
Oleg.
-----BEGIN PGP SIGNATURE-----
iQIzBAEBCgAdFiEEc+OyAXw1EaDPCmAPckbhHGm3lWkFAltJMpEACgkQckbhHGm3lWk9OxAAyUre6UB2LbiZ7qZDBeyp3CM2ksu/7S43MELrfEUmyEFN2xNJzzCfdGN0SSBnjqRZ7BMD6fzLQ3Q5Q7qruLLmoc6B+dbFhOKw2JtndMuwvIJXgRemIBFsL8TRgM/gn2wdZmScG73Hk7b7MWrtOj6w+b/88AnUz7WxmAGBeKhw+2B6d88z+htp1/6li1w9PActkZaJlJSElx7+76kCrfYs7oYImLLSyYMCki8jr/Fz56+Av4vh9kWfDf3dAjH8BoZXr/5JhyxNAj0KPDBTzqoiWYzhLw6o2CH8/pvJrYzT7X6t0LO89f5q5NLSw7XOGMAxXHW5HYyNo28oyRZZWkRnBfqwrGF7nGvdsUgeEy3e4DC8ekDMKUHJ+Bw2XV2AH2pqaGZSqgDhqm1b5XEyaf7YB0k0VBqn8blYwJl3aZE8a0uYuQIvCYpIi/kKtcoPm0goWG2l1b6K/eHeXWee+zF+dpxYO4gJGddzB1eSx4Y6XDrbTZvTEhPuoDHGSFt/jkQfp/zJWEahBxXZiX0Lnj9+ShuKlGBFK/NDDNMmHMEIfXfvLR/YqaHBcpGRSw/VVC6vMFjuQzFpbuDmBV7x/kCuJgTqgSlOiGU4G9Lg5KH5mFe+DRE05rPiatYXNgnFhQmjYimJ9SQqlUGenNxHpsVAUAH+rt7/cWhR/GBKkJ7KNmI==R9cx-----END PGP SIGNATURE-----
C
C
Christopher Baines wrote on 14 Jul 2018 08:28
[PATCH 2/2] services: Add Gitolite.
(address . 30809@debbugs.gnu.org)
20180714062855.18705-2-mail@cbaines.net
* gnu/services/version-control.scm (<gitolite-configuration>,<gitolite-rc-file>): New record types.(gitolite-accounts, gitolite-setup, gitolite-activation): New procedures.(gitolite-service-type): New variables.* gnu/tests/version-control.scm (%gitolite-test-admin-keypair, %gitolite-os,%test-gitolite): New variables.(run-gitolite-test): New procedure.* doc/guix.texi (Version Control): Document the gitolite service.--- doc/guix.texi | 90 ++++++++++++++++ gnu/services/version-control.scm | 169 ++++++++++++++++++++++++++++++- gnu/tests/version-control.scm | 103 ++++++++++++++++++- 3 files changed, 360 insertions(+), 2 deletions(-)
Toggle diff (412 lines)diff --git a/doc/guix.texi b/doc/guix.texiindex 7ce364b0a..b43f43bb9 100644--- a/doc/guix.texi+++ b/doc/guix.texi@@ -20127,6 +20127,96 @@ could instantiate a cgit service like this: (cgitrc ""))) @end example +@subsubheading Gitolite Service++@cindex Gitolite service+@cindex Git, hosting+@uref{http://gitolite.com/gitolite/, Gitolite} is a tool for hosting Git+repositories on a central server.++Gitolite can handle multiple repositories and users, and supports flexible+configuration of the permissions for the users on the repositories.++The following example will configure Gitolite using the default @code{git}+user, and the provided SSH public key. A public key is necessary to setup+Gitolite initially, but can be omitted once Gitolite is setup.++@example+(service gitolite-service-type+ (gitolite-configuration+ (admin-pubkey (plain-file+ "id_rsa.pub"+ "ssh-rsa AAAA... guix@@example.com"))))+@end example++Gitolite is configured through a special admin repository which you can clone,+for example, if you setup Gitolite on @code{example.com}, you would run the+following command to clone the admin repository.++@example+git clone git@@example.com:gitolite-admin+@end example++@deftp {Data Type} gitolite-configuration+Data type representing the configuration for @code{gitolite-service-type}.++@table @asis+@item @code{package} (default: @var{gitolite})+Gitolite package to use.++@item @code{user} (default: @var{git})+User to use for Gitolite. This will be user that you use when accessing+Gitolite over SSH.++@item @code{rc-file} (default: @var{(gitolite-rc-file)})+A ``file-like'' object (@pxref{G-Expressions, file-like objects}),+representing the configuration for Gitolite.++@item @code{admin-pubkey} (default: @var{#f})+A ``file-like'' object (@pxref{G-Expressions, file-like objects}) used to+setup Gitolite. This can be omitted once Gitolite has successfully been+setup.++The following G-exp would use the @file{/home/user/.ssh/id_rsa.pub} file.++@example+(local-file "/home/user/.ssh/id_rsa.pub")+@end example++To specify the SSH key as a string, use the @code{plain-file} function.++@example+(plain-file "id_rsa.pub" "ssh-rsa AAAA... guix@@example.com")+@end example++@end table+@end deftp++@deftp {Data Type} gitolite-rc-file+Data type representing the Gitolite RC file.++@table @asis+@item @code{umask} (default: @code{#o0077})+This controls the permissions Gitolite sets on the repositories and their+contents.++A value like @code{#o0027} will give read access to the group used by Gitolite+(by default: @code{git}). This is necessary when using Gitolite with software+like cgit or gitweb.++@item @code{git-config-keys} (default: @code{""})+Gitolite allows you to set git config values using the "config" keyword. This+setting allows control over the config keys to accept.++@item @code{roles} (default: @code{'(("READERS" . 1) ("WRITERS" . ))})+Set the role names allowed to be used by users running the perms command.++@item @code{enable} (default: @code{'("help" "desc" "info" "perms" "writable" "ssh-authkeys" "git-config" "daemon" "gitweb")})+This setting controls the commands and features to enable within Gitolite.++@end table+@end deftp+ @node Game Services @subsubsection Game Servicesdiff --git a/gnu/services/version-control.scm b/gnu/services/version-control.scmindex 58274c8be..1000207ed 100644--- a/gnu/services/version-control.scm+++ b/gnu/services/version-control.scm@@ -40,7 +40,23 @@ git-http-configuration git-http-configuration?- git-http-nginx-location-configuration))+ git-http-nginx-location-configuration++ <gitolite-configuration>+ gitolite-configuration+ gitolite-configuration-package+ gitolite-configuration-user+ gitolite-configuration-rc-file+ gitolite-configuration-admin-pubkey++ <gitolite-rc-file>+ gitolite-rc-file+ gitolite-rc-file-umask+ gitolite-rc-file-git-config-keys+ gitolite-rc-file-roles+ gitolite-rc-file-enable++ gitolite-service-type)) ;;; Commentary: ;;;@@ -197,3 +213,154 @@ access to exported repositories under @file{/srv/git}." "") (list "fastcgi_param GIT_PROJECT_ROOT " git-root ";") "fastcgi_param PATH_INFO $1;"))))))++ +;;;+;;; Gitolite+;;;++(define-record-type* <gitolite-rc-file>+ gitolite-rc-file make-gitolite-rc-file+ gitolite-rc-file?+ (umask gitolite-rc-file-umask+ (default #o0077))+ (git-config-keys gitolite-rc-file-git-config-keys+ (default ""))+ (roles gitolite-rc-file-roles+ (default '(("READERS" . 1)+ ("WRITERS" . 1))))+ (enable gitolite-rc-file-enable+ (default '("help"+ "desc"+ "info"+ "perms"+ "writable"+ "ssh-authkeys"+ "git-config"+ "daemon"+ "gitweb"))))++(define-gexp-compiler (gitolite-rc-file-compiler+ (file <gitolite-rc-file>) system target)+ (match file+ (($ <gitolite-rc-file> umask git-config-keys roles enable)+ (apply text-file* "gitolite.rc"+ `("%RC = (\n"+ " UMASK => " ,(format #f "~4,'0o" umask) ",\n"+ " GIT_CONFIG_KEYS => '" ,git-config-keys "',\n"+ " ROLES => {\n"+ ,@(map (match-lambda+ ((role . value)+ (simple-format #f " ~A => ~A,\n" role value)))+ roles)+ " },\n"+ "\n"+ " ENABLE => [\n"+ ,@(map (lambda (value)+ (simple-format #f " '~A',\n" value))+ enable)+ " ],\n"+ ");\n"+ "\n"+ "1;\n")))))++(define-record-type* <gitolite-configuration>+ gitolite-configuration make-gitolite-configuration+ gitolite-configuration?+ (package gitolite-configuration-package+ (default gitolite))+ (user gitolite-configuration-user+ (default "git"))+ (rc-file gitolite-configuration-rc-file+ (default (gitolite-rc-file)))+ (admin-pubkey gitolite-configuration-admin-pubkey+ (default #f)))++(define (gitolite-accounts config)+ (let ((user (gitolite-configuration-user config)))+ ;; User group and account to run Gitolite.+ (list (user-group (name user) (system? #t))+ (user-account+ (name user)+ (group user)+ (system? #t)+ (comment "Gitolite user")+ (home-directory "/var/lib/gitolite")))))++(define gitolite-setup+ (match-lambda+ (($ <gitolite-configuration> package user rc-file admin-pubkey)+ #~(begin+ (use-modules (ice-9 match)+ (guix build utils))+ (if (not (file-exists? "/var/lib/gitolite/.gitolite"))+ (let ((user-info (getpwnam #$user)))+ (simple-format #t "guix: gitolite: installing ~A\n"+ #$rc-file)+ (symlink #$rc-file "/var/lib/gitolite/.gitolite.rc")++ ;; The key must be writable, so copy it from the store+ (copy-file #$admin-pubkey "/var/lib/gitolite/id_rsa.pub")++ (chmod "/var/lib/gitolite/id_rsa.pub" #o500)+ (chown "/var/lib/gitolite/id_rsa.pub"+ (passwd:uid user-info)+ (passwd:gid user-info))++ ;; Set the git configuration, to avoid gitolite trying to use+ ;; the hostname command, as the network might not be up yet+ (with-output-to-file "/var/lib/gitolite/.gitconfig"+ (lambda ()+ (display "[user]+ name = GNU Guix+ email = guix@localhost+")))++ (match (primitive-fork)+ (0+ ;; Exit with a non-zero status code if an exception is thrown.+ (dynamic-wind+ (const #t)+ (lambda ()+ (setenv "HOME" (passwd:dir user-info))+ (setenv "USER" #$user)+ (setgid (passwd:gid user-info))+ (setuid (passwd:uid user-info))+ (primitive-exit+ (system* #$(file-append package "/bin/gitolite")+ "setup"+ "-pk" "/var/lib/gitolite/id_rsa.pub")))+ (lambda ()+ (primitive-exit 1))))+ (pid (waitpid pid)))++ (delete-file "/var/lib/gitolite/id_rsa.pub")))))))++(define (gitolite-activation config)+ (if (gitolite-configuration-admin-pubkey config)+ (gitolite-setup config)+ #~(display+ "guix: Skipping gitolite setup as the admin-pubkey has not been provided\n")))++(define gitolite-service-type+ (service-type+ (name 'gitolite)+ (extensions+ (list (service-extension activation-service-type+ gitolite-activation)+ (service-extension account-service-type+ gitolite-accounts)+ (service-extension profile-service-type+ ;; The Gitolite package in Guix uses+ ;; gitolite-shell in the authorized_keys file, so+ ;; gitolite-shell needs to be on the PATH for+ ;; gitolite to work.+ (lambda (config)+ (list+ (gitolite-configuration-package config))))))+ (default-value (gitolite-configuration))+ (description+ "Setup @command{gitolite}, a Git hosting tool providing access over SSH..+By default, the @code{git} user is used, but this is configurable.+Additionally, Gitolite can integrate with with tools like gitweb or cgit to+provide a web interface to view selected repositories.")))diff --git a/gnu/tests/version-control.scm b/gnu/tests/version-control.scmindex 3b935a1b4..e4cd3fc3f 100644--- a/gnu/tests/version-control.scm+++ b/gnu/tests/version-control.scm@@ -27,14 +27,17 @@ #:use-module (gnu services) #:use-module (gnu services version-control) #:use-module (gnu services cgit)+ #:use-module (gnu services ssh) #:use-module (gnu services web) #:use-module (gnu services networking) #:use-module (gnu packages version-control)+ #:use-module (gnu packages ssh) #:use-module (guix gexp) #:use-module (guix store) #:use-module (guix modules) #:export (%test-cgit- %test-git-http))+ %test-git-http+ %test-gitolite)) (define README-contents "Hello! This is what goes inside the 'README' file.")@@ -300,3 +303,101 @@ HTTP-PORT." (name "git-http") (description "Connect to a running Git HTTP server.") (value (run-git-http-test))))++ +;;;+;;; Gitolite.+;;;++(define %gitolite-test-admin-keypair+ (computed-file+ "gitolite-test-admin-keypair"+ (with-imported-modules (source-module-closure+ '((guix build utils)))+ #~(begin+ (use-modules (ice-9 match) (srfi srfi-26)+ (guix build utils))++ (mkdir #$output)+ (invoke #$(file-append openssh "/bin/ssh-keygen")+ "-f" (string-append #$output "/id_rsa")+ "-t" "rsa"+ "-q"+ "-N" "")))))++(define %gitolite-os+ (simple-operating-system+ (dhcp-client-service)+ (service openssh-service-type)+ (service gitolite-service-type+ (gitolite-configuration+ (admin-pubkey+ (file-append %gitolite-test-admin-keypair "/id_rsa.pub"))))))++(define (run-gitolite-test)+ (define os+ (marionette-operating-system+ %gitolite-os+ #:imported-modules '((gnu services herd)+ (guix combinators))))++ (define vm+ (virtual-machine+ (operating-system os)+ (port-forwardings `((2222 . 22)))))++ (define test+ (with-imported-modules '((gnu build marionette)+ (guix build utils))+ #~(begin+ (use-modules (srfi srfi-64)+ (rnrs io ports)+ (gnu build marionette)+ (guix build utils))++ (define marionette+ (make-marionette (list #$vm)))++ (mkdir #$output)+ (chdir #$output)++ (test-begin "gitolite")++ ;; Wait for sshd to be up and running.+ (test-eq "service running"+ 'running!+ (marionette-eval+ '(begin+ (use-modules (gnu services herd))+ (start-service 'ssh-daemon)+ 'running!)+ marionette))++ (display #$%gitolite-test-admin-keypair)++ (setenv "GIT_SSH_VARIANT" "ssh")+ (setenv "GIT_SSH_COMMAND"+ (string-join+ '(#$(file-append openssh "/bin/ssh")+ "-i" #$(file-append %gitolite-test-admin-keypair "/id_rsa")+ "-o" "UserKnownHostsFile=/dev/null"+ "-o" "StrictHostKeyChecking=no")))++ ;; Make sure we can clone the repo from the host.+ (test-eq "clone"+ #t+ (invoke #$(file-append git "/bin/git")+ "clone" "-v"+ "ssh://git@localhost:2222/gitolite-admin"+ "/tmp/clone"))++ (test-end)+ (exit (= (test-runner-fail-count (test-runner-current)) 0)))))++ (gexp->derivation "gitolite" test))++(define %test-gitolite+ (system-test+ (name "gitolite")+ (description "Clone the Gitolite admin repository.")+ (value (run-gitolite-test))))-- 2.17.1
C
C
Christopher Baines wrote on 14 Jul 2018 08:28
[PATCH 1/2] gnu: Modify the gitolite package to support the Guix service.
(address . 30809@debbugs.gnu.org)
20180714062855.18705-1-mail@cbaines.net
Previously the gitolite package worked, but there were problems using it forthe service where you might have a minimal PATH. This commit patches thesource and scripts where possible to use store paths, and also wraps thegitolite script to handle the harder dependencies.
* gnu/packages/version-control.scm (gitolite)[arguments]: Add more patching tothe patch-scripts phase, and add two new phases (patch-source andwrap-scripts).[inputs]: Add coreutils, findutils and inetutils.--- gnu/packages/version-control.scm | 53 ++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-)
Toggle diff (80 lines)diff --git a/gnu/packages/version-control.scm b/gnu/packages/version-control.scmindex 2bd59ae95..3bbc586e1 100644--- a/gnu/packages/version-control.scm+++ b/gnu/packages/version-control.scm@@ -1026,12 +1026,42 @@ also walk each side of a merge and test those changes individually.") ((" perl -") (string-append " " perl " -"))) + (substitute* (find-files "src/triggers" ".*")+ ((" sed ")+ (string-append " " (which "sed") " ")))++ (substitute*+ '("src/triggers/post-compile/update-gitweb-access-list"+ "src/triggers/post-compile/ssh-authkeys-split"+ "src/triggers/upstream")+ ((" grep ")+ (string-append " " (which "grep") " ")))+ ;; Avoid references to the store in authorized_keys. ;; This works because gitolite-shell is in the PATH. (substitute* "src/triggers/post-compile/ssh-authkeys" (("\\$glshell \\$user") "gitolite-shell $user")) #t)))+ (add-before 'install 'patch-source+ (lambda* (#:key inputs #:allow-other-keys)+ ;; Gitolite uses cat to test the readability of the+ ;; pubkey+ (substitute* "src/lib/Gitolite/Setup.pm"+ (("\"cat ")+ (string-append "\"" (which "cat") " "))+ (("\"ssh-keygen")+ (string-append "\"" (which "ssh-keygen"))))++ (substitute* "src/lib/Gitolite/Common.pm"+ (("\"ssh-keygen")+ (string-append "\"" (which "ssh-keygen")))+ (("\"logger\"")+ (string-append "\""+ (assoc-ref inputs "inetutils")+ "/bin/logger\"")))++ #t)) (replace 'install (lambda* (#:key outputs #:allow-other-keys) (let* ((output (assoc-ref outputs "out"))@@ -1045,9 +1075,28 @@ also walk each side of a merge and test those changes individually.") (symlink (string-append sharedir "/" script) (string-append bindir "/" script))) '("gitolite" "gitolite-shell"))- #t))))))+ #t)))+ (add-after 'install 'wrap-scripts+ (lambda* (#:key inputs outputs #:allow-other-keys)+ (wrap-program (string-append (assoc-ref outputs "out")+ "/bin/gitolite")+ `("PATH" ":" prefix+ (,(string-append (assoc-ref outputs "out")+ "/bin")+ ,(string-append (assoc-ref inputs "coreutils")+ "/bin")+ ;; find is used in quite a few places+ ,(string-append (assoc-ref inputs "findutils")+ "/bin")+ ,(string-append (assoc-ref inputs "git")+ "/bin"))))++ #t))))) (inputs- `(("perl" ,perl)))+ `(("perl" ,perl)+ ("coreutils" ,coreutils)+ ("findutils" ,findutils)+ ("inetutils" ,inetutils))) ;; git and openssh are propagated because trying to patch the source via ;; regexp matching is too brittle and prone to false positives. (propagated-inputs-- 2.17.1
C
C
Christopher Baines wrote on 14 Jul 2018 08:31
Re: [bug#30809] [PATCH 2/2] services: Add Gitolite.
(name . Oleg Pykhalov)(address . go.wigust@gmail.com)(address . 30809@debbugs.gnu.org)
87y3eee3b7.fsf@cbaines.net
Oleg Pykhalov <go.wigust@gmail.com> writes:
Toggle quote (5 lines)> Hello Christopher,>> Not a full review, just want to note issue in the documentation and say> thank you. The gitolite service works for me.
Awesome, thanks for taking a look :)
Toggle quote (14 lines)> Christopher Baines <mail@cbaines.net> writes:>>> +The following G-exp would use the @file{~/.ssh/id_rsa.pub} file.>> +>> +@example>> +(local-file "~/.ssh/id_rsa.pub")>> +@end example>> ‘~/.ssh/id_rsa.pub’ doesn't work for me, because with ‘./pre-inst-env> guix system vm ./test.scm’ it will be expanded to> ‘/home/natsu/src/guix/~/.ssh/id_rsa.pub’.>> Specifing full path ‘/home/natsu/.ssh/id_rsa.pub’ is required for me.
Ok, I've changed the docs to use a absolute filename instead.
Thanks,
Chris
-----BEGIN PGP SIGNATURE-----
iQKTBAEBCgB9FiEEPonu50WOcg2XVOCyXiijOwuE9XcFAltJmLxfFIAAAAAALgAoaXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldDNFODlFRUU3NDU4RTcyMEQ5NzU0RTBCMjVFMjhBMzNCMEI4NEY1NzcACgkQXiijOwuE9XfIHBAAuUTKvQ+u7huq4jX/5twiSXLK/1a48P3nXO1nzd06YJbeDjphGOG9BjU2XbKiwcBrZkvXDgjl/3JMM2/ZKWqCbu1wpwyGrYt6j+uYXF7TN4vng3ixmhXujBARdmb2KQOUWyWWrRPlVgia5kf6YHNoCS+cHUZr2hjMEzEpArZpW5nRSn5c1x3D0X6JVYGA4Gz/XWG8+5K3JQaX+OdBT5eCmGbZz51TnMphtl0B9OZ6KJgAtvx23sqwoZuao1QtSX1PJe0/La7p9qjzSE/WQVDM1O3aYqYIdyu3pfg858zVEHwToo9CkJIMaK2DDDj4U9jGdcQQ3G76oWb+Wzh8yXSGerfNXJYiiXMw6gkXa2er9GKDHPXkkV8qfC5r1ML/dkfrAE2znkGn8MOPtjqm+BUxIQh8uQc9OIlI+Z84EySdH4egGthutXNInKbyTKIEAVS5EBz8xLQI0Z8MplFnEM3PmCY8eJL4oYWbGT95ewjW8cdUYPTcZr0UJNNyJmODYHi2dgYptvuo/U8YOWNn+MIWGOeyRLxyo1kAN0/Wib37DiMZ/GS/jG1VqqYSNWFvyZiUX7H1DXTqiJmbjLIdy11dNh2pK6p7/eJX17qQipyTCuH5Il7CqnIrj23xZOLvoh8/7kSDORNEs9Djh47ax2DRLRu5KS/QCUwbQ4hGLVRxu/E==cyFi-----END PGP SIGNATURE-----
C
C
Clément Lassieur wrote on 23 Jul 2018 00:26
Re: [bug#30809] [PATCH 1/2] gnu: Modify the gitolite package to support the Guix service.
(name . Christopher Baines)(address . mail@cbaines.net)(address . 30809@debbugs.gnu.org)
87wotmq54x.fsf@lassieur.org
Hi Christopher!
Christopher Baines <mail@cbaines.net> writes:
Toggle quote (13 lines)> Previously the gitolite package worked, but there were problems using it for> the service where you might have a minimal PATH. This commit patches the> source and scripts where possible to use store paths, and also wraps the> gitolite script to handle the harder dependencies.>> * gnu/packages/version-control.scm (gitolite)[arguments]: Add more patching to> the patch-scripts phase, and add two new phases (patch-source and> wrap-scripts).> [inputs]: Add coreutils, findutils and inetutils.> ---> gnu/packages/version-control.scm | 53 ++++++++++++++++++++++++++++++--> 1 file changed, 51 insertions(+), 2 deletions(-)
[...]
Toggle quote (24 lines)> (replace 'install> (lambda* (#:key outputs #:allow-other-keys)> (let* ((output (assoc-ref outputs "out"))> @@ -1045,9 +1075,28 @@ also walk each side of a merge and test those changes individually.")> (symlink (string-append sharedir "/" script)> (string-append bindir "/" script)))> '("gitolite" "gitolite-shell"))> - #t))))))> + #t)))> + (add-after 'install 'wrap-scripts> + (lambda* (#:key inputs outputs #:allow-other-keys)> + (wrap-program (string-append (assoc-ref outputs "out")> + "/bin/gitolite")> + `("PATH" ":" prefix> + (,(string-append (assoc-ref outputs "out")> + "/bin")> + ,(string-append (assoc-ref inputs "coreutils")> + "/bin")> + ;; find is used in quite a few places> + ,(string-append (assoc-ref inputs "findutils")> + "/bin")> + ,(string-append (assoc-ref inputs "git")> + "/bin"))))
Here you can avoid some repetitions like this:
(let ((out (assoc-ref outputs "out")) (coreutils (assoc-ref inputs "coreutils")) (findutils (assoc-ref inputs "findutils")) (git (assoc-ref inputs "git"))) (wrap-program (string-append out "/bin/gitolite") `("PATH" ":" prefix ,(map (lambda (dir) (string-append dir "/bin")) (list out coreutils findutils git)))) #t)
Toggle quote (12 lines)> +> + #t)))))> (inputs> - `(("perl" ,perl)))> + `(("perl" ,perl)> + ("coreutils" ,coreutils)> + ("findutils" ,findutils)> + ("inetutils" ,inetutils)))> ;; git and openssh are propagated because trying to patch the source via> ;; regexp matching is too brittle and prone to false positives.> (propagated-inputs
Otherwise, LGTM, thank you!
C
C
Clément Lassieur wrote on 23 Jul 2018 00:30
Re: [bug#30809] [PATCH 2/2] services: Add Gitolite.
(name . Christopher Baines)(address . mail@cbaines.net)(address . 30809@debbugs.gnu.org)
87va96q4ye.fsf@lassieur.org
Christopher Baines <mail@cbaines.net> writes:
Toggle quote (14 lines)> * gnu/services/version-control.scm (<gitolite-configuration>,> <gitolite-rc-file>): New record types.> (gitolite-accounts, gitolite-setup, gitolite-activation): New procedures.> (gitolite-service-type): New variables.> * gnu/tests/version-control.scm (%gitolite-test-admin-keypair, %gitolite-os,> %test-gitolite): New variables.> (run-gitolite-test): New procedure.> * doc/guix.texi (Version Control): Document the gitolite service.> ---> doc/guix.texi | 90 ++++++++++++++++> gnu/services/version-control.scm | 169 ++++++++++++++++++++++++++++++-> gnu/tests/version-control.scm | 103 ++++++++++++++++++-> 3 files changed, 360 insertions(+), 2 deletions(-)
Great :-)
[...]
Toggle quote (5 lines)> +@item @code{admin-pubkey} (default: @var{#f})> +A ``file-like'' object (@pxref{G-Expressions, file-like objects}) used to> +setup Gitolite. This can be omitted once Gitolite has successfully been> +setup.
It looks like almost everything else can be ommited once Gitolite hassuccessfully been setup :-), I put another comment about it below.
[...]
Toggle quote (20 lines)> +(define-record-type* <gitolite-configuration>> + gitolite-configuration make-gitolite-configuration> + gitolite-configuration?> + (package gitolite-configuration-package> + (default gitolite))> + (user gitolite-configuration-user> + (default "git"))> + (rc-file gitolite-configuration-rc-file> + (default (gitolite-rc-file)))> + (admin-pubkey gitolite-configuration-admin-pubkey> + (default #f)))> +> +(define (gitolite-accounts config)> + (let ((user (gitolite-configuration-user config)))> + ;; User group and account to run Gitolite.> + (list (user-group (name user) (system? #t))> + (user-account> + (name user)> + (group user)
It would be great to make the group and home directory configurabletoo. I personally use other settings for them.
Toggle quote (12 lines)> + (system? #t)> + (comment "Gitolite user")> + (home-directory "/var/lib/gitolite")))))> +> +(define gitolite-setup> + (match-lambda> + (($ <gitolite-configuration> package user rc-file admin-pubkey)> + #~(begin> + (use-modules (ice-9 match)> + (guix build utils))> + (if (not (file-exists? "/var/lib/gitolite/.gitolite"))
'unless', instead of 'if not'.
Also, is there a way to update the config once .gitolite exists? If theusers update their config, they'd expect the new config to be applied Iguess. Maybe we could override the symlink in that case. Would that besafe? WDYT?
Toggle quote (42 lines)> + (let ((user-info (getpwnam #$user)))> + (simple-format #t "guix: gitolite: installing ~A\n"> + #$rc-file)> + (symlink #$rc-file "/var/lib/gitolite/.gitolite.rc")> +> + ;; The key must be writable, so copy it from the store> + (copy-file #$admin-pubkey "/var/lib/gitolite/id_rsa.pub")> +> + (chmod "/var/lib/gitolite/id_rsa.pub" #o500)> + (chown "/var/lib/gitolite/id_rsa.pub"> + (passwd:uid user-info)> + (passwd:gid user-info))> +> + ;; Set the git configuration, to avoid gitolite trying to use> + ;; the hostname command, as the network might not be up yet> + (with-output-to-file "/var/lib/gitolite/.gitconfig"> + (lambda ()> + (display "[user]> + name = GNU Guix> + email = guix@localhost> +")))> +> + (match (primitive-fork)> + (0> + ;; Exit with a non-zero status code if an exception is thrown.> + (dynamic-wind> + (const #t)> + (lambda ()> + (setenv "HOME" (passwd:dir user-info))> + (setenv "USER" #$user)> + (setgid (passwd:gid user-info))> + (setuid (passwd:uid user-info))> + (primitive-exit> + (system* #$(file-append package "/bin/gitolite")> + "setup"> + "-pk" "/var/lib/gitolite/id_rsa.pub")))> + (lambda ()> + (primitive-exit 1))))> + (pid (waitpid pid)))> +> + (delete-file "/var/lib/gitolite/id_rsa.pub")))))))
[...]
Toggle quote (2 lines)> diff --git a/gnu/tests/version-control.scm b/gnu/tests/version-control.scm
Could you add your copyright header for this file?
Toggle quote (37 lines)> index 3b935a1b4..e4cd3fc3f 100644> --- a/gnu/tests/version-control.scm> +++ b/gnu/tests/version-control.scm> @@ -27,14 +27,17 @@> #:use-module (gnu services)> #:use-module (gnu services version-control)> #:use-module (gnu services cgit)> + #:use-module (gnu services ssh)> #:use-module (gnu services web)> #:use-module (gnu services networking)> #:use-module (gnu packages version-control)> + #:use-module (gnu packages ssh)> #:use-module (guix gexp)> #:use-module (guix store)> #:use-module (guix modules)> #:export (%test-cgit> - %test-git-http))> + %test-git-http> + %test-gitolite))> > (define README-contents> "Hello! This is what goes inside the 'README' file.")> @@ -300,3 +303,101 @@ HTTP-PORT."> (name "git-http")> (description "Connect to a running Git HTTP server.")> (value (run-git-http-test))))> +> + > +;;;> +;;; Gitolite.> +;;;> +> +(define %gitolite-test-admin-keypair> + (computed-file> + "gitolite-test-admin-keypair"> + (with-imported-modules (source-module-closure> + '((guix build utils)))
^Here indentation is not correct ;-)
Toggle quote (11 lines)> + #~(begin> + (use-modules (ice-9 match) (srfi srfi-26)> + (guix build utils))> +> + (mkdir #$output)> + (invoke #$(file-append openssh "/bin/ssh-keygen")> + "-f" (string-append #$output "/id_rsa")> + "-t" "rsa"> + "-q"> + "-N" "")))))
[...]
Toggle quote (27 lines)> + (define test> + (with-imported-modules '((gnu build marionette)> + (guix build utils))> + #~(begin> + (use-modules (srfi srfi-64)> + (rnrs io ports)> + (gnu build marionette)> + (guix build utils))> +> + (define marionette> + (make-marionette (list #$vm)))> +> + (mkdir #$output)> + (chdir #$output)> +> + (test-begin "gitolite")> +> + ;; Wait for sshd to be up and running.> + (test-eq "service running"> + 'running!> + (marionette-eval> + '(begin> + (use-modules (gnu services herd))> + (start-service 'ssh-daemon)> + 'running!)> + marionette))
Here the test produces a false positive because the return value of'start-service' isn't used. It should be
(test-assert ... (start-service ...))
instead.
Toggle quote (29 lines)> + (display #$%gitolite-test-admin-keypair)> +> + (setenv "GIT_SSH_VARIANT" "ssh")> + (setenv "GIT_SSH_COMMAND"> + (string-join> + '(#$(file-append openssh "/bin/ssh")> + "-i" #$(file-append %gitolite-test-admin-keypair "/id_rsa")> + "-o" "UserKnownHostsFile=/dev/null"> + "-o" "StrictHostKeyChecking=no")))> +> + ;; Make sure we can clone the repo from the host.> + (test-eq "clone"> + #t> + (invoke #$(file-append git "/bin/git")> + "clone" "-v"> + "ssh://git@localhost:2222/gitolite-admin"> + "/tmp/clone"))> +> + (test-end)> + (exit (= (test-runner-fail-count (test-runner-current)) 0)))))> +> + (gexp->derivation "gitolite" test))> +> +(define %test-gitolite> + (system-test> + (name "gitolite")> + (description "Clone the Gitolite admin repository.")> + (value (run-gitolite-test))))
Also, did you encounter bugs https://bugs.gnu.org/25957andhttps://bugs.gnu.org/30401? Do you know if they are still here?
Thank you very much!Clément
C
C
Christopher Baines wrote on 23 Jul 2018 23:43
[PATCH 1/2] gnu: Modify the gitolite package to support the Guix service.
(address . 30809@debbugs.gnu.org)
20180723214328.18740-1-mail@cbaines.net
Previously the gitolite package worked, but there were problems using it forthe service where you might have a minimal PATH. This commit patches thesource and scripts where possible to use store paths, and also wraps thegitolite script to handle the harder dependencies.
* gnu/packages/version-control.scm (gitolite)[arguments]: Add more patching tothe patch-scripts phase, and add two new phases (patch-source andwrap-scripts).[inputs]: Add coreutils, findutils and inetutils.--- gnu/packages/version-control.scm | 53 +++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-)
Toggle diff (81 lines)diff --git a/gnu/packages/version-control.scm b/gnu/packages/version-control.scmindex 6cb335420..ca765be1a 100644--- a/gnu/packages/version-control.scm+++ b/gnu/packages/version-control.scm@@ -1026,12 +1026,48 @@ also walk each side of a merge and test those changes individually.") ((" perl -") (string-append " " perl " -"))) + (substitute* (find-files "src/triggers" ".*")+ ((" sed ")+ (string-append " " (which "sed") " ")))++ (substitute*+ '("src/triggers/post-compile/update-gitweb-access-list"+ "src/triggers/post-compile/ssh-authkeys-split"+ "src/triggers/upstream")+ ((" grep ")+ (string-append " " (which "grep") " ")))+ ;; Avoid references to the store in authorized_keys. ;; This works because gitolite-shell is in the PATH. (substitute* "src/triggers/post-compile/ssh-authkeys" (("\\$glshell \\$user") "gitolite-shell $user")) #t)))+ (add-before 'install 'patch-source+ (lambda* (#:key inputs #:allow-other-keys)+ ;; Gitolite uses cat to test the readability of the+ ;; pubkey+ (substitute* "src/lib/Gitolite/Setup.pm"+ (("\"cat ")+ (string-append "\"" (which "cat") " "))+ (("\"ssh-keygen")+ (string-append "\"" (which "ssh-keygen"))))++ (substitute* '("src/lib/Gitolite/Hooks/PostUpdate.pm"+ "src/lib/Gitolite/Hooks/Update.pm")+ (("/usr/bin/perl")+ (string-append (assoc-ref inputs "perl")+ "/bin/perl")))++ (substitute* "src/lib/Gitolite/Common.pm"+ (("\"ssh-keygen")+ (string-append "\"" (which "ssh-keygen")))+ (("\"logger\"")+ (string-append "\""+ (assoc-ref inputs "inetutils")+ "/bin/logger\"")))++ #t)) (replace 'install (lambda* (#:key outputs #:allow-other-keys) (let* ((output (assoc-ref outputs "out"))@@ -1045,9 +1081,24 @@ also walk each side of a merge and test those changes individually.") (symlink (string-append sharedir "/" script) (string-append bindir "/" script))) '("gitolite" "gitolite-shell"))+ #t)))+ (add-after 'install 'wrap-scripts+ (lambda* (#:key inputs outputs #:allow-other-keys)+ (let ((out (assoc-ref outputs "out"))+ (coreutils (assoc-ref inputs "coreutils"))+ (findutils (assoc-ref inputs "findutils"))+ (git (assoc-ref inputs "git")))+ (wrap-program (string-append out "/bin/gitolite")+ `("PATH" ":" prefix+ ,(map (lambda (dir)+ (string-append dir "/bin"))+ (list out coreutils findutils git)))) #t)))))) (inputs- `(("perl" ,perl)))+ `(("perl" ,perl)+ ("coreutils" ,coreutils)+ ("findutils" ,findutils)+ ("inetutils" ,inetutils))) ;; git and openssh are propagated because trying to patch the source via ;; regexp matching is too brittle and prone to false positives. (propagated-inputs-- 2.18.0
C
C
Christopher Baines wrote on 23 Jul 2018 23:43
[PATCH 2/2] services: Add Gitolite.
(address . 30809@debbugs.gnu.org)
20180723214328.18740-2-mail@cbaines.net
* gnu/services/version-control.scm (<gitolite-configuration>,<gitolite-rc-file>): New record types.(gitolite-accounts, gitolite-setup, gitolite-activation): New procedures.(gitolite-service-type): New variables.* gnu/tests/version-control.scm (%gitolite-test-admin-keypair, %gitolite-os,%test-gitolite): New variables.(run-gitolite-test): New procedure.* doc/guix.texi (Version Control): Document the gitolite service.--- doc/guix.texi | 90 +++++++++++++++ gnu/services/version-control.scm | 185 ++++++++++++++++++++++++++++++- gnu/tests/version-control.scm | 112 ++++++++++++++++++- 3 files changed, 385 insertions(+), 2 deletions(-)
Toggle diff (451 lines)diff --git a/doc/guix.texi b/doc/guix.texiindex 84347d156..8618f4cdb 100644--- a/doc/guix.texi+++ b/doc/guix.texi@@ -20217,6 +20217,96 @@ could instantiate a cgit service like this: (cgitrc ""))) @end example +@subsubheading Gitolite Service++@cindex Gitolite service+@cindex Git, hosting+@uref{http://gitolite.com/gitolite/, Gitolite} is a tool for hosting Git+repositories on a central server.++Gitolite can handle multiple repositories and users, and supports flexible+configuration of the permissions for the users on the repositories.++The following example will configure Gitolite using the default @code{git}+user, and the provided SSH public key. A public key is necessary to setup+Gitolite initially, but can be omitted once Gitolite is setup.++@example+(service gitolite-service-type+ (gitolite-configuration+ (admin-pubkey (plain-file+ "id_rsa.pub"+ "ssh-rsa AAAA... guix@@example.com"))))+@end example++Gitolite is configured through a special admin repository which you can clone,+for example, if you setup Gitolite on @code{example.com}, you would run the+following command to clone the admin repository.++@example+git clone git@@example.com:gitolite-admin+@end example++@deftp {Data Type} gitolite-configuration+Data type representing the configuration for @code{gitolite-service-type}.++@table @asis+@item @code{package} (default: @var{gitolite})+Gitolite package to use.++@item @code{user} (default: @var{git})+User to use for Gitolite. This will be user that you use when accessing+Gitolite over SSH.++@item @code{rc-file} (default: @var{(gitolite-rc-file)})+A ``file-like'' object (@pxref{G-Expressions, file-like objects}),+representing the configuration for Gitolite.++@item @code{admin-pubkey} (default: @var{#f})+A ``file-like'' object (@pxref{G-Expressions, file-like objects}) used to+setup Gitolite. This can be omitted once Gitolite has successfully been+setup.++The following G-exp would use the @file{/home/user/.ssh/id_rsa.pub} file.++@example+(local-file "/home/user/.ssh/id_rsa.pub")+@end example++To specify the SSH key as a string, use the @code{plain-file} function.++@example+(plain-file "id_rsa.pub" "ssh-rsa AAAA... guix@@example.com")+@end example++@end table+@end deftp++@deftp {Data Type} gitolite-rc-file+Data type representing the Gitolite RC file.++@table @asis+@item @code{umask} (default: @code{#o0077})+This controls the permissions Gitolite sets on the repositories and their+contents.++A value like @code{#o0027} will give read access to the group used by Gitolite+(by default: @code{git}). This is necessary when using Gitolite with software+like cgit or gitweb.++@item @code{git-config-keys} (default: @code{""})+Gitolite allows you to set git config values using the "config" keyword. This+setting allows control over the config keys to accept.++@item @code{roles} (default: @code{'(("READERS" . 1) ("WRITERS" . ))})+Set the role names allowed to be used by users running the perms command.++@item @code{enable} (default: @code{'("help" "desc" "info" "perms" "writable" "ssh-authkeys" "git-config" "daemon" "gitweb")})+This setting controls the commands and features to enable within Gitolite.++@end table+@end deftp+ @node Game Services @subsubsection Game Servicesdiff --git a/gnu/services/version-control.scm b/gnu/services/version-control.scmindex 58274c8be..367ea3a38 100644--- a/gnu/services/version-control.scm+++ b/gnu/services/version-control.scm@@ -3,6 +3,7 @@ ;;; Copyright © 2016 Sou Bunnbu <iyzsong@member.fsf.org> ;;; Copyright © 2017 Oleg Pykhalov <go.wigust@gmail.com> ;;; Copyright © 2017 Clément Lassieur <clement@lassieur.org>+;;; Copyright © 2018 Christopher Baines <mail@cbaines.net> ;;; ;;; This file is part of GNU Guix. ;;;@@ -40,7 +41,23 @@ git-http-configuration git-http-configuration?- git-http-nginx-location-configuration))+ git-http-nginx-location-configuration++ <gitolite-configuration>+ gitolite-configuration+ gitolite-configuration-package+ gitolite-configuration-user+ gitolite-configuration-rc-file+ gitolite-configuration-admin-pubkey++ <gitolite-rc-file>+ gitolite-rc-file+ gitolite-rc-file-umask+ gitolite-rc-file-git-config-keys+ gitolite-rc-file-roles+ gitolite-rc-file-enable++ gitolite-service-type)) ;;; Commentary: ;;;@@ -197,3 +214,169 @@ access to exported repositories under @file{/srv/git}." "") (list "fastcgi_param GIT_PROJECT_ROOT " git-root ";") "fastcgi_param PATH_INFO $1;"))))))++ +;;;+;;; Gitolite+;;;++(define-record-type* <gitolite-rc-file>+ gitolite-rc-file make-gitolite-rc-file+ gitolite-rc-file?+ (umask gitolite-rc-file-umask+ (default #o0077))+ (git-config-keys gitolite-rc-file-git-config-keys+ (default ""))+ (roles gitolite-rc-file-roles+ (default '(("READERS" . 1)+ ("WRITERS" . 1))))+ (enable gitolite-rc-file-enable+ (default '("help"+ "desc"+ "info"+ "perms"+ "writable"+ "ssh-authkeys"+ "git-config"+ "daemon"+ "gitweb"))))++(define-gexp-compiler (gitolite-rc-file-compiler+ (file <gitolite-rc-file>) system target)+ (match file+ (($ <gitolite-rc-file> umask git-config-keys roles enable)+ (apply text-file* "gitolite.rc"+ `("%RC = (\n"+ " UMASK => " ,(format #f "~4,'0o" umask) ",\n"+ " GIT_CONFIG_KEYS => '" ,git-config-keys "',\n"+ " ROLES => {\n"+ ,@(map (match-lambda+ ((role . value)+ (simple-format #f " ~A => ~A,\n" role value)))+ roles)+ " },\n"+ "\n"+ " ENABLE => [\n"+ ,@(map (lambda (value)+ (simple-format #f " '~A',\n" value))+ enable)+ " ],\n"+ ");\n"+ "\n"+ "1;\n")))))++(define-record-type* <gitolite-configuration>+ gitolite-configuration make-gitolite-configuration+ gitolite-configuration?+ (package gitolite-configuration-package+ (default gitolite))+ (user gitolite-configuration-user+ (default "git"))+ (group gitolite-configuration-group+ (default "git"))+ (home-directory gitolite-configuration-home-directory+ (default "/var/lib/gitolite"))+ (rc-file gitolite-configuration-rc-file+ (default (gitolite-rc-file)))+ (admin-pubkey gitolite-configuration-admin-pubkey+ (default #f)))++(define gitolite-accounts+ (match-lambda+ (($ <gitolite-configuration> package user group home-directory+ rc-file admin-pubkey)+ ;; User group and account to run Gitolite.+ (list (user-group (name user) (system? #t))+ (user-account+ (name user)+ (group group)+ (system? #t)+ (comment "Gitolite user")+ (home-directory home-directory))))))++(define gitolite-setup+ (match-lambda+ (($ <gitolite-configuration> package user group home+ rc-file admin-pubkey)+ #~(let ((user-info (getpwnam #$user)))+ (use-modules (guix build utils))++ (simple-format #t "guix: gitolite: installing ~A\n" #$rc-file)+ (copy-file #$rc-file #$(string-append home "/.gitolite.rc"))++ (let ((admin-pubkey #$admin-pubkey)+ (pubkey-file #$(string-append home "/id_rsa.pub")))+ (when admin-pubkey+ ;; The key must be writable, so copy it from the store+ (copy-file #$admin-pubkey pubkey-file)++ (chmod pubkey-file #o500)+ (chown pubkey-file+ (passwd:uid user-info)+ (passwd:gid user-info))++ ;; Set the git configuration, to avoid gitolite trying to use+ ;; the hostname command, as the network might not be up yet+ (with-output-to-file #$(string-append home "/.gitconfig")+ (lambda ()+ (display "[user]+ name = GNU Guix+ email = guix@localhost+"))))+ ;; Run Gitolite setup, as this updates the hooks and include the+ ;; admin pubkey if specified. The admin pubkey is required for+ ;; initial setup, and will replace the previous key if run after+ ;; initial setup+ (let ((pid (primitive-fork)))+ (if (eq? pid 0)+ (begin+ ;; Exit with a non-zero status code if an exception is thrown.+ (dynamic-wind+ (const #t)+ (lambda ()+ (setenv "HOME" (passwd:dir user-info))+ (setenv "USER" #$user)+ (setgid (passwd:gid user-info))+ (setuid (passwd:uid user-info))+ (primitive-exit+ (apply system*+ #$(file-append package "/bin/gitolite")+ "setup"+ (if admin-pubkey+ `("-pk" ,pubkey-file)+ '()))))+ (lambda ()+ (primitive-exit 1))))+ (waitpid pid)))++ (when (file-exists? pubkey-file)+ (delete-file pubkey-file)))))))++(define (gitolite-activation config)+ (if (gitolite-configuration-admin-pubkey config)+ (gitolite-setup config)+ #~(display+ "guix: Skipping gitolite setup as the admin-pubkey has not been provided\n")))++(define gitolite-service-type+ (service-type+ (name 'gitolite)+ (extensions+ (list (service-extension activation-service-type+ gitolite-activation)+ (service-extension account-service-type+ gitolite-accounts)+ (service-extension profile-service-type+ ;; The Gitolite package in Guix uses+ ;; gitolite-shell in the authorized_keys file, so+ ;; gitolite-shell needs to be on the PATH for+ ;; gitolite to work.+ (lambda (config)+ (list+ (gitolite-configuration-package config))))))+ (default-value (gitolite-configuration))+ (description+ "Setup @command{gitolite}, a Git hosting tool providing access over SSH..+By default, the @code{git} user is used, but this is configurable.+Additionally, Gitolite can integrate with with tools like gitweb or cgit to+provide a web interface to view selected repositories.")))diff --git a/gnu/tests/version-control.scm b/gnu/tests/version-control.scmindex 3b935a1b4..f2935b166 100644--- a/gnu/tests/version-control.scm+++ b/gnu/tests/version-control.scm@@ -2,6 +2,7 @@ ;;; Copyright © 2017, 2018 Oleg Pykhalov <go.wigust@gmail.com> ;;; Copyright © 2017, 2018 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2017, 2018 Clément Lassieur <clement@lassieur.org>+;;; Copyright © 2018 Christopher Baines <mail@cbaines.net> ;;; ;;; This file is part of GNU Guix. ;;;@@ -27,14 +28,17 @@ #:use-module (gnu services) #:use-module (gnu services version-control) #:use-module (gnu services cgit)+ #:use-module (gnu services ssh) #:use-module (gnu services web) #:use-module (gnu services networking) #:use-module (gnu packages version-control)+ #:use-module (gnu packages ssh) #:use-module (guix gexp) #:use-module (guix store) #:use-module (guix modules) #:export (%test-cgit- %test-git-http))+ %test-git-http+ %test-gitolite)) (define README-contents "Hello! This is what goes inside the 'README' file.")@@ -300,3 +304,109 @@ HTTP-PORT." (name "git-http") (description "Connect to a running Git HTTP server.") (value (run-git-http-test))))++ +;;;+;;; Gitolite.+;;;++(define %gitolite-test-admin-keypair+ (computed-file+ "gitolite-test-admin-keypair"+ (with-imported-modules (source-module-closure+ '((guix build utils)))+ #~(begin+ (use-modules (ice-9 match) (srfi srfi-26)+ (guix build utils))++ (mkdir #$output)+ (invoke #$(file-append openssh "/bin/ssh-keygen")+ "-f" (string-append #$output "/id_rsa")+ "-t" "rsa"+ "-q"+ "-N" "")))))++(define %gitolite-os+ (simple-operating-system+ (dhcp-client-service)+ (service openssh-service-type)+ (service gitolite-service-type+ (gitolite-configuration+ (admin-pubkey+ (file-append %gitolite-test-admin-keypair "/id_rsa.pub"))))))++(define (run-gitolite-test)+ (define os+ (marionette-operating-system+ %gitolite-os+ #:imported-modules '((gnu services herd)+ (guix combinators))))++ (define vm+ (virtual-machine+ (operating-system os)+ (port-forwardings `((2222 . 22)))))++ (define test+ (with-imported-modules '((gnu build marionette)+ (guix build utils))+ #~(begin+ (use-modules (srfi srfi-64)+ (rnrs io ports)+ (gnu build marionette)+ (guix build utils))++ (define marionette+ (make-marionette (list #$vm)))++ (mkdir #$output)+ (chdir #$output)++ (test-begin "gitolite")++ ;; Wait for sshd to be up and running.+ (test-assert "service running"+ (marionette-eval+ '(begin+ (use-modules (gnu services herd))+ (start-service 'ssh-daemon))+ marionette))++ (display #$%gitolite-test-admin-keypair)++ (setenv "GIT_SSH_VARIANT" "ssh")+ (setenv "GIT_SSH_COMMAND"+ (string-join+ '(#$(file-append openssh "/bin/ssh")+ "-i" #$(file-append %gitolite-test-admin-keypair "/id_rsa")+ "-o" "UserKnownHostsFile=/dev/null"+ "-o" "StrictHostKeyChecking=no")))++ (test-eq "cloning the admin repository"+ #t+ (invoke #$(file-append git "/bin/git")+ "clone" "-v"+ "ssh://git@localhost:2222/gitolite-admin"+ "/tmp/clone"))++ (with-directory-excursion "/tmp/clone"+ (invoke #$(file-append git "/bin/git")+ "-c" "user.name=Guix" "-c" "user.email=guix"+ "commit"+ "-m" "Test commit"+ "--allow-empty")++ (test-eq "pushing, and the associated hooks"+ #t+ (invoke #$(file-append git "/bin/git") "push")))++ (test-end)+ (exit (= (test-runner-fail-count (test-runner-current)) 0)))))++ (gexp->derivation "gitolite" test))++(define %test-gitolite+ (system-test+ (name "gitolite")+ (description "Clone the Gitolite admin repository.")+ (value (run-gitolite-test))))-- 2.18.0
C
C
Christopher Baines wrote on 24 Jul 2018 00:06
(name . Clément Lassieur)(address . clement@lassieur.org)(address . 30809@debbugs.gnu.org)
87efftwqrs.fsf@cbaines.net
Clément Lassieur <clement@lassieur.org> writes:
Toggle quote (18 lines)> Christopher Baines <mail@cbaines.net> writes:>>> * gnu/services/version-control.scm (<gitolite-configuration>,>> <gitolite-rc-file>): New record types.>> (gitolite-accounts, gitolite-setup, gitolite-activation): New procedures.>> (gitolite-service-type): New variables.>> * gnu/tests/version-control.scm (%gitolite-test-admin-keypair, %gitolite-os,>> %test-gitolite): New variables.>> (run-gitolite-test): New procedure.>> * doc/guix.texi (Version Control): Document the gitolite service.>> --->> doc/guix.texi | 90 ++++++++++++++++>> gnu/services/version-control.scm | 169 ++++++++++++++++++++++++++++++->> gnu/tests/version-control.scm | 103 ++++++++++++++++++->> 3 files changed, 360 insertions(+), 2 deletions(-)>> Great :-)
Thanks for taking a look Clément, I too was looking at the these patchesover the last few days, and I've sent some updated patches with somechanges.
Toggle quote (8 lines)>> +@item @code{admin-pubkey} (default: @var{#f})>> +A ``file-like'' object (@pxref{G-Expressions, file-like objects}) used to>> +setup Gitolite. This can be omitted once Gitolite has successfully been>> +setup.>> It looks like almost everything else can be ommited once Gitolite has> successfully been setup :-), I put another comment about it below.
Well, maybe things like the rc-file could be omitted, but that'sprobably worth keeping.
Toggle quote (23 lines)>> +(define-record-type* <gitolite-configuration>>> + gitolite-configuration make-gitolite-configuration>> + gitolite-configuration?>> + (package gitolite-configuration-package>> + (default gitolite))>> + (user gitolite-configuration-user>> + (default "git"))>> + (rc-file gitolite-configuration-rc-file>> + (default (gitolite-rc-file)))>> + (admin-pubkey gitolite-configuration-admin-pubkey>> + (default #f)))>> +>> +(define (gitolite-accounts config)>> + (let ((user (gitolite-configuration-user config)))>> + ;; User group and account to run Gitolite.>> + (list (user-group (name user) (system? #t))>> + (user-account>> + (name user)>> + (group user)>> It would be great to make the group and home directory configurable> too. I personally use other settings for them.
Sure, I've made those configurable now.
Toggle quote (19 lines)>> + (system? #t)>> + (comment "Gitolite user")>> + (home-directory "/var/lib/gitolite")))))>> +>> +(define gitolite-setup>> + (match-lambda>> + (($ <gitolite-configuration> package user rc-file admin-pubkey)>> + #~(begin>> + (use-modules (ice-9 match)>> + (guix build utils))>> + (if (not (file-exists? "/var/lib/gitolite/.gitolite"))>> 'unless', instead of 'if not'.>> Also, is there a way to update the config once .gitolite exists? If the> users update their config, they'd expect the new config to be applied I> guess. Maybe we could override the symlink in that case. Would that be> safe? WDYT?
So, I've rewritten some of this now. gitolite setup will be run eachtime the service is activated, and this is important to ensure that thehooks are updated.
Toggle quote (48 lines)>> + (let ((user-info (getpwnam #$user)))>> + (simple-format #t "guix: gitolite: installing ~A\n">> + #$rc-file)>> + (symlink #$rc-file "/var/lib/gitolite/.gitolite.rc")>> +>> + ;; The key must be writable, so copy it from the store>> + (copy-file #$admin-pubkey "/var/lib/gitolite/id_rsa.pub")>> +>> + (chmod "/var/lib/gitolite/id_rsa.pub" #o500)>> + (chown "/var/lib/gitolite/id_rsa.pub">> + (passwd:uid user-info)>> + (passwd:gid user-info))>> +>> + ;; Set the git configuration, to avoid gitolite trying to use>> + ;; the hostname command, as the network might not be up yet>> + (with-output-to-file "/var/lib/gitolite/.gitconfig">> + (lambda ()>> + (display "[user]>> + name = GNU Guix>> + email = guix@localhost>> +")))>> +>> + (match (primitive-fork)>> + (0>> + ;; Exit with a non-zero status code if an exception is thrown.>> + (dynamic-wind>> + (const #t)>> + (lambda ()>> + (setenv "HOME" (passwd:dir user-info))>> + (setenv "USER" #$user)>> + (setgid (passwd:gid user-info))>> + (setuid (passwd:uid user-info))>> + (primitive-exit>> + (system* #$(file-append package "/bin/gitolite")>> + "setup">> + "-pk" "/var/lib/gitolite/id_rsa.pub")))>> + (lambda ()>> + (primitive-exit 1))))>> + (pid (waitpid pid)))>> +>> + (delete-file "/var/lib/gitolite/id_rsa.pub")))))))>> [...]>>> diff --git a/gnu/tests/version-control.scm b/gnu/tests/version-control.scm>> Could you add your copyright header for this file?
I've done this now :)
Toggle quote (40 lines)>> index 3b935a1b4..e4cd3fc3f 100644>> --- a/gnu/tests/version-control.scm>> +++ b/gnu/tests/version-control.scm>> @@ -27,14 +27,17 @@>> #:use-module (gnu services)>> #:use-module (gnu services version-control)>> #:use-module (gnu services cgit)>> + #:use-module (gnu services ssh)>> #:use-module (gnu services web)>> #:use-module (gnu services networking)>> #:use-module (gnu packages version-control)>> + #:use-module (gnu packages ssh)>> #:use-module (guix gexp)>> #:use-module (guix store)>> #:use-module (guix modules)>> #:export (%test-cgit>> - %test-git-http))>> + %test-git-http>> + %test-gitolite))>>>> (define README-contents>> "Hello! This is what goes inside the 'README' file.")>> @@ -300,3 +303,101 @@ HTTP-PORT.">> (name "git-http")>> (description "Connect to a running Git HTTP server.")>> (value (run-git-http-test))))>> +>> + >> +;;;>> +;;; Gitolite.>> +;;;>> +>> +(define %gitolite-test-admin-keypair>> + (computed-file>> + "gitolite-test-admin-keypair">> + (with-imported-modules (source-module-closure>> + '((guix build utils)))> ^> Here indentation is not correct ;-)
Ah, yep, I've corrected this.
Toggle quote (17 lines)>> + ;; Wait for sshd to be up and running.>> + (test-eq "service running">> + 'running!>> + (marionette-eval>> + '(begin>> + (use-modules (gnu services herd))>> + (start-service 'ssh-daemon)>> + 'running!)>> + marionette))>> Here the test produces a false positive because the return value of> 'start-service' isn't used. It should be>> (test-assert ... (start-service ...))>> instead.
Ok, I've made this change now.
Toggle quote (32 lines)>> + (display #$%gitolite-test-admin-keypair)>> +>> + (setenv "GIT_SSH_VARIANT" "ssh")>> + (setenv "GIT_SSH_COMMAND">> + (string-join>> + '(#$(file-append openssh "/bin/ssh")>> + "-i" #$(file-append %gitolite-test-admin-keypair "/id_rsa")>> + "-o" "UserKnownHostsFile=/dev/null">> + "-o" "StrictHostKeyChecking=no")))>> +>> + ;; Make sure we can clone the repo from the host.>> + (test-eq "clone">> + #t>> + (invoke #$(file-append git "/bin/git")>> + "clone" "-v">> + "ssh://git@localhost:2222/gitolite-admin">> + "/tmp/clone"))>> +>> + (test-end)>> + (exit (= (test-runner-fail-count (test-runner-current)) 0)))))>> +>> + (gexp->derivation "gitolite" test))>> +>> +(define %test-gitolite>> + (system-test>> + (name "gitolite")>> + (description "Clone the Gitolite admin repository.")>> + (value (run-gitolite-test))))>> Also, did you encounter bugs https://bugs.gnu.org/25957 and> https://bugs.gnu.org/30401? Do you know if they are still here?
So, 25957 should be fixed. That's now handled in the 'patch-source phaseof the package.
As for 30401, I'm not too sure.
-----BEGIN PGP SIGNATURE-----
iQKTBAEBCgB9FiEEPonu50WOcg2XVOCyXiijOwuE9XcFAltWUXdfFIAAAAAALgAoaXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldDNFODlFRUU3NDU4RTcyMEQ5NzU0RTBCMjVFMjhBMzNCMEI4NEY1NzcACgkQXiijOwuE9XcK9hAAuSreMgaYFT3/ucaBw+dMXq95+bFtXHXmhuYTFQGJgsj3+ifRbANMV4DGS4WtwBk8+mujSqzapSM2bY1cETg4zVJXZUAtsQSje6Y0yBDMcOsIc0vK6owJVjFbh+zdC1txJBwF9L7K0IKzlXYLgIWcBcVVLLhaY98w15sqXhjKEGfF7NKcmJjDa2XS6QXv8bEyMyqlWFqoQrcoQMUDOXDaUKWwAWlWx9QV1MPuhTCVGn5+cKL+0E+znrhcTx/+ea3KFjvmX5MJfIO3mmJ4yejxv5hljUQKT8Gw5qzHUDZr+yzia2fomzyYCcT0dD5j5iroeLFji9vWCsG5Rwwe1UCKR6trkXqI+y0bXngL1hgIbY7r68jx5caBXMnLD3cbweLZM7xCEqCCfIGGLKRynOe3Fo4jwywMVuch0gvfNPboKHpaygntpyFoIS2nv/xXt3tWk6pDBAebffCJabpmovksoydL71Sq9gJTJiBzFGhagfmrth7qxpFiJSaTXIJs69CTh4p4kFrlyzPHzr8Bdj09kUGGxgpBCgcv7Zj7ZDR1MasFTwgM/KvEy+oxDC7RUdECuyttqRqo9fBIE0uVG7nVjfEhnRqdRn5lR4oF/diS3jrqLhAjNj1EU57N2m8kMgHfZh1ttujw57na58qkqsAts1qpRHdmJ2k/AK8+8h47Qgs==QQDE-----END PGP SIGNATURE-----
C
C
Christopher Baines wrote on 24 Jul 2018 00:10
Re: [bug#30809] [PATCH 1/2] gnu: Modify the gitolite package to support the Guix service.
(name . Clément Lassieur)(address . clement@lassieur.org)(address . 30809@debbugs.gnu.org)
87d0vdwqlp.fsf@cbaines.net
Clément Lassieur <clement@lassieur.org> writes:
Toggle quote (37 lines)>> (replace 'install>> (lambda* (#:key outputs #:allow-other-keys)>> (let* ((output (assoc-ref outputs "out"))>> @@ -1045,9 +1075,28 @@ also walk each side of a merge and test those changes individually.")>> (symlink (string-append sharedir "/" script)>> (string-append bindir "/" script)))>> '("gitolite" "gitolite-shell"))>> - #t))))))>> + #t)))>> + (add-after 'install 'wrap-scripts>> + (lambda* (#:key inputs outputs #:allow-other-keys)>> + (wrap-program (string-append (assoc-ref outputs "out")>> + "/bin/gitolite")>> + `("PATH" ":" prefix>> + (,(string-append (assoc-ref outputs "out")>> + "/bin")>> + ,(string-append (assoc-ref inputs "coreutils")>> + "/bin")>> + ;; find is used in quite a few places>> + ,(string-append (assoc-ref inputs "findutils")>> + "/bin")>> + ,(string-append (assoc-ref inputs "git")>> + "/bin"))))>> Here you can avoid some repetitions like this:>> (let ((out (assoc-ref outputs "out"))> (coreutils (assoc-ref inputs "coreutils"))> (findutils (assoc-ref inputs "findutils"))> (git (assoc-ref inputs "git")))> (wrap-program (string-append out "/bin/gitolite")> `("PATH" ":" prefix> ,(map (lambda (dir)> (string-append dir "/bin"))> (list out coreutils findutils git))))> #t)
Thanks, I've used this in the updated patch now.
Toggle quote (14 lines)>> +>> + #t)))))>> (inputs>> - `(("perl" ,perl)))>> + `(("perl" ,perl)>> + ("coreutils" ,coreutils)>> + ("findutils" ,findutils)>> + ("inetutils" ,inetutils)))>> ;; git and openssh are propagated because trying to patch the source via>> ;; regexp matching is too brittle and prone to false positives.>> (propagated-inputs>> Otherwise, LGTM, thank you!
Great :) I've made quite a few changes in the most recent update, so ifyou have some time to look at those, that would be useful. The systemtest is more rigorous now, pushing to the repository to test the hooks,and I've rewritten most of the activation code.
-----BEGIN PGP SIGNATURE-----
iQKTBAEBCgB9FiEEPonu50WOcg2XVOCyXiijOwuE9XcFAltWUlJfFIAAAAAALgAoaXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldDNFODlFRUU3NDU4RTcyMEQ5NzU0RTBCMjVFMjhBMzNCMEI4NEY1NzcACgkQXiijOwuE9XfLBg//csgcqJuSldNfM3FOaD31LW/QoH/vgPllv/R1zEbum5oRVYc1yiQCuzjhL1ZWoHlURra3vMy6Ceu5w/cldkQy/0ZB45xw4f1IFPI+sTOuKlguXxBTIeLE0YXe6y3WqFvZLFLqY3fgbRnaCrrwylLiuJLAAUbQ77FKz6Khu0Qj+Ca7nmppp0EImML668RtSi7LD35EOVFnxa3HiR29n6b1/nGT7lcxFkFZbwYfpp5xcwOVVy5WkCKwYqyq5AvDw+pvkm60JxOKvrileP/cTvw/Y/iIwK2r+hECbhCcLIXIvZphhDkDYqTZZ2uHt3Pk7BPyYTYE2ReBjvTCVkasuFEBgD4KcogvLVYsb2YcpxNYPtDKkDeJHicR1T7XkDsyDdRuYSRE4dZCtTLwvjK4jtwReFE0au5vz51qeVunuL/A6cd0njLNh+wkT0VDkrcDD7VOr6DdvTBkIaVF05wDoHbq5TrzisTyricsAf0kPv+d8cOB3QK4poZoCIp8BrC8AexWpSspiU+cTrUTSe3W6kqZmofiHa+IZSj2MfkLdHJyUwHs9cIknMoGHNpxgJatSNdqrH/6jYiAQidkWVk4HB0nyeda8KRt4dlVyAcKsZorCjm5oYnxCOxHXRwRxrA15+c4g60OyW+uZeSd+vekwboYmYp+HQ0+sf3eQpgSSNzYMjc==Uc6/-----END PGP SIGNATURE-----
C
C
Clément Lassieur wrote on 24 Jul 2018 11:23
Re: [bug#30809] [PATCH 2/2] services: Add Gitolite.
(name . Christopher Baines)(address . mail@cbaines.net)(address . 30809@debbugs.gnu.org)
87o9ext2b8.fsf@lassieur.org
Hi Christopher, thank you for the update!
Christopher Baines <mail@cbaines.net> writes:
[...]
Toggle quote (12 lines)> +(define gitolite-setup> + (match-lambda> + (($ <gitolite-configuration> package user group home> + rc-file admin-pubkey)> + #~(let ((user-info (getpwnam #$user)))> + (use-modules (guix build utils))> +> + (simple-format #t "guix: gitolite: installing ~A\n" #$rc-file)> + (copy-file #$rc-file #$(string-append home "/.gitolite.rc"))> +> + (let ((admin-pubkey #$admin-pubkey)
What's the point of that 'let'? Afterwards you reuse '$admin-pubkey':-).
Toggle quote (3 lines)> + (pubkey-file #$(string-append home "/id_rsa.pub")))> + (when admin-pubkey
If we are 'gitolite-setup', that means 'admin-pubkey' is true, I think,so that 'when' is useless.
Toggle quote (23 lines)> + ;; The key must be writable, so copy it from the store> + (copy-file #$admin-pubkey pubkey-file)> +> + (chmod pubkey-file #o500)> + (chown pubkey-file> + (passwd:uid user-info)> + (passwd:gid user-info))> +> + ;; Set the git configuration, to avoid gitolite trying to use> + ;; the hostname command, as the network might not be up yet> + (with-output-to-file #$(string-append home "/.gitconfig")> + (lambda ()> + (display "[user]> + name = GNU Guix> + email = guix@localhost> +"))))> + ;; Run Gitolite setup, as this updates the hooks and include the> + ;; admin pubkey if specified. The admin pubkey is required for> + ;; initial setup, and will replace the previous key if run after> + ;; initial setup> + (let ((pid (primitive-fork)))> + (if (eq? pid 0)
I have a slight preference for the previous 'match' expression you usedbefore, because it's used elsewhere this way and it requires less code.
Toggle quote (2 lines)> + (begin
I think that 'begin' is useless.
Toggle quote (28 lines)> + ;; Exit with a non-zero status code if an exception is thrown.> + (dynamic-wind> + (const #t)> + (lambda ()> + (setenv "HOME" (passwd:dir user-info))> + (setenv "USER" #$user)> + (setgid (passwd:gid user-info))> + (setuid (passwd:uid user-info))> + (primitive-exit> + (apply system*> + #$(file-append package "/bin/gitolite")> + "setup"> + (if admin-pubkey> + `("-pk" ,pubkey-file)> + '()))))> + (lambda ()> + (primitive-exit 1))))> + (waitpid pid)))> +> + (when (file-exists? pubkey-file)> + (delete-file pubkey-file)))))))> +> +(define (gitolite-activation config)> + (if (gitolite-configuration-admin-pubkey config)> + (gitolite-setup config)> + #~(display> + "guix: Skipping gitolite setup as the admin-pubkey has not been provided\n")))
I'm not fan of the idea that a user might: 1. setup an initial configuration with 'admin-pubkey', 2. change that configuration once the initial activation has been done.
What is the drawback to forcing the user to setup an 'admin-pubkey'?Maybe you think that doing the activation is annoying and it should onlybe done when necessary? If that's the case, maybe what we need is anad-hoc command instead of the activation, a bit like the'certbot-command' of the Certbot service.
[...]
Toggle quote (3 lines)> + (test-eq "cloning the admin repository"> + #t
test-assert
Toggle quote (15 lines)> + (invoke #$(file-append git "/bin/git")> + "clone" "-v"> + "ssh://git@localhost:2222/gitolite-admin"> + "/tmp/clone"))> +> + (with-directory-excursion "/tmp/clone"> + (invoke #$(file-append git "/bin/git")> + "-c" "user.name=Guix" "-c" "user.email=guix"> + "commit"> + "-m" "Test commit"> + "--allow-empty")> +> + (test-eq "pushing, and the associated hooks"> + #t
test-assert
Toggle quote (2 lines)> + (invoke #$(file-append git "/bin/git") "push")))
Could you confirm that if a hook fails, that test will fail?
Toggle quote (11 lines)> + (test-end)> + (exit (= (test-runner-fail-count (test-runner-current)) 0)))))> +> + (gexp->derivation "gitolite" test))> +> +(define %test-gitolite> + (system-test> + (name "gitolite")> + (description "Clone the Gitolite admin repository.")> + (value (run-gitolite-test))))
Thanks!Clément
C
C
Christopher Baines wrote on 29 Jul 2018 22:18
[PATCH 1/2] gnu: Modify the gitolite package to support the Guix service.
(address . 30809@debbugs.gnu.org)
20180729201822.12372-1-mail@cbaines.net
Previously the gitolite package worked, but there were problems using it forthe service where you might have a minimal PATH. This commit patches thesource and scripts where possible to use store paths, and also wraps thegitolite script to handle the harder dependencies.
* gnu/packages/version-control.scm (gitolite)[arguments]: Add more patching tothe patch-scripts phase, and add two new phases (patch-source andwrap-scripts).[inputs]: Add coreutils, findutils and inetutils.--- gnu/packages/version-control.scm | 53 +++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-)
Toggle diff (81 lines)diff --git a/gnu/packages/version-control.scm b/gnu/packages/version-control.scmindex 6cb335420..ca765be1a 100644--- a/gnu/packages/version-control.scm+++ b/gnu/packages/version-control.scm@@ -1026,12 +1026,48 @@ also walk each side of a merge and test those changes individually.") ((" perl -") (string-append " " perl " -"))) + (substitute* (find-files "src/triggers" ".*")+ ((" sed ")+ (string-append " " (which "sed") " ")))++ (substitute*+ '("src/triggers/post-compile/update-gitweb-access-list"+ "src/triggers/post-compile/ssh-authkeys-split"+ "src/triggers/upstream")+ ((" grep ")+ (string-append " " (which "grep") " ")))+ ;; Avoid references to the store in authorized_keys. ;; This works because gitolite-shell is in the PATH. (substitute* "src/triggers/post-compile/ssh-authkeys" (("\\$glshell \\$user") "gitolite-shell $user")) #t)))+ (add-before 'install 'patch-source+ (lambda* (#:key inputs #:allow-other-keys)+ ;; Gitolite uses cat to test the readability of the+ ;; pubkey+ (substitute* "src/lib/Gitolite/Setup.pm"+ (("\"cat ")+ (string-append "\"" (which "cat") " "))+ (("\"ssh-keygen")+ (string-append "\"" (which "ssh-keygen"))))++ (substitute* '("src/lib/Gitolite/Hooks/PostUpdate.pm"+ "src/lib/Gitolite/Hooks/Update.pm")+ (("/usr/bin/perl")+ (string-append (assoc-ref inputs "perl")+ "/bin/perl")))++ (substitute* "src/lib/Gitolite/Common.pm"+ (("\"ssh-keygen")+ (string-append "\"" (which "ssh-keygen")))+ (("\"logger\"")+ (string-append "\""+ (assoc-ref inputs "inetutils")+ "/bin/logger\"")))++ #t)) (replace 'install (lambda* (#:key outputs #:allow-other-keys) (let* ((output (assoc-ref outputs "out"))@@ -1045,9 +1081,24 @@ also walk each side of a merge and test those changes individually.") (symlink (string-append sharedir "/" script) (string-append bindir "/" script))) '("gitolite" "gitolite-shell"))+ #t)))+ (add-after 'install 'wrap-scripts+ (lambda* (#:key inputs outputs #:allow-other-keys)+ (let ((out (assoc-ref outputs "out"))+ (coreutils (assoc-ref inputs "coreutils"))+ (findutils (assoc-ref inputs "findutils"))+ (git (assoc-ref inputs "git")))+ (wrap-program (string-append out "/bin/gitolite")+ `("PATH" ":" prefix+ ,(map (lambda (dir)+ (string-append dir "/bin"))+ (list out coreutils findutils git)))) #t)))))) (inputs- `(("perl" ,perl)))+ `(("perl" ,perl)+ ("coreutils" ,coreutils)+ ("findutils" ,findutils)+ ("inetutils" ,inetutils))) ;; git and openssh are propagated because trying to patch the source via ;; regexp matching is too brittle and prone to false positives. (propagated-inputs-- 2.18.0
C
C
Christopher Baines wrote on 29 Jul 2018 22:18
[PATCH 2/2] services: Add Gitolite.
(address . 30809@debbugs.gnu.org)
20180729201822.12372-2-mail@cbaines.net
* gnu/services/version-control.scm (<gitolite-configuration>,<gitolite-rc-file>): New record types.(gitolite-accounts, gitolite-activation): New procedures.(gitolite-service-type): New variables.* gnu/tests/version-control.scm (%gitolite-test-admin-keypair, %gitolite-os,%test-gitolite): New variables.(run-gitolite-test): New procedure.* doc/guix.texi (Version Control): Document the gitolite service.--- doc/guix.texi | 94 +++++++++++++++++ gnu/services/version-control.scm | 176 ++++++++++++++++++++++++++++++- gnu/tests/version-control.scm | 114 +++++++++++++++++++- 3 files changed, 382 insertions(+), 2 deletions(-)
Toggle diff (448 lines)diff --git a/doc/guix.texi b/doc/guix.texiindex d5588066b..9b8e482d8 100644--- a/doc/guix.texi+++ b/doc/guix.texi@@ -20246,6 +20246,100 @@ could instantiate a cgit service like this: (cgitrc ""))) @end example +@subsubheading Gitolite Service++@cindex Gitolite service+@cindex Git, hosting+@uref{http://gitolite.com/gitolite/, Gitolite} is a tool for hosting Git+repositories on a central server.++Gitolite can handle multiple repositories and users, and supports flexible+configuration of the permissions for the users on the repositories.++The following example will configure Gitolite using the default @code{git}+user, and the provided SSH public key.++@example+(service gitolite-service-type+ (gitolite-configuration+ (admin-pubkey (plain-file+ "yourname.pub"+ "ssh-rsa AAAA... guix@@example.com"))))+@end example++Gitolite is configured through a special admin repository which you can clone,+for example, if you setup Gitolite on @code{example.com}, you would run the+following command to clone the admin repository.++@example+git clone git@@example.com:gitolite-admin+@end example++When the Gitolite service is activated, the provided @code{admin-pubkey} will+be inserted in to the @file{keydir} directory in the gitolite-admin+repository. If this results in a change in the repository, it will be+committed using the message ``gitolite setup by GNU Guix''.++@deftp {Data Type} gitolite-configuration+Data type representing the configuration for @code{gitolite-service-type}.++@table @asis+@item @code{package} (default: @var{gitolite})+Gitolite package to use.++@item @code{user} (default: @var{git})+User to use for Gitolite. This will be user that you use when accessing+Gitolite over SSH.++@item @code{group} (default: @var{git})+Group to use for Gitolite.++@item @code{home-directory} (default: @var{"/var/lib/gitolite"})+Directory in which to store the Gitolite configuration and repositories.++@item @code{rc-file} (default: @var{(gitolite-rc-file)})+A ``file-like'' object (@pxref{G-Expressions, file-like objects}),+representing the configuration for Gitolite.++@item @code{admin-pubkey} (default: @var{#f})+A ``file-like'' object (@pxref{G-Expressions, file-like objects}) used to+setup Gitolite. This will be inserted in to the @file{keydir} directory+within the gitolite-admin repository.++To specify the SSH key as a string, use the @code{plain-file} function.++@example+(plain-file "yourname.pub" "ssh-rsa AAAA... guix@@example.com")+@end example++@end table+@end deftp++@deftp {Data Type} gitolite-rc-file+Data type representing the Gitolite RC file.++@table @asis+@item @code{umask} (default: @code{#o0077})+This controls the permissions Gitolite sets on the repositories and their+contents.++A value like @code{#o0027} will give read access to the group used by Gitolite+(by default: @code{git}). This is necessary when using Gitolite with software+like cgit or gitweb.++@item @code{git-config-keys} (default: @code{""})+Gitolite allows you to set git config values using the "config" keyword. This+setting allows control over the config keys to accept.++@item @code{roles} (default: @code{'(("READERS" . 1) ("WRITERS" . ))})+Set the role names allowed to be used by users running the perms command.++@item @code{enable} (default: @code{'("help" "desc" "info" "perms" "writable" "ssh-authkeys" "git-config" "daemon" "gitweb")})+This setting controls the commands and features to enable within Gitolite.++@end table+@end deftp+ @node Game Services @subsubsection Game Servicesdiff --git a/gnu/services/version-control.scm b/gnu/services/version-control.scmindex 58274c8be..2afdf4a29 100644--- a/gnu/services/version-control.scm+++ b/gnu/services/version-control.scm@@ -3,6 +3,7 @@ ;;; Copyright © 2016 Sou Bunnbu <iyzsong@member.fsf.org> ;;; Copyright © 2017 Oleg Pykhalov <go.wigust@gmail.com> ;;; Copyright © 2017 Clément Lassieur <clement@lassieur.org>+;;; Copyright © 2018 Christopher Baines <mail@cbaines.net> ;;; ;;; This file is part of GNU Guix. ;;;@@ -40,7 +41,23 @@ git-http-configuration git-http-configuration?- git-http-nginx-location-configuration))+ git-http-nginx-location-configuration++ <gitolite-configuration>+ gitolite-configuration+ gitolite-configuration-package+ gitolite-configuration-user+ gitolite-configuration-rc-file+ gitolite-configuration-admin-pubkey++ <gitolite-rc-file>+ gitolite-rc-file+ gitolite-rc-file-umask+ gitolite-rc-file-git-config-keys+ gitolite-rc-file-roles+ gitolite-rc-file-enable++ gitolite-service-type)) ;;; Commentary: ;;;@@ -197,3 +214,160 @@ access to exported repositories under @file{/srv/git}." "") (list "fastcgi_param GIT_PROJECT_ROOT " git-root ";") "fastcgi_param PATH_INFO $1;"))))))++ +;;;+;;; Gitolite+;;;++(define-record-type* <gitolite-rc-file>+ gitolite-rc-file make-gitolite-rc-file+ gitolite-rc-file?+ (umask gitolite-rc-file-umask+ (default #o0077))+ (git-config-keys gitolite-rc-file-git-config-keys+ (default ""))+ (roles gitolite-rc-file-roles+ (default '(("READERS" . 1)+ ("WRITERS" . 1))))+ (enable gitolite-rc-file-enable+ (default '("help"+ "desc"+ "info"+ "perms"+ "writable"+ "ssh-authkeys"+ "git-config"+ "daemon"+ "gitweb"))))++(define-gexp-compiler (gitolite-rc-file-compiler+ (file <gitolite-rc-file>) system target)+ (match file+ (($ <gitolite-rc-file> umask git-config-keys roles enable)+ (apply text-file* "gitolite.rc"+ `("%RC = (\n"+ " UMASK => " ,(format #f "~4,'0o" umask) ",\n"+ " GIT_CONFIG_KEYS => '" ,git-config-keys "',\n"+ " ROLES => {\n"+ ,@(map (match-lambda+ ((role . value)+ (simple-format #f " ~A => ~A,\n" role value)))+ roles)+ " },\n"+ "\n"+ " ENABLE => [\n"+ ,@(map (lambda (value)+ (simple-format #f " '~A',\n" value))+ enable)+ " ],\n"+ ");\n"+ "\n"+ "1;\n")))))++(define-record-type* <gitolite-configuration>+ gitolite-configuration make-gitolite-configuration+ gitolite-configuration?+ (package gitolite-configuration-package+ (default gitolite))+ (user gitolite-configuration-user+ (default "git"))+ (group gitolite-configuration-group+ (default "git"))+ (home-directory gitolite-configuration-home-directory+ (default "/var/lib/gitolite"))+ (rc-file gitolite-configuration-rc-file+ (default (gitolite-rc-file)))+ (admin-pubkey gitolite-configuration-admin-pubkey))++(define gitolite-accounts+ (match-lambda+ (($ <gitolite-configuration> package user group home-directory+ rc-file admin-pubkey)+ ;; User group and account to run Gitolite.+ (list (user-group (name user) (system? #t))+ (user-account+ (name user)+ (group group)+ (system? #t)+ (comment "Gitolite user")+ (home-directory home-directory))))))++(define gitolite-activation+ (match-lambda+ (($ <gitolite-configuration> package user group home+ rc-file admin-pubkey)+ #~(let* ((user-info (getpwnam #$user))+ (admin-pubkey #$admin-pubkey)+ (pubkey-file (string-append+ #$home "/"+ (basename+ (strip-store-file-name admin-pubkey)))))+ (use-modules (guix build utils))++ (simple-format #t "guix: gitolite: installing ~A\n" #$rc-file)+ (copy-file #$rc-file #$(string-append home "/.gitolite.rc"))++ ;; The key must be writable, so copy it from the store+ (copy-file admin-pubkey pubkey-file)++ (chmod pubkey-file #o500)+ (chown pubkey-file+ (passwd:uid user-info)+ (passwd:gid user-info))++ ;; Set the git configuration, to avoid gitolite trying to use+ ;; the hostname command, as the network might not be up yet+ (with-output-to-file #$(string-append home "/.gitconfig")+ (lambda ()+ (display "[user]+ name = GNU Guix+ email = guix@localhost+")))+ ;; Run Gitolite setup, as this updates the hooks and include the+ ;; admin pubkey if specified. The admin pubkey is required for+ ;; initial setup, and will replace the previous key if run after+ ;; initial setup+ (let ((pid (primitive-fork)))+ (if (eq? pid 0)+ ;; Exit with a non-zero status code if an exception is thrown.+ (dynamic-wind+ (const #t)+ (lambda ()+ (setenv "HOME" (passwd:dir user-info))+ (setenv "USER" #$user)+ (setgid (passwd:gid user-info))+ (setuid (passwd:uid user-info))+ (primitive-exit+ (system* #$(file-append package "/bin/gitolite")+ "setup"+ "-m" "gitolite setup by GNU Guix"+ "-pk" pubkey-file)))+ (lambda ()+ (primitive-exit 1)))+ (waitpid pid)))++ (when (file-exists? pubkey-file)+ (delete-file pubkey-file))))))++(define gitolite-service-type+ (service-type+ (name 'gitolite)+ (extensions+ (list (service-extension activation-service-type+ gitolite-activation)+ (service-extension account-service-type+ gitolite-accounts)+ (service-extension profile-service-type+ ;; The Gitolite package in Guix uses+ ;; gitolite-shell in the authorized_keys file, so+ ;; gitolite-shell needs to be on the PATH for+ ;; gitolite to work.+ (lambda (config)+ (list+ (gitolite-configuration-package config))))))+ (description+ "Setup @command{gitolite}, a Git hosting tool providing access over SSH..+By default, the @code{git} user is used, but this is configurable.+Additionally, Gitolite can integrate with with tools like gitweb or cgit to+provide a web interface to view selected repositories.")))diff --git a/gnu/tests/version-control.scm b/gnu/tests/version-control.scmindex 3b935a1b4..4409b8a12 100644--- a/gnu/tests/version-control.scm+++ b/gnu/tests/version-control.scm@@ -2,6 +2,7 @@ ;;; Copyright © 2017, 2018 Oleg Pykhalov <go.wigust@gmail.com> ;;; Copyright © 2017, 2018 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2017, 2018 Clément Lassieur <clement@lassieur.org>+;;; Copyright © 2018 Christopher Baines <mail@cbaines.net> ;;; ;;; This file is part of GNU Guix. ;;;@@ -27,14 +28,17 @@ #:use-module (gnu services) #:use-module (gnu services version-control) #:use-module (gnu services cgit)+ #:use-module (gnu services ssh) #:use-module (gnu services web) #:use-module (gnu services networking) #:use-module (gnu packages version-control)+ #:use-module (gnu packages ssh) #:use-module (guix gexp) #:use-module (guix store) #:use-module (guix modules) #:export (%test-cgit- %test-git-http))+ %test-git-http+ %test-gitolite)) (define README-contents "Hello! This is what goes inside the 'README' file.")@@ -300,3 +304,111 @@ HTTP-PORT." (name "git-http") (description "Connect to a running Git HTTP server.") (value (run-git-http-test))))++ +;;;+;;; Gitolite.+;;;++(define %gitolite-test-admin-keypair+ (computed-file+ "gitolite-test-admin-keypair"+ (with-imported-modules (source-module-closure+ '((guix build utils)))+ #~(begin+ (use-modules (ice-9 match) (srfi srfi-26)+ (guix build utils))++ (mkdir #$output)+ (invoke #$(file-append openssh "/bin/ssh-keygen")+ "-f" (string-append #$output "/test-admin")+ "-t" "rsa"+ "-q"+ "-N" "")))))++(define %gitolite-os+ (simple-operating-system+ (dhcp-client-service)+ (service openssh-service-type)+ (service gitolite-service-type+ (gitolite-configuration+ (admin-pubkey+ (file-append %gitolite-test-admin-keypair "/test-admin.pub"))))))++(define (run-gitolite-test)+ (define os+ (marionette-operating-system+ %gitolite-os+ #:imported-modules '((gnu services herd)+ (guix combinators))))++ (define vm+ (virtual-machine+ (operating-system os)+ (port-forwardings `((2222 . 22)))))++ (define test+ (with-imported-modules '((gnu build marionette)+ (guix build utils))+ #~(begin+ (use-modules (srfi srfi-64)+ (rnrs io ports)+ (gnu build marionette)+ (guix build utils))++ (define marionette+ (make-marionette (list #$vm)))++ (mkdir #$output)+ (chdir #$output)++ (test-begin "gitolite")++ ;; Wait for sshd to be up and running.+ (test-assert "service running"+ (marionette-eval+ '(begin+ (use-modules (gnu services herd))+ (start-service 'ssh-daemon))+ marionette))++ (display #$%gitolite-test-admin-keypair)++ (setenv "GIT_SSH_VARIANT" "ssh")+ (setenv "GIT_SSH_COMMAND"+ (string-join+ '(#$(file-append openssh "/bin/ssh")+ "-i" #$(file-append %gitolite-test-admin-keypair+ "/test-admin")+ "-o" "UserKnownHostsFile=/dev/null"+ "-o" "StrictHostKeyChecking=no")))++ (test-assert "cloning the admin repository"+ (invoke #$(file-append git "/bin/git")+ "clone" "-v"+ "ssh://git@localhost:2222/gitolite-admin"+ "/tmp/clone"))++ (test-assert "admin key exists"+ (file-exists? "/tmp/clone/keydir/test-admin.pub"))++ (with-directory-excursion "/tmp/clone"+ (invoke #$(file-append git "/bin/git")+ "-c" "user.name=Guix" "-c" "user.email=guix"+ "commit"+ "-m" "Test commit"+ "--allow-empty")++ (test-assert "pushing, and the associated hooks"+ (invoke #$(file-append git "/bin/git") "push")))++ (test-end)+ (exit (= (test-runner-fail-count (test-runner-current)) 0)))))++ (gexp->derivation "gitolite" test))++(define %test-gitolite+ (system-test+ (name "gitolite")+ (description "Clone the Gitolite admin repository.")+ (value (run-gitolite-test))))-- 2.18.0
C
C
Christopher Baines wrote on 29 Jul 2018 22:45
(name . Clément Lassieur)(address . clement@lassieur.org)(address . 30809@debbugs.gnu.org)
87zhy9kbyu.fsf@cbaines.net
Clément Lassieur <clement@lassieur.org> writes:
Toggle quote (2 lines)> Hi Christopher, thank you for the update!
Thanks for taking another look. I've just send another set of revisedpatches.
Toggle quote (19 lines)> Christopher Baines <mail@cbaines.net> writes:>> [...]>>> +(define gitolite-setup>> + (match-lambda>> + (($ <gitolite-configuration> package user group home>> + rc-file admin-pubkey)>> + #~(let ((user-info (getpwnam #$user)))>> + (use-modules (guix build utils))>> +>> + (simple-format #t "guix: gitolite: installing ~A\n" #$rc-file)>> + (copy-file #$rc-file #$(string-append home "/.gitolite.rc"))>> +>> + (let ((admin-pubkey #$admin-pubkey)>> What's the point of that 'let'? Afterwards you reuse '$admin-pubkey'> :-).
Ah yeah, I've fixed that now.
Toggle quote (6 lines)>> + (pubkey-file #$(string-append home "/id_rsa.pub")))>> + (when admin-pubkey>> If we are 'gitolite-setup', that means 'admin-pubkey' is true, I think,> so that 'when' is useless.
Indeed. I've removed the gitolite-setup function now, along with thisconditional.
Toggle quote (26 lines)>> + ;; The key must be writable, so copy it from the store>> + (copy-file #$admin-pubkey pubkey-file)>> +>> + (chmod pubkey-file #o500)>> + (chown pubkey-file>> + (passwd:uid user-info)>> + (passwd:gid user-info))>> +>> + ;; Set the git configuration, to avoid gitolite trying to use>> + ;; the hostname command, as the network might not be up yet>> + (with-output-to-file #$(string-append home "/.gitconfig")>> + (lambda ()>> + (display "[user]>> + name = GNU Guix>> + email = guix@localhost>> +"))))>> + ;; Run Gitolite setup, as this updates the hooks and include the>> + ;; admin pubkey if specified. The admin pubkey is required for>> + ;; initial setup, and will replace the previous key if run after>> + ;; initial setup>> + (let ((pid (primitive-fork)))>> + (if (eq? pid 0)>> I have a slight preference for the previous 'match' expression you used> before, because it's used elsewhere this way and it requires less code.
While I agree with both your points, I tried for quite a while lastweekend to get match to work, and couldn't. I couldn't even tell why itsuddenly wasn't. Unfortunately, Linux panicing when anything fails makesdebugging the system test a bit tricky.
Toggle quote (4 lines)>> + (begin>> I think that 'begin' is useless.
Yeah, I think I added that while trying to get match to work. I'veremoved it now.
Toggle quote (39 lines)>> + ;; Exit with a non-zero status code if an exception is thrown.>> + (dynamic-wind>> + (const #t)>> + (lambda ()>> + (setenv "HOME" (passwd:dir user-info))>> + (setenv "USER" #$user)>> + (setgid (passwd:gid user-info))>> + (setuid (passwd:uid user-info))>> + (primitive-exit>> + (apply system*>> + #$(file-append package "/bin/gitolite")>> + "setup">> + (if admin-pubkey>> + `("-pk" ,pubkey-file)>> + '()))))>> + (lambda ()>> + (primitive-exit 1))))>> + (waitpid pid)))>> +>> + (when (file-exists? pubkey-file)>> + (delete-file pubkey-file)))))))>> +>> +(define (gitolite-activation config)>> + (if (gitolite-configuration-admin-pubkey config)>> + (gitolite-setup config)>> + #~(display>> + "guix: Skipping gitolite setup as the admin-pubkey has not been provided\n")))>> I'm not fan of the idea that a user might:> 1. setup an initial configuration with 'admin-pubkey',> 2. change that configuration once the initial activation has been> done.>> What is the drawback to forcing the user to setup an 'admin-pubkey'?> Maybe you think that doing the activation is annoying and it should only> be done when necessary? If that's the case, maybe what we need is an> ad-hoc command instead of the activation, a bit like the> 'certbot-command' of the Certbot service.
I wrote it this way as this is how I've been using Gitolite so far. OnDebian, I think debconf prompts you for the key when you install thepackage, and runs gitolite setup.
I've actually read the gitolite setup script now, and its behaviour itpretty reasonable if it's run frequently. As I understand it, it ensuresthat the provided admin-pubkey exists in the keydir directory in thegitolite-admin repository, and will commit to the repository if itchanges anything.
So, I think I've now changed both the service and the documentation todescribe adding the admin-pubkey always.
Toggle quote (10 lines)>> + (test-eq "cloning the admin repository">> + #t>> test-assert>>> + (test-eq "pushing, and the associated hooks">> + #t>> test-assert
I've changed these now :)
Toggle quote (4 lines)>> + (invoke #$(file-append git "/bin/git") "push")))>> Could you confirm that if a hook fails, that test will fail?
Yep, I added this check when I realised that the hooks were broken.
-----BEGIN PGP SIGNATURE-----
iQKTBAEBCgB9FiEEPonu50WOcg2XVOCyXiijOwuE9XcFAlteJ2lfFIAAAAAALgAoaXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldDNFODlFRUU3NDU4RTcyMEQ5NzU0RTBCMjVFMjhBMzNCMEI4NEY1NzcACgkQXiijOwuE9XeW3xAAntZSanenOHsLxeMnfXl+IHhS5mzNNDbm3WG0G5J+u8xq2KLJFUKASD1tI4FYoTCtzAdFZVHKe/dmZCzp3ydFrC38UtHGbx4L4tfEiuX8HHQIUqz/QI3P+/lUXvsZuFsHWYhapVj278KcJN4O3YLHNt+NstKpTm8h5/upkRM9hB69H3Ku65Z16xLsVG1rmBn5JAf+nw2JLJXgBNybzwGkIoT5FNlXth4io4rPwItAhTGfK+pfqfI16eUEZcI0O99/UH5pQI2f92HkJe/NK9l1RdNYEA+QKViGUHC0hr6lruQon6QLCpCLrVnERiBMXC4x94uB6AoPfNfzaSfdzEdffX+crxIPtr67Ehv9989H7PZo+xeWlM6IC+crYIIGCBykyAz0AkGBn0EVG9qy0jzOI7VEgJBpMznc4xzK+qPPUgnJK2mp1R5gzLeEUBp38uyuiHATTmOgrr+S8z//iHugW4atlbsREpKKnkzaHXYIUpVXhJ4d5n5JPoDw0iwHSun5jIstAndHSF2CnGMfRNiluGlZpfUrBUwnvIuV2G3foQABCXQ1GpmuWK/CCF958dzzD+rWlX9+6dpp2BMZafnDaU+2LEWUjQIiK8oiiST7/Y+DDCpgaBeer9dS3D37wIC9+LEnxy3/WcayxwDTO34Tb8RwhhwIKRBFb4prgVb7fzo==YoxP-----END PGP SIGNATURE-----
C
C
Clément Lassieur wrote on 30 Jul 2018 20:26
(name . Christopher Baines)(address . mail@cbaines.net)(address . 30809@debbugs.gnu.org)
87tvog8trt.fsf@lassieur.org
Christopher Baines <mail@cbaines.net> writes:
[...]
Toggle quote (7 lines)>>> +(define gitolite-setup>>> + (match-lambda>>> + (($ <gitolite-configuration> package user group home>>> + rc-file admin-pubkey)>>> + #~(let ((user-info (getpwnam #$user)))>>> + (use-modules (guix build utils))
-----------------(ice-9 match)----^
Toggle quote (6 lines)>>> +>>> + (simple-format #t "guix: gitolite: installing ~A\n" #$rc-file)>>> + (copy-file #$rc-file #$(string-append home "/.gitolite.rc"))>>> +>>> + (let ((admin-pubkey #$admin-pubkey)
[...]
Toggle quote (8 lines)>> I have a slight preference for the previous 'match' expression you used>> before, because it's used elsewhere this way and it requires less code.>> While I agree with both your points, I tried for quite a while last> weekend to get match to work, and couldn't. I couldn't even tell why it> suddenly wasn't. Unfortunately, Linux panicing when anything fails makes> debugging the system test a bit tricky.
Maybe you forgot to add the (ice-9 match) module?
C
C
Clément Lassieur wrote on 31 Jul 2018 01:39
(name . Christopher Baines)(address . mail@cbaines.net)(address . 30809@debbugs.gnu.org)
87r2jk8faj.fsf@lassieur.org
Hey Christopher!
Thank you for the update.
Christopher Baines <mail@cbaines.net> writes:
[...]
Toggle quote (17 lines)> +@example> +git clone git@@example.com:gitolite-admin> +@end example> +> +When the Gitolite service is activated, the provided @code{admin-pubkey} will> +be inserted in to the @file{keydir} directory in the gitolite-admin> +repository. If this results in a change in the repository, it will be> +committed using the message ``gitolite setup by GNU Guix''.> +> +@deftp {Data Type} gitolite-configuration> +Data type representing the configuration for @code{gitolite-service-type}.> +> +@table @asis> +@item @code{package} (default: @var{gitolite})> +Gitolite package to use.> +> +@item @code{user} (default: @var{git})
^It should be a string ---------------
I don't think you should use @var for default values. @code would be better.
Toggle quote (4 lines)> +User to use for Gitolite. This will be user that you use when accessing> +Gitolite over SSH.> +> +@item @code{group} (default: @var{git})
^It should be a string ---------------
Toggle quote (11 lines)> +Group to use for Gitolite.> +> +@item @code{home-directory} (default: @var{"/var/lib/gitolite"})> +Directory in which to store the Gitolite configuration and repositories.> +> +@item @code{rc-file} (default: @var{(gitolite-rc-file)})> +A ``file-like'' object (@pxref{G-Expressions, file-like objects}),> +representing the configuration for Gitolite.> +> +@item @code{admin-pubkey} (default: @var{#f})
Actually, there is no default :-)
[...]
Toggle quote (13 lines)> + (match-lambda> + (($ <gitolite-configuration> package user group home> + rc-file admin-pubkey)> + #~(let* ((user-info (getpwnam #$user))> + (admin-pubkey #$admin-pubkey)> + (pubkey-file (string-append> + #$home "/"> + (basename> + (strip-store-file-name admin-pubkey)))))> + (use-modules (guix build utils))> +> + (simple-format #t "guix: gitolite: installing ~A\n" #$rc-file)> + (copy-file #$rc-file #$(string-append home "/.gitolite.rc"))
^Maybe a symlink here?
Toggle quote (5 lines)> + ;; The key must be writable, so copy it from the store> + (copy-file admin-pubkey pubkey-file)> +> + (chmod pubkey-file #o500)
I don't think it must be writable, because #o500 isn't writable.
Toggle quote (35 lines)> + (chown pubkey-file> + (passwd:uid user-info)> + (passwd:gid user-info))> +> + ;; Set the git configuration, to avoid gitolite trying to use> + ;; the hostname command, as the network might not be up yet> + (with-output-to-file #$(string-append home "/.gitconfig")> + (lambda ()> + (display "[user]> + name = GNU Guix> + email = guix@localhost> +")))> + ;; Run Gitolite setup, as this updates the hooks and include the> + ;; admin pubkey if specified. The admin pubkey is required for> + ;; initial setup, and will replace the previous key if run after> + ;; initial setup> + (let ((pid (primitive-fork)))> + (if (eq? pid 0)> + ;; Exit with a non-zero status code if an exception is thrown.> + (dynamic-wind> + (const #t)> + (lambda ()> + (setenv "HOME" (passwd:dir user-info))> + (setenv "USER" #$user)> + (setgid (passwd:gid user-info))> + (setuid (passwd:uid user-info))> + (primitive-exit> + (system* #$(file-append package "/bin/gitolite")> + "setup"> + "-m" "gitolite setup by GNU Guix"> + "-pk" pubkey-file)))> + (lambda ()> + (primitive-exit 1)))> + (waitpid pid)))
This works (with the (ice-9 match) module added):
(match (primitive-fork) (0 ;; Exit with a non-zero status code if an exception is thrown. (dynamic-wind (const #t) (lambda () (setenv "HOME" (passwd:dir user-info)) (setenv "USER" #$user) (setgid (passwd:gid user-info)) (setuid (passwd:uid user-info)) (primitive-exit (system* #$(file-append package "/bin/gitolite") "setup" "-m" "gitolite setup by GNU Guix" "-pk" pubkey-file))) (lambda () (primitive-exit 1)))) (pid (waitpid pid)))
Other than that, it looks good to me!
Thanks again,Clément
C
C
Christopher Baines wrote on 31 Jul 2018 23:39
[PATCH 1/2] gnu: Modify the gitolite package to support the Guix service.
(address . 30809@debbugs.gnu.org)
20180731213945.12930-1-mail@cbaines.net
Previously the gitolite package worked, but there were problems using it forthe service where you might have a minimal PATH. This commit patches thesource and scripts where possible to use store paths, and also wraps thegitolite script to handle the harder dependencies.
* gnu/packages/version-control.scm (gitolite)[arguments]: Add more patching tothe patch-scripts phase, and add two new phases (patch-source andwrap-scripts).[inputs]: Add coreutils, findutils and inetutils.--- gnu/packages/version-control.scm | 53 +++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-)
Toggle diff (81 lines)diff --git a/gnu/packages/version-control.scm b/gnu/packages/version-control.scmindex 3db5796b4..70fd40d87 100644--- a/gnu/packages/version-control.scm+++ b/gnu/packages/version-control.scm@@ -1026,12 +1026,48 @@ also walk each side of a merge and test those changes individually.") ((" perl -") (string-append " " perl " -"))) + (substitute* (find-files "src/triggers" ".*")+ ((" sed ")+ (string-append " " (which "sed") " ")))++ (substitute*+ '("src/triggers/post-compile/update-gitweb-access-list"+ "src/triggers/post-compile/ssh-authkeys-split"+ "src/triggers/upstream")+ ((" grep ")+ (string-append " " (which "grep") " ")))+ ;; Avoid references to the store in authorized_keys. ;; This works because gitolite-shell is in the PATH. (substitute* "src/triggers/post-compile/ssh-authkeys" (("\\$glshell \\$user") "gitolite-shell $user")) #t)))+ (add-before 'install 'patch-source+ (lambda* (#:key inputs #:allow-other-keys)+ ;; Gitolite uses cat to test the readability of the+ ;; pubkey+ (substitute* "src/lib/Gitolite/Setup.pm"+ (("\"cat ")+ (string-append "\"" (which "cat") " "))+ (("\"ssh-keygen")+ (string-append "\"" (which "ssh-keygen"))))++ (substitute* '("src/lib/Gitolite/Hooks/PostUpdate.pm"+ "src/lib/Gitolite/Hooks/Update.pm")+ (("/usr/bin/perl")+ (string-append (assoc-ref inputs "perl")+ "/bin/perl")))++ (substitute* "src/lib/Gitolite/Common.pm"+ (("\"ssh-keygen")+ (string-append "\"" (which "ssh-keygen")))+ (("\"logger\"")+ (string-append "\""+ (assoc-ref inputs "inetutils")+ "/bin/logger\"")))++ #t)) (replace 'install (lambda* (#:key outputs #:allow-other-keys) (let* ((output (assoc-ref outputs "out"))@@ -1045,9 +1081,24 @@ also walk each side of a merge and test those changes individually.") (symlink (string-append sharedir "/" script) (string-append bindir "/" script))) '("gitolite" "gitolite-shell"))+ #t)))+ (add-after 'install 'wrap-scripts+ (lambda* (#:key inputs outputs #:allow-other-keys)+ (let ((out (assoc-ref outputs "out"))+ (coreutils (assoc-ref inputs "coreutils"))+ (findutils (assoc-ref inputs "findutils"))+ (git (assoc-ref inputs "git")))+ (wrap-program (string-append out "/bin/gitolite")+ `("PATH" ":" prefix+ ,(map (lambda (dir)+ (string-append dir "/bin"))+ (list out coreutils findutils git)))) #t)))))) (inputs- `(("perl" ,perl)))+ `(("perl" ,perl)+ ("coreutils" ,coreutils)+ ("findutils" ,findutils)+ ("inetutils" ,inetutils))) ;; git and openssh are propagated because trying to patch the source via ;; regexp matching is too brittle and prone to false positives. (propagated-inputs-- 2.18.0
C
C
Christopher Baines wrote on 31 Jul 2018 23:39
[PATCH 2/2] services: Add Gitolite.
(address . 30809@debbugs.gnu.org)
20180731213945.12930-2-mail@cbaines.net
* gnu/services/version-control.scm (<gitolite-configuration>,<gitolite-rc-file>): New record types.(gitolite-accounts, gitolite-activation): New procedures.(gitolite-service-type): New variables.* gnu/tests/version-control.scm (%gitolite-test-admin-keypair, %gitolite-os,%test-gitolite): New variables.(run-gitolite-test): New procedure.* doc/guix.texi (Version Control): Document the gitolite service.--- doc/guix.texi | 94 ++++++++++++++++++ gnu/services/version-control.scm | 165 ++++++++++++++++++++++++++++++- gnu/tests/version-control.scm | 114 ++++++++++++++++++++- 3 files changed, 371 insertions(+), 2 deletions(-)
Toggle diff (437 lines)diff --git a/doc/guix.texi b/doc/guix.texiindex 080b091b3..e59d7bacd 100644--- a/doc/guix.texi+++ b/doc/guix.texi@@ -20246,6 +20246,100 @@ could instantiate a cgit service like this: (cgitrc ""))) @end example +@subsubheading Gitolite Service++@cindex Gitolite service+@cindex Git, hosting+@uref{http://gitolite.com/gitolite/, Gitolite} is a tool for hosting Git+repositories on a central server.++Gitolite can handle multiple repositories and users, and supports flexible+configuration of the permissions for the users on the repositories.++The following example will configure Gitolite using the default @code{git}+user, and the provided SSH public key.++@example+(service gitolite-service-type+ (gitolite-configuration+ (admin-pubkey (plain-file+ "yourname.pub"+ "ssh-rsa AAAA... guix@@example.com"))))+@end example++Gitolite is configured through a special admin repository which you can clone,+for example, if you setup Gitolite on @code{example.com}, you would run the+following command to clone the admin repository.++@example+git clone git@@example.com:gitolite-admin+@end example++When the Gitolite service is activated, the provided @code{admin-pubkey} will+be inserted in to the @file{keydir} directory in the gitolite-admin+repository. If this results in a change in the repository, it will be+committed using the message ``gitolite setup by GNU Guix''.++@deftp {Data Type} gitolite-configuration+Data type representing the configuration for @code{gitolite-service-type}.++@table @asis+@item @code{package} (default: @var{gitolite})+Gitolite package to use.++@item @code{user} (default: @code{"git"})+User to use for Gitolite. This will be user that you use when accessing+Gitolite over SSH.++@item @code{group} (default: @code{"git"})+Group to use for Gitolite.++@item @code{home-directory} (default: @code{"/var/lib/gitolite"})+Directory in which to store the Gitolite configuration and repositories.++@item @code{rc-file} (default: @code{(gitolite-rc-file)})+A ``file-like'' object (@pxref{G-Expressions, file-like objects}),+representing the configuration for Gitolite.++@item @code{admin-pubkey}+A ``file-like'' object (@pxref{G-Expressions, file-like objects}) used to+setup Gitolite. This will be inserted in to the @file{keydir} directory+within the gitolite-admin repository.++To specify the SSH key as a string, use the @code{plain-file} function.++@example+(plain-file "yourname.pub" "ssh-rsa AAAA... guix@@example.com")+@end example++@end table+@end deftp++@deftp {Data Type} gitolite-rc-file+Data type representing the Gitolite RC file.++@table @asis+@item @code{umask} (default: @code{#o0077})+This controls the permissions Gitolite sets on the repositories and their+contents.++A value like @code{#o0027} will give read access to the group used by Gitolite+(by default: @code{git}). This is necessary when using Gitolite with software+like cgit or gitweb.++@item @code{git-config-keys} (default: @code{""})+Gitolite allows you to set git config values using the "config" keyword. This+setting allows control over the config keys to accept.++@item @code{roles} (default: @code{'(("READERS" . 1) ("WRITERS" . ))})+Set the role names allowed to be used by users running the perms command.++@item @code{enable} (default: @code{'("help" "desc" "info" "perms" "writable" "ssh-authkeys" "git-config" "daemon" "gitweb")})+This setting controls the commands and features to enable within Gitolite.++@end table+@end deftp+ @node Game Services @subsubsection Game Servicesdiff --git a/gnu/services/version-control.scm b/gnu/services/version-control.scmindex 58274c8be..555028d43 100644--- a/gnu/services/version-control.scm+++ b/gnu/services/version-control.scm@@ -3,6 +3,7 @@ ;;; Copyright © 2016 Sou Bunnbu <iyzsong@member.fsf.org> ;;; Copyright © 2017 Oleg Pykhalov <go.wigust@gmail.com> ;;; Copyright © 2017 Clément Lassieur <clement@lassieur.org>+;;; Copyright © 2018 Christopher Baines <mail@cbaines.net> ;;; ;;; This file is part of GNU Guix. ;;;@@ -40,7 +41,23 @@ git-http-configuration git-http-configuration?- git-http-nginx-location-configuration))+ git-http-nginx-location-configuration++ <gitolite-configuration>+ gitolite-configuration+ gitolite-configuration-package+ gitolite-configuration-user+ gitolite-configuration-rc-file+ gitolite-configuration-admin-pubkey++ <gitolite-rc-file>+ gitolite-rc-file+ gitolite-rc-file-umask+ gitolite-rc-file-git-config-keys+ gitolite-rc-file-roles+ gitolite-rc-file-enable++ gitolite-service-type)) ;;; Commentary: ;;;@@ -197,3 +214,149 @@ access to exported repositories under @file{/srv/git}." "") (list "fastcgi_param GIT_PROJECT_ROOT " git-root ";") "fastcgi_param PATH_INFO $1;"))))))++ +;;;+;;; Gitolite+;;;++(define-record-type* <gitolite-rc-file>+ gitolite-rc-file make-gitolite-rc-file+ gitolite-rc-file?+ (umask gitolite-rc-file-umask+ (default #o0077))+ (git-config-keys gitolite-rc-file-git-config-keys+ (default ""))+ (roles gitolite-rc-file-roles+ (default '(("READERS" . 1)+ ("WRITERS" . 1))))+ (enable gitolite-rc-file-enable+ (default '("help"+ "desc"+ "info"+ "perms"+ "writable"+ "ssh-authkeys"+ "git-config"+ "daemon"+ "gitweb"))))++(define-gexp-compiler (gitolite-rc-file-compiler+ (file <gitolite-rc-file>) system target)+ (match file+ (($ <gitolite-rc-file> umask git-config-keys roles enable)+ (apply text-file* "gitolite.rc"+ `("%RC = (\n"+ " UMASK => " ,(format #f "~4,'0o" umask) ",\n"+ " GIT_CONFIG_KEYS => '" ,git-config-keys "',\n"+ " ROLES => {\n"+ ,@(map (match-lambda+ ((role . value)+ (simple-format #f " ~A => ~A,\n" role value)))+ roles)+ " },\n"+ "\n"+ " ENABLE => [\n"+ ,@(map (lambda (value)+ (simple-format #f " '~A',\n" value))+ enable)+ " ],\n"+ ");\n"+ "\n"+ "1;\n")))))++(define-record-type* <gitolite-configuration>+ gitolite-configuration make-gitolite-configuration+ gitolite-configuration?+ (package gitolite-configuration-package+ (default gitolite))+ (user gitolite-configuration-user+ (default "git"))+ (group gitolite-configuration-group+ (default "git"))+ (home-directory gitolite-configuration-home-directory+ (default "/var/lib/gitolite"))+ (rc-file gitolite-configuration-rc-file+ (default (gitolite-rc-file)))+ (admin-pubkey gitolite-configuration-admin-pubkey))++(define gitolite-accounts+ (match-lambda+ (($ <gitolite-configuration> package user group home-directory+ rc-file admin-pubkey)+ ;; User group and account to run Gitolite.+ (list (user-group (name user) (system? #t))+ (user-account+ (name user)+ (group group)+ (system? #t)+ (comment "Gitolite user")+ (home-directory home-directory))))))++(define gitolite-activation+ (match-lambda+ (($ <gitolite-configuration> package user group home+ rc-file admin-pubkey)+ #~(let* ((user-info (getpwnam #$user))+ (admin-pubkey #$admin-pubkey)+ (pubkey-file (string-append+ #$home "/"+ (basename+ (strip-store-file-name admin-pubkey))))+ (installed-rc-file+ #$(string-append home "/.gitolite.rc")))+ (use-modules (guix build utils))++ (simple-format #t "guix: gitolite: installing ~A\n" #$rc-file)+ (false-if-exception (delete-file installed-rc-file))+ (symlink #$rc-file installed-rc-file)++ ;; Set the git configuration, to avoid gitolite trying to use+ ;; the hostname command, as the network might not be up yet+ (with-output-to-file #$(string-append home "/.gitconfig")+ (lambda ()+ (display "[user]+ name = GNU Guix+ email = guix@localhost+")))+ ;; Run Gitolite setup, as this updates the hooks and the admin-pubkey+ (let ((pid (primitive-fork)))+ (if (eq? pid 0)+ ;; Exit with a non-zero status code if an exception is thrown.+ (dynamic-wind+ (const #t)+ (lambda ()+ (setenv "HOME" (passwd:dir user-info))+ (setenv "USER" #$user)+ (setgid (passwd:gid user-info))+ (setuid (passwd:uid user-info))+ (primitive-exit+ (system* #$(file-append package "/bin/gitolite")+ "setup"+ "-m" "gitolite setup by GNU Guix"+ "-pk" admin-pubkey)))+ (lambda ()+ (primitive-exit 1)))+ (waitpid pid)))))))++(define gitolite-service-type+ (service-type+ (name 'gitolite)+ (extensions+ (list (service-extension activation-service-type+ gitolite-activation)+ (service-extension account-service-type+ gitolite-accounts)+ (service-extension profile-service-type+ ;; The Gitolite package in Guix uses+ ;; gitolite-shell in the authorized_keys file, so+ ;; gitolite-shell needs to be on the PATH for+ ;; gitolite to work.+ (lambda (config)+ (list+ (gitolite-configuration-package config))))))+ (description+ "Setup @command{gitolite}, a Git hosting tool providing access over SSH..+By default, the @code{git} user is used, but this is configurable.+Additionally, Gitolite can integrate with with tools like gitweb or cgit to+provide a web interface to view selected repositories.")))diff --git a/gnu/tests/version-control.scm b/gnu/tests/version-control.scmindex 3b935a1b4..4409b8a12 100644--- a/gnu/tests/version-control.scm+++ b/gnu/tests/version-control.scm@@ -2,6 +2,7 @@ ;;; Copyright © 2017, 2018 Oleg Pykhalov <go.wigust@gmail.com> ;;; Copyright © 2017, 2018 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2017, 2018 Clément Lassieur <clement@lassieur.org>+;;; Copyright © 2018 Christopher Baines <mail@cbaines.net> ;;; ;;; This file is part of GNU Guix. ;;;@@ -27,14 +28,17 @@ #:use-module (gnu services) #:use-module (gnu services version-control) #:use-module (gnu services cgit)+ #:use-module (gnu services ssh) #:use-module (gnu services web) #:use-module (gnu services networking) #:use-module (gnu packages version-control)+ #:use-module (gnu packages ssh) #:use-module (guix gexp) #:use-module (guix store) #:use-module (guix modules) #:export (%test-cgit- %test-git-http))+ %test-git-http+ %test-gitolite)) (define README-contents "Hello! This is what goes inside the 'README' file.")@@ -300,3 +304,111 @@ HTTP-PORT." (name "git-http") (description "Connect to a running Git HTTP server.") (value (run-git-http-test))))++ +;;;+;;; Gitolite.+;;;++(define %gitolite-test-admin-keypair+ (computed-file+ "gitolite-test-admin-keypair"+ (with-imported-modules (source-module-closure+ '((guix build utils)))+ #~(begin+ (use-modules (ice-9 match) (srfi srfi-26)+ (guix build utils))++ (mkdir #$output)+ (invoke #$(file-append openssh "/bin/ssh-keygen")+ "-f" (string-append #$output "/test-admin")+ "-t" "rsa"+ "-q"+ "-N" "")))))++(define %gitolite-os+ (simple-operating-system+ (dhcp-client-service)+ (service openssh-service-type)+ (service gitolite-service-type+ (gitolite-configuration+ (admin-pubkey+ (file-append %gitolite-test-admin-keypair "/test-admin.pub"))))))++(define (run-gitolite-test)+ (define os+ (marionette-operating-system+ %gitolite-os+ #:imported-modules '((gnu services herd)+ (guix combinators))))++ (define vm+ (virtual-machine+ (operating-system os)+ (port-forwardings `((2222 . 22)))))++ (define test+ (with-imported-modules '((gnu build marionette)+ (guix build utils))+ #~(begin+ (use-modules (srfi srfi-64)+ (rnrs io ports)+ (gnu build marionette)+ (guix build utils))++ (define marionette+ (make-marionette (list #$vm)))++ (mkdir #$output)+ (chdir #$output)++ (test-begin "gitolite")++ ;; Wait for sshd to be up and running.+ (test-assert "service running"+ (marionette-eval+ '(begin+ (use-modules (gnu services herd))+ (start-service 'ssh-daemon))+ marionette))++ (display #$%gitolite-test-admin-keypair)++ (setenv "GIT_SSH_VARIANT" "ssh")+ (setenv "GIT_SSH_COMMAND"+ (string-join+ '(#$(file-append openssh "/bin/ssh")+ "-i" #$(file-append %gitolite-test-admin-keypair+ "/test-admin")+ "-o" "UserKnownHostsFile=/dev/null"+ "-o" "StrictHostKeyChecking=no")))++ (test-assert "cloning the admin repository"+ (invoke #$(file-append git "/bin/git")+ "clone" "-v"+ "ssh://git@localhost:2222/gitolite-admin"+ "/tmp/clone"))++ (test-assert "admin key exists"+ (file-exists? "/tmp/clone/keydir/test-admin.pub"))++ (with-directory-excursion "/tmp/clone"+ (invoke #$(file-append git "/bin/git")+ "-c" "user.name=Guix" "-c" "user.email=guix"+ "commit"+ "-m" "Test commit"+ "--allow-empty")++ (test-assert "pushing, and the associated hooks"+ (invoke #$(file-append git "/bin/git") "push")))++ (test-end)+ (exit (= (test-runner-fail-count (test-runner-current)) 0)))))++ (gexp->derivation "gitolite" test))++(define %test-gitolite+ (system-test+ (name "gitolite")+ (description "Clone the Gitolite admin repository.")+ (value (run-gitolite-test))))-- 2.18.0
C
C
Christopher Baines wrote on 31 Jul 2018 23:40
(name . Clément Lassieur)(address . clement@lassieur.org)(address . 30809@debbugs.gnu.org)
87wotbm6db.fsf@cbaines.net
Clément Lassieur <clement@lassieur.org> writes:
Toggle quote (4 lines)> Hey Christopher!>> Thank you for the update.
Thanks for taking another look, I've sent some updated patches again.
Toggle quote (26 lines)> Christopher Baines <mail@cbaines.net> writes:>> [...]>>> +@example>> +git clone git@@example.com:gitolite-admin>> +@end example>> +>> +When the Gitolite service is activated, the provided @code{admin-pubkey} will>> +be inserted in to the @file{keydir} directory in the gitolite-admin>> +repository. If this results in a change in the repository, it will be>> +committed using the message ``gitolite setup by GNU Guix''.>> +>> +@deftp {Data Type} gitolite-configuration>> +Data type representing the configuration for @code{gitolite-service-type}.>> +>> +@table @asis>> +@item @code{package} (default: @var{gitolite})>> +Gitolite package to use.>> +>> +@item @code{user} (default: @var{git})> ^> It should be a string --------------->> I don't think you should use @var for default values. @code would be better.
Ah, ok, I think I've corrected these issues where appropriate.
Toggle quote (4 lines)>> +@item @code{admin-pubkey} (default: @var{#f})>> Actually, there is no default :-)
Good spot, I've removed it now.
Toggle quote (16 lines)>> + (match-lambda>> + (($ <gitolite-configuration> package user group home>> + rc-file admin-pubkey)>> + #~(let* ((user-info (getpwnam #$user))>> + (admin-pubkey #$admin-pubkey)>> + (pubkey-file (string-append>> + #$home "/">> + (basename>> + (strip-store-file-name admin-pubkey)))))>> + (use-modules (guix build utils))>> +>> + (simple-format #t "guix: gitolite: installing ~A\n" #$rc-file)>> + (copy-file #$rc-file #$(string-append home "/.gitolite.rc"))> ^> Maybe a symlink here?
I had some concerns that the store item might be removed, but I guess itmust be safe as it's referenced by the activation script. I've nowchanged it to use a symlink.
Toggle quote (7 lines)>> + ;; The key must be writable, so copy it from the store>> + (copy-file admin-pubkey pubkey-file)>> +>> + (chmod pubkey-file #o500)>> I don't think it must be writable, because #o500 isn't writable.
I can't quite remember why I added this... I've removed it, andeverything still seems to work.
Toggle quote (25 lines)>> + ;; Run Gitolite setup, as this updates the hooks and include the>> + ;; admin pubkey if specified. The admin pubkey is required for>> + ;; initial setup, and will replace the previous key if run after>> + ;; initial setup>> + (let ((pid (primitive-fork)))>> + (if (eq? pid 0)>> + ;; Exit with a non-zero status code if an exception is thrown.>> + (dynamic-wind>> + (const #t)>> + (lambda ()>> + (setenv "HOME" (passwd:dir user-info))>> + (setenv "USER" #$user)>> + (setgid (passwd:gid user-info))>> + (setuid (passwd:uid user-info))>> + (primitive-exit>> + (system* #$(file-append package "/bin/gitolite")>> + "setup">> + "-m" "gitolite setup by GNU Guix">> + "-pk" pubkey-file)))>> + (lambda ()>> + (primitive-exit 1)))>> + (waitpid pid)))>> This works (with the (ice-9 match) module added):
Unfortunately, when I try, I'm still hitting the same problem. To betterexplain, match seems to run the code for the forked process, in bothprocesses. Adding in some peek statements [1] gives:
;;; ("FORK" 273)
;;; ("PID SHOULD BE 0")
;;; ("FORK" 0)
;;; ("PID SHOULD BE 0")
[ 1.817611] Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000000

This can't be due to a missing import, as removing the import gives adifferent error message.
Unbound variable: match [ 1.638616] Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000000

I'm at a loss regarding what is going on here. I've tried testing on topof 8b8978ade and a previous commit, I've also reproduced this on twodifferent computers.
I've pushed up a branch here [2] in case you're interested in checkingout the exact code I'm using.

1: (match (peek "FORK" (primitive-fork)) (0 ;; Exit with a non-zero status code if an exception is thrown. (dynamic-wind (const #t) (lambda () (setenv "HOME" (passwd:dir user-info)) (setenv "USER" #$user) (setgid (passwd:gid user-info)) (setuid (passwd:uid user-info)) (peek "PID SHOULD BE 0") (primitive-exit (system* #$(file-append package "/bin/gitolite") "setup" "-m" "gitolite setup by GNU Guix" "-pk" pubkey-file))) (lambda () (primitive-exit 1)))) (pid (waitpid (peek "WAITING FOR PID ->" pid))))
2: https://git.cbaines.net/guix/commit/?h=gitolite-service-broken-match&id=b70a26a7875e0d1106290d583ee34db7159bbf60
-----BEGIN PGP SIGNATURE-----
iQKTBAEBCgB9FiEEPonu50WOcg2XVOCyXiijOwuE9XcFAltg10BfFIAAAAAALgAoaXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldDNFODlFRUU3NDU4RTcyMEQ5NzU0RTBCMjVFMjhBMzNCMEI4NEY1NzcACgkQXiijOwuE9XfYPA/9FJDeM6CSCqIT2EZZwD0M1nJ0wXbpQfsvEjb3OGlQohM6xooVbIAZFJ0RKMtpz6YQFNeT9nANCzJW5Zxz7Cf3XqstVEQncSZM6iy+jNKWwIz/beXxE15MG/3kKraZ4OsiRDFaKXM1/lI3rvqx2raWiBpzCSe/A4f1P+xu/iRfr/9dCsavJl4hXHzvgcDMLZ9I6pXovvBaibGIDWn3mtlP0txxaJovqc0esb/WZuo4clxRKccreCmX9uTtmutMl6UUbuOftcR/oxlKbTcdI7brvGiNqS9ETC+80wI+67TFhrpI3CRSepkj0NwnZdQSBz4YOovCiTK3sNyRI2HU5Ub4o0RdxaqfJ6mfMc6NtMcSLksf7g8+0Bx/3+KpAngTE3QzLAl6gXkOy5E1b1pZBMVg8rI4UN5A6NnZNz0OQ9fV9Vr7FpGh8UbzEuPf/4zNx3wq1btrKK5kqjXep0kI5lWMYgIn6EIrZKCBCG8GuWl5Y1/4+nR5rT0IPdWwbd7m9EepMEn1ZXIxiBdHmp2FZh8FQq6k1e6DMdkI16psk6IS/baIuPfOGeIZtpq+QsOv8a6dKi6y6f3RgbEDbJz+lAUSN+YjDjcvzOOELHao6ziZbW2PCeTOizpaas3R2IM5BIqPwErVvP4nagX61DAl1gmuM3qFdyJeqqnzmg1vriRztHg==CIcR-----END PGP SIGNATURE-----
C
C
Clément Lassieur wrote on 12 Aug 2018 22:07
(name . Christopher Baines)(address . mail@cbaines.net)(address . 30809@debbugs.gnu.org)
87a7pr73ho.fsf@lassieur.org
Hello Christopher,
I often get:
guix: gitolite: installing /gnu/store/hraw5zr6lp2w4v6czhvf1gp6phzxmzmj-gitolite.rc fatal: Unable to create '/var/lib/git/repositories/gitolite-admin.git/./index.lock': File exists.
While upgrading my gitolite service. Did you encounter it? Do you knowhow to fix it?
Clément
C
C
Christopher Baines wrote on 19 Aug 2018 18:12
(name . Clément Lassieur)(address . clement@lassieur.org)(address . 30809@debbugs.gnu.org)
87h8jql4ic.fsf@cbaines.net
Clément Lassieur <clement@lassieur.org> writes:
Toggle quote (10 lines)> Hello Christopher,>> I often get:>> guix: gitolite: installing /gnu/store/hraw5zr6lp2w4v6czhvf1gp6phzxmzmj-gitolite.rc> fatal: Unable to create '/var/lib/git/repositories/gitolite-admin.git/./index.lock': File exists.>> While upgrading my gitolite service. Did you encounter it? Do you know> how to fix it?
I don't think I've seen this. It could be if something has gone wrongwith git, it's left the lockfile around. Perhaps before you nextreconfigure, check if the lockfile exists, and then assuming git isn'trunning, delete it.
Do say if it keeps happening though.
-----BEGIN PGP SIGNATURE-----
iQKTBAEBCgB9FiEEPonu50WOcg2XVOCyXiijOwuE9XcFAlt5lutfFIAAAAAALgAoaXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldDNFODlFRUU3NDU4RTcyMEQ5NzU0RTBCMjVFMjhBMzNCMEI4NEY1NzcACgkQXiijOwuE9Xc1rg/6A1rAsJ8xG62VNrpwsDYed32RD48mNJaP32GXfRBJCfeXd53pHR0bTko32RFZTCN1fdOPWKNTWWqp6iUeHwYKgmCcdPynMDScJ2Zi6KLXxv/W2q1BayAD3G+1acHof4/LYUuoAtkTw+SAjQsBrJg9yMzlf2vfJnCUEWKXG/wnoQFU8/xapJPSdCKWHBho/tYwKo5a0ql0YQpsgwlWag064J2X2BYOubuftlrv5flXA9ndnrpi/Eibe5uUjZP4xhMHDjCytihKDhIMu31DDEbrGZjy8WbW0EAtV4aBlTyMwR4lR0bYKuHpa3fjEiZHzodK+dGfxd8RQVM634CbZMRmqvZi0GR0KSs/zQwazGXz3P4bYBXx5gSQvJqGIIa0xmEIcf8xkv95raK13kxBC8W97sUYlc4Kv57E7QxxEEoloE4NgCNC/KK/A1o4TI67TAObLlZhOmFGmfqbWkzPhCx1RLLd5ersaLurxy1tPXBaV5cDDDqMQ82eYfL+A0jzXGTwmxbByt43obj5oqDvxFcsbUMoWINqeS2qV6oce+vcsUR+8I4LbwiDvlOiWwhJbnIu370hoaxwmGZ71n4jLUpW/tivL/K05H/BWAUSqeFL3IYFQ8KM70h6HGKSsEeenJGs7csoHu9DMG6LtsYJ+hvJ3E9yBNZW/LT2eupV0+0RHwM==7h1x-----END PGP SIGNATURE-----
C
C
Christopher Baines wrote on 22 Sep 2018 17:14
[PATCH 1/2] gnu: Modify the gitolite package to support the Guix service.
(address . 30809@debbugs.gnu.org)
20180922151437.20154-1-mail@cbaines.net
Previously the gitolite package worked, but there were problems using it forthe service where you might have a minimal PATH. This commit patches thesource and scripts where possible to use store paths, and also wraps thegitolite script to handle the harder dependencies.
* gnu/packages/version-control.scm (gitolite)[arguments]: Add more patching tothe patch-scripts phase, and add two new phases (patch-source andwrap-scripts).[inputs]: Add coreutils, findutils and inetutils.--- gnu/packages/version-control.scm | 53 +++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-)
Toggle diff (81 lines)diff --git a/gnu/packages/version-control.scm b/gnu/packages/version-control.scmindex 58c870df5..c45610f2b 100644--- a/gnu/packages/version-control.scm+++ b/gnu/packages/version-control.scm@@ -1031,12 +1031,48 @@ also walk each side of a merge and test those changes individually.") ((" perl -") (string-append " " perl " -"))) + (substitute* (find-files "src/triggers" ".*")+ ((" sed ")+ (string-append " " (which "sed") " ")))++ (substitute*+ '("src/triggers/post-compile/update-gitweb-access-list"+ "src/triggers/post-compile/ssh-authkeys-split"+ "src/triggers/upstream")+ ((" grep ")+ (string-append " " (which "grep") " ")))+ ;; Avoid references to the store in authorized_keys. ;; This works because gitolite-shell is in the PATH. (substitute* "src/triggers/post-compile/ssh-authkeys" (("\\$glshell \\$user") "gitolite-shell $user")) #t)))+ (add-before 'install 'patch-source+ (lambda* (#:key inputs #:allow-other-keys)+ ;; Gitolite uses cat to test the readability of the+ ;; pubkey+ (substitute* "src/lib/Gitolite/Setup.pm"+ (("\"cat ")+ (string-append "\"" (which "cat") " "))+ (("\"ssh-keygen")+ (string-append "\"" (which "ssh-keygen"))))++ (substitute* '("src/lib/Gitolite/Hooks/PostUpdate.pm"+ "src/lib/Gitolite/Hooks/Update.pm")+ (("/usr/bin/perl")+ (string-append (assoc-ref inputs "perl")+ "/bin/perl")))++ (substitute* "src/lib/Gitolite/Common.pm"+ (("\"ssh-keygen")+ (string-append "\"" (which "ssh-keygen")))+ (("\"logger\"")+ (string-append "\""+ (assoc-ref inputs "inetutils")+ "/bin/logger\"")))++ #t)) (replace 'install (lambda* (#:key outputs #:allow-other-keys) (let* ((output (assoc-ref outputs "out"))@@ -1050,9 +1086,24 @@ also walk each side of a merge and test those changes individually.") (symlink (string-append sharedir "/" script) (string-append bindir "/" script))) '("gitolite" "gitolite-shell"))+ #t)))+ (add-after 'install 'wrap-scripts+ (lambda* (#:key inputs outputs #:allow-other-keys)+ (let ((out (assoc-ref outputs "out"))+ (coreutils (assoc-ref inputs "coreutils"))+ (findutils (assoc-ref inputs "findutils"))+ (git (assoc-ref inputs "git")))+ (wrap-program (string-append out "/bin/gitolite")+ `("PATH" ":" prefix+ ,(map (lambda (dir)+ (string-append dir "/bin"))+ (list out coreutils findutils git)))) #t)))))) (inputs- `(("perl" ,perl)))+ `(("perl" ,perl)+ ("coreutils" ,coreutils)+ ("findutils" ,findutils)+ ("inetutils" ,inetutils))) ;; git and openssh are propagated because trying to patch the source via ;; regexp matching is too brittle and prone to false positives. (propagated-inputs-- 2.18.0
C
C
Christopher Baines wrote on 22 Sep 2018 17:14
[PATCH 2/2] services: Add Gitolite.
(address . 30809@debbugs.gnu.org)
20180922151437.20154-2-mail@cbaines.net
* gnu/services/version-control.scm (<gitolite-configuration>,<gitolite-rc-file>): New record types.(gitolite-accounts, gitolite-activation): New procedures.(gitolite-service-type): New variables.* gnu/tests/version-control.scm (%gitolite-test-admin-keypair, %gitolite-os,%test-gitolite): New variables.(run-gitolite-test): New procedure.* doc/guix.texi (Version Control): Document the gitolite service.--- doc/guix.texi | 94 ++++++++++++++++ gnu/services/version-control.scm | 179 ++++++++++++++++++++++++++++++- gnu/tests/version-control.scm | 114 +++++++++++++++++++- 3 files changed, 385 insertions(+), 2 deletions(-)
Toggle diff (451 lines)diff --git a/doc/guix.texi b/doc/guix.texiindex 76ec718b0..4c0b38a00 100644--- a/doc/guix.texi+++ b/doc/guix.texi@@ -20948,6 +20948,100 @@ could instantiate a cgit service like this: (cgitrc ""))) @end example +@subsubheading Gitolite Service++@cindex Gitolite service+@cindex Git, hosting+@uref{http://gitolite.com/gitolite/, Gitolite} is a tool for hosting Git+repositories on a central server.++Gitolite can handle multiple repositories and users, and supports flexible+configuration of the permissions for the users on the repositories.++The following example will configure Gitolite using the default @code{git}+user, and the provided SSH public key.++@example+(service gitolite-service-type+ (gitolite-configuration+ (admin-pubkey (plain-file+ "yourname.pub"+ "ssh-rsa AAAA... guix@@example.com"))))+@end example++Gitolite is configured through a special admin repository which you can clone,+for example, if you setup Gitolite on @code{example.com}, you would run the+following command to clone the admin repository.++@example+git clone git@@example.com:gitolite-admin+@end example++When the Gitolite service is activated, the provided @code{admin-pubkey} will+be inserted in to the @file{keydir} directory in the gitolite-admin+repository. If this results in a change in the repository, it will be+committed using the message ``gitolite setup by GNU Guix''.++@deftp {Data Type} gitolite-configuration+Data type representing the configuration for @code{gitolite-service-type}.++@table @asis+@item @code{package} (default: @var{gitolite})+Gitolite package to use.++@item @code{user} (default: @var{git})+User to use for Gitolite. This will be user that you use when accessing+Gitolite over SSH.++@item @code{group} (default: @var{git})+Group to use for Gitolite.++@item @code{home-directory} (default: @var{"/var/lib/gitolite"})+Directory in which to store the Gitolite configuration and repositories.++@item @code{rc-file} (default: @var{(gitolite-rc-file)})+A ``file-like'' object (@pxref{G-Expressions, file-like objects}),+representing the configuration for Gitolite.++@item @code{admin-pubkey} (default: @var{#f})+A ``file-like'' object (@pxref{G-Expressions, file-like objects}) used to+setup Gitolite. This will be inserted in to the @file{keydir} directory+within the gitolite-admin repository.++To specify the SSH key as a string, use the @code{plain-file} function.++@example+(plain-file "yourname.pub" "ssh-rsa AAAA... guix@@example.com")+@end example++@end table+@end deftp++@deftp {Data Type} gitolite-rc-file+Data type representing the Gitolite RC file.++@table @asis+@item @code{umask} (default: @code{#o0077})+This controls the permissions Gitolite sets on the repositories and their+contents.++A value like @code{#o0027} will give read access to the group used by Gitolite+(by default: @code{git}). This is necessary when using Gitolite with software+like cgit or gitweb.++@item @code{git-config-keys} (default: @code{""})+Gitolite allows you to set git config values using the "config" keyword. This+setting allows control over the config keys to accept.++@item @code{roles} (default: @code{'(("READERS" . 1) ("WRITERS" . ))})+Set the role names allowed to be used by users running the perms command.++@item @code{enable} (default: @code{'("help" "desc" "info" "perms" "writable" "ssh-authkeys" "git-config" "daemon" "gitweb")})+This setting controls the commands and features to enable within Gitolite.++@end table+@end deftp+ @node Game Services @subsubsection Game Servicesdiff --git a/gnu/services/version-control.scm b/gnu/services/version-control.scmindex 58274c8be..cc8cd2202 100644--- a/gnu/services/version-control.scm+++ b/gnu/services/version-control.scm@@ -3,6 +3,7 @@ ;;; Copyright © 2016 Sou Bunnbu <iyzsong@member.fsf.org> ;;; Copyright © 2017 Oleg Pykhalov <go.wigust@gmail.com> ;;; Copyright © 2017 Clément Lassieur <clement@lassieur.org>+;;; Copyright © 2018 Christopher Baines <mail@cbaines.net> ;;; ;;; This file is part of GNU Guix. ;;;@@ -40,7 +41,23 @@ git-http-configuration git-http-configuration?- git-http-nginx-location-configuration))+ git-http-nginx-location-configuration++ <gitolite-configuration>+ gitolite-configuration+ gitolite-configuration-package+ gitolite-configuration-user+ gitolite-configuration-rc-file+ gitolite-configuration-admin-pubkey++ <gitolite-rc-file>+ gitolite-rc-file+ gitolite-rc-file-umask+ gitolite-rc-file-git-config-keys+ gitolite-rc-file-roles+ gitolite-rc-file-enable++ gitolite-service-type)) ;;; Commentary: ;;;@@ -197,3 +214,163 @@ access to exported repositories under @file{/srv/git}." "") (list "fastcgi_param GIT_PROJECT_ROOT " git-root ";") "fastcgi_param PATH_INFO $1;"))))))++ +;;;+;;; Gitolite+;;;++(define-record-type* <gitolite-rc-file>+ gitolite-rc-file make-gitolite-rc-file+ gitolite-rc-file?+ (umask gitolite-rc-file-umask+ (default #o0077))+ (git-config-keys gitolite-rc-file-git-config-keys+ (default ""))+ (roles gitolite-rc-file-roles+ (default '(("READERS" . 1)+ ("WRITERS" . 1))))+ (enable gitolite-rc-file-enable+ (default '("help"+ "desc"+ "info"+ "perms"+ "writable"+ "ssh-authkeys"+ "git-config"+ "daemon"+ "gitweb"))))++(define-gexp-compiler (gitolite-rc-file-compiler+ (file <gitolite-rc-file>) system target)+ (match file+ (($ <gitolite-rc-file> umask git-config-keys roles enable)+ (apply text-file* "gitolite.rc"+ `("%RC = (\n"+ " UMASK => " ,(format #f "~4,'0o" umask) ",\n"+ " GIT_CONFIG_KEYS => '" ,git-config-keys "',\n"+ " ROLES => {\n"+ ,@(map (match-lambda+ ((role . value)+ (simple-format #f " ~A => ~A,\n" role value)))+ roles)+ " },\n"+ "\n"+ " ENABLE => [\n"+ ,@(map (lambda (value)+ (simple-format #f " '~A',\n" value))+ enable)+ " ],\n"+ ");\n"+ "\n"+ "1;\n")))))++(define-record-type* <gitolite-configuration>+ gitolite-configuration make-gitolite-configuration+ gitolite-configuration?+ (package gitolite-configuration-package+ (default gitolite))+ (user gitolite-configuration-user+ (default "git"))+ (group gitolite-configuration-group+ (default "git"))+ (home-directory gitolite-configuration-home-directory+ (default "/var/lib/gitolite"))+ (rc-file gitolite-configuration-rc-file+ (default (gitolite-rc-file)))+ (admin-pubkey gitolite-configuration-admin-pubkey))++(define gitolite-accounts+ (match-lambda+ (($ <gitolite-configuration> package user group home-directory+ rc-file admin-pubkey)+ ;; User group and account to run Gitolite.+ (list (user-group (name user) (system? #t))+ (user-account+ (name user)+ (group group)+ (system? #t)+ (comment "Gitolite user")+ (home-directory home-directory))))))++(define gitolite-activation+ (match-lambda+ (($ <gitolite-configuration> package user group home+ rc-file admin-pubkey)+ #~(begin+ (use-modules (ice-9 match)+ (guix build utils))++ (let* ((user-info (getpwnam #$user))+ (admin-pubkey #$admin-pubkey)+ (pubkey-file (string-append+ #$home "/"+ (basename+ (strip-store-file-name admin-pubkey)))))++ (simple-format #t "guix: gitolite: installing ~A\n" #$rc-file)+ (copy-file #$rc-file #$(string-append home "/.gitolite.rc"))++ ;; The key must be writable, so copy it from the store+ (copy-file admin-pubkey pubkey-file)++ (chmod pubkey-file #o500)+ (chown pubkey-file+ (passwd:uid user-info)+ (passwd:gid user-info))++ ;; Set the git configuration, to avoid gitolite trying to use+ ;; the hostname command, as the network might not be up yet+ (with-output-to-file #$(string-append home "/.gitconfig")+ (lambda ()+ (display "[user]+ name = GNU Guix+ email = guix@localhost+")))+ ;; Run Gitolite setup, as this updates the hooks and include the+ ;; admin pubkey if specified. The admin pubkey is required for+ ;; initial setup, and will replace the previous key if run after+ ;; initial setup+ (match (primitive-fork)+ (0+ ;; Exit with a non-zero status code if an exception is thrown.+ (dynamic-wind+ (const #t)+ (lambda ()+ (setenv "HOME" (passwd:dir user-info))+ (setenv "USER" #$user)+ (setgid (passwd:gid user-info))+ (setuid (passwd:uid user-info))+ (primitive-exit+ (system* #$(file-append package "/bin/gitolite")+ "setup"+ "-m" "gitolite setup by GNU Guix"+ "-pk" pubkey-file)))+ (lambda ()+ (primitive-exit 1))))+ (pid (waitpid pid)))++ (when (file-exists? pubkey-file)+ (delete-file pubkey-file)))))))++(define gitolite-service-type+ (service-type+ (name 'gitolite)+ (extensions+ (list (service-extension activation-service-type+ gitolite-activation)+ (service-extension account-service-type+ gitolite-accounts)+ (service-extension profile-service-type+ ;; The Gitolite package in Guix uses+ ;; gitolite-shell in the authorized_keys file, so+ ;; gitolite-shell needs to be on the PATH for+ ;; gitolite to work.+ (lambda (config)+ (list+ (gitolite-configuration-package config))))))+ (description+ "Setup @command{gitolite}, a Git hosting tool providing access over SSH..+By default, the @code{git} user is used, but this is configurable.+Additionally, Gitolite can integrate with with tools like gitweb or cgit to+provide a web interface to view selected repositories.")))diff --git a/gnu/tests/version-control.scm b/gnu/tests/version-control.scmindex 3b935a1b4..4409b8a12 100644--- a/gnu/tests/version-control.scm+++ b/gnu/tests/version-control.scm@@ -2,6 +2,7 @@ ;;; Copyright © 2017, 2018 Oleg Pykhalov <go.wigust@gmail.com> ;;; Copyright © 2017, 2018 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2017, 2018 Clément Lassieur <clement@lassieur.org>+;;; Copyright © 2018 Christopher Baines <mail@cbaines.net> ;;; ;;; This file is part of GNU Guix. ;;;@@ -27,14 +28,17 @@ #:use-module (gnu services) #:use-module (gnu services version-control) #:use-module (gnu services cgit)+ #:use-module (gnu services ssh) #:use-module (gnu services web) #:use-module (gnu services networking) #:use-module (gnu packages version-control)+ #:use-module (gnu packages ssh) #:use-module (guix gexp) #:use-module (guix store) #:use-module (guix modules) #:export (%test-cgit- %test-git-http))+ %test-git-http+ %test-gitolite)) (define README-contents "Hello! This is what goes inside the 'README' file.")@@ -300,3 +304,111 @@ HTTP-PORT." (name "git-http") (description "Connect to a running Git HTTP server.") (value (run-git-http-test))))++ +;;;+;;; Gitolite.+;;;++(define %gitolite-test-admin-keypair+ (computed-file+ "gitolite-test-admin-keypair"+ (with-imported-modules (source-module-closure+ '((guix build utils)))+ #~(begin+ (use-modules (ice-9 match) (srfi srfi-26)+ (guix build utils))++ (mkdir #$output)+ (invoke #$(file-append openssh "/bin/ssh-keygen")+ "-f" (string-append #$output "/test-admin")+ "-t" "rsa"+ "-q"+ "-N" "")))))++(define %gitolite-os+ (simple-operating-system+ (dhcp-client-service)+ (service openssh-service-type)+ (service gitolite-service-type+ (gitolite-configuration+ (admin-pubkey+ (file-append %gitolite-test-admin-keypair "/test-admin.pub"))))))++(define (run-gitolite-test)+ (define os+ (marionette-operating-system+ %gitolite-os+ #:imported-modules '((gnu services herd)+ (guix combinators))))++ (define vm+ (virtual-machine+ (operating-system os)+ (port-forwardings `((2222 . 22)))))++ (define test+ (with-imported-modules '((gnu build marionette)+ (guix build utils))+ #~(begin+ (use-modules (srfi srfi-64)+ (rnrs io ports)+ (gnu build marionette)+ (guix build utils))++ (define marionette+ (make-marionette (list #$vm)))++ (mkdir #$output)+ (chdir #$output)++ (test-begin "gitolite")++ ;; Wait for sshd to be up and running.+ (test-assert "service running"+ (marionette-eval+ '(begin+ (use-modules (gnu services herd))+ (start-service 'ssh-daemon))+ marionette))++ (display #$%gitolite-test-admin-keypair)++ (setenv "GIT_SSH_VARIANT" "ssh")+ (setenv "GIT_SSH_COMMAND"+ (string-join+ '(#$(file-append openssh "/bin/ssh")+ "-i" #$(file-append %gitolite-test-admin-keypair+ "/test-admin")+ "-o" "UserKnownHostsFile=/dev/null"+ "-o" "StrictHostKeyChecking=no")))++ (test-assert "cloning the admin repository"+ (invoke #$(file-append git "/bin/git")+ "clone" "-v"+ "ssh://git@localhost:2222/gitolite-admin"+ "/tmp/clone"))++ (test-assert "admin key exists"+ (file-exists? "/tmp/clone/keydir/test-admin.pub"))++ (with-directory-excursion "/tmp/clone"+ (invoke #$(file-append git "/bin/git")+ "-c" "user.name=Guix" "-c" "user.email=guix"+ "commit"+ "-m" "Test commit"+ "--allow-empty")++ (test-assert "pushing, and the associated hooks"+ (invoke #$(file-append git "/bin/git") "push")))++ (test-end)+ (exit (= (test-runner-fail-count (test-runner-current)) 0)))))++ (gexp->derivation "gitolite" test))++(define %test-gitolite+ (system-test+ (name "gitolite")+ (description "Clone the Gitolite admin repository.")+ (value (run-gitolite-test))))-- 2.18.0
C
C
Christopher Baines wrote on 22 Sep 2018 18:03
(address . 30809@debbugs.gnu.org)(name . Clément Lassieur)(address . clement@lassieur.org)
87y3btwmcc.fsf@cbaines.net
Christopher Baines <mail@cbaines.net> writes:
Toggle quote (4 lines)> I'm at a loss regarding what is going on here. I've tried testing on top> of 8b8978ade and a previous commit, I've also reproduced this on two> different computers.
Right, I think I've found a work around this problem!
Previously the activation gexp was like:
#~(let* ... (use-modules (ice-9 match) (guix build utils))

...
(match ... ))
This seems to break, no idea why, but I think it's something to do withthe mystery of macros in Scheme/Guile.
I had a look at how other services were using primitive-fork, and thePostgreSQL service does. However, it's activation gexp looks more like:
#~(begin (use-modules (ice-9 match) (guix build utils))
(let ... ...
(match ... )))
So, I switched the gitolite activation phase around to use a begin asthe outer expression (rather than the let*), and it seems to work!
I've sent the patches again.
Chris
-----BEGIN PGP SIGNATURE-----
iQKTBAEBCgB9FiEEPonu50WOcg2XVOCyXiijOwuE9XcFAlumZ+NfFIAAAAAALgAoaXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldDNFODlFRUU3NDU4RTcyMEQ5NzU0RTBCMjVFMjhBMzNCMEI4NEY1NzcACgkQXiijOwuE9XdF/BAAtQnwOWNNLUrZXsA47gw7vCiViqZznuGLzgZs8o2bZS4P2ZNwHk0ALJhOZ8MRKsVLvMF1SbTyz2bluG0EGgROcJYiYUSrOCZOHFk0npcmZJgSWjHVzFqGaa2h658iielmK4U6ekHQ/4PelXs8YAwxAl+rNT4Qp7+AiJOLmKj0s1LWwweis88lo0woHZaQsKk4Wh8NhF6o13dqErGvXhmhzW4J7/5VMpFpTjYrKwLprJEehLz9e5QvTLrKlfReJsqwJkIBPY1HmoLZnFFxvOS3qV5FEiSLGVEdj+icseJaopOPz/DZnQE/oNkMp71VTsEODFOZ6LRvZYZEIP+zvqS74m1L1xUtA0BCXWiq36Ooc79QxeWTCBJ91rRL9afySPmF0qRIkzvz/sTeuXfmRIfRlfMFtTaF79iTpo9LgQJZdEbBLZxxY3iYCPQzapKLPuB91vE5ZyXSf8m7bfe/b/ZNIc5uyaMsVo/vjPBNtYtR4RpUSPl8ijF8aZqSg+9+8J8cZKro+sqE/sR7XCjMZO4r1i9jXNKlbZQNR4NlNyAiSt9a9Xm4TJuIHiqckaFvjk9WSdIkapTWyl6o5XQn19O8SR/7kQ7VLaaWQHSU+TGkWekcf7H3JxwN9D7EP6TkzY36PrX6lmVH5HZVb+sItCcocIoWrill9tj3oTkUDf+rY6Y==KNwj-----END PGP SIGNATURE-----
N
N
Nils Gillmann wrote on 25 Sep 2018 20:01
(name . Christopher Baines)(address . mail@cbaines.net)
20180925180146.cwchfgbre5xfnxj7@abyayala
Christopher Baines transcribed 1.8K bytes:
Toggle quote (21 lines)> > Clément Lassieur <clement@lassieur.org> writes:> > > Hello Christopher,> >> > I often get:> >> > guix: gitolite: installing /gnu/store/hraw5zr6lp2w4v6czhvf1gp6phzxmzmj-gitolite.rc> > fatal: Unable to create '/var/lib/git/repositories/gitolite-admin.git/./index.lock': File exists.> >> > While upgrading my gitolite service. Did you encounter it? Do you know> > how to fix it?> > I don't think I've seen this. It could be if something has gone wrong> with git, it's left the lockfile around. Perhaps before you next> reconfigure, check if the lockfile exists, and then assuming git isn't> running, delete it.> > Do say if it keeps happening though.

Hi Christopher,
until end of october Taler needs to migrate servers, and I amresponsible to move it to GuixSD. Gitolite is a critical andessential part of the infrastructure.
Do you think the gitolite service is (mostly) ready to be deployed orhave you encountered any bugs with it?

Thanks for your work on it!
C
C
Christopher Baines wrote on 28 Sep 2018 22:28
(name . Nils Gillmann)(address . ng0@n0.is)(address . 30809-done@debbugs.gnu.org)
87h8i9jric.fsf@cbaines.net
Nils Gillmann <ng0@n0.is> writes:
Toggle quote (31 lines)> Christopher Baines transcribed 1.8K bytes:>>>> Clément Lassieur <clement@lassieur.org> writes:>>>> > Hello Christopher,>> >>> > I often get:>> >>> > guix: gitolite: installing /gnu/store/hraw5zr6lp2w4v6czhvf1gp6phzxmzmj-gitolite.rc>> > fatal: Unable to create '/var/lib/git/repositories/gitolite-admin.git/./index.lock': File exists.>> >>> > While upgrading my gitolite service. Did you encounter it? Do you know>> > how to fix it?>>>> I don't think I've seen this. It could be if something has gone wrong>> with git, it's left the lockfile around. Perhaps before you next>> reconfigure, check if the lockfile exists, and then assuming git isn't>> running, delete it.>>>> Do say if it keeps happening though.>>> Hi Christopher,>> until end of october Taler needs to migrate servers, and I am> responsible to move it to GuixSD. Gitolite is a critical and> essential part of the infrastructure.>> Do you think the gitolite service is (mostly) ready to be deployed or> have you encountered any bugs with it?
Well, it's in master now (as of a few minutes ago), so I'd suggestgiving it a go.
The Guix service is just a thin wrapper around Gitolite to get it going,so hopefully not much can go wrong. I'm not sure if necessarily all thefeatures of Gitolite work in the package (as the service runs in a moreminimal environment that a normal user may have). But, hopefully it willjust work fine :)
1: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=30809#80
-----BEGIN PGP SIGNATURE-----
iQKTBAEBCgB9FiEEPonu50WOcg2XVOCyXiijOwuE9XcFAluujvtfFIAAAAAALgAoaXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldDNFODlFRUU3NDU4RTcyMEQ5NzU0RTBCMjVFMjhBMzNCMEI4NEY1NzcACgkQXiijOwuE9Xdr5A//Q5YtUagA9WNh5ZeB2lIfaTWQnKF1Czvc+1FofM5XU2PZnUJf+I+UHUSRUClaBhCrBoFOQ1Y4O3z5tkNqCmnxIUb+vgGnz9qCtCt2aNiMh1mHKI3iLUaZx8L02s3c9S+2M4CDUMQvFsrEhhTwu+yZlqe+gJMRDGFv2Z+etIqJNFXKuQhBeBFN53DhPUS2YOJxzeH5BocWNCMf1KOBX5MWE/iSqodY78N/OAJjRMlHIXT+sZyF/qPoQxuyQcbhy7cWYZo4dQK8fa6+z5o2/JkYJ214c+0wsOSTI7f5d6c0+ub0YUDwNIkAvIJb3/c7v0q0o1q25kILr/wvdzjVQMC3eYbo2sPETWKieTOez9XFZYN1OKz+BTo9ljHKm/OGmtdlrpKhMs2lIuYTtbEYnyIw/BdTFcTo+HWitaDyZ9y6KPuhJNjioDq5+JxC6j9qkzG8wSJQ/tY7GI0So8IVCVZe/vFPDBfk6ASFx0SEOpkY4aJQZ+BhChi7nPc9PlrP1FQbPqsvfuUy40xTpfxX9xwex0gb+eBLOXf4Dhud8fEfnNFNNsZLzsmRkIvNT/Jeor5yBOVxdLX73KcOS3HVoj4Zye69NOaXCmusN+4e10aIvXr+p+Zp3nxUWGUXwAc/YI9SefgzSDYEwz4xWdyFDIZYOfPr5pywMFwHWT2nR5D6jjM==+3Wm-----END PGP SIGNATURE-----
Closed
?
Your comment

This issue is archived.

To comment on this conversation send email to 30809@debbugs.gnu.org