From 4353981eb095459c47a9e12950745ac0304162ae Mon Sep 17 00:00:00 2001 From: Marius Bakke Date: Wed, 26 Sep 2018 01:45:05 +0200 Subject: tests: Add missing copyright statement. This is a follow-up to commit 3b97a1779f3b65d582b8edc8c154b6414314b946. * gnu/tests/web.scm: Update copyright header. --- gnu/tests/web.scm | 1 + 1 file changed, 1 insertion(+) (limited to 'gnu/tests') diff --git a/gnu/tests/web.scm b/gnu/tests/web.scm index bcc919137b..2e209fee97 100644 --- a/gnu/tests/web.scm +++ b/gnu/tests/web.scm @@ -3,6 +3,7 @@ ;;; Copyright © 2017 Christopher Baines ;;; Copyright © 2017, 2018 Clément Lassieur ;;; Copyright © 2018 Pierre-Antoine Rouby +;;; Copyright © 2018 Marius Bakke ;;; ;;; This file is part of GNU Guix. ;;; -- cgit v1.2.3 From 258a6d944ed891fa92fa87a16731e5dfe0bac477 Mon Sep 17 00:00:00 2001 From: Christopher Baines Date: Fri, 13 Jul 2018 20:39:46 +0100 Subject: services: Add Gitolite. * gnu/services/version-control.scm (, ): 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(-) (limited to 'gnu/tests') diff --git a/doc/guix.texi b/doc/guix.texi index e1046eb512..94bb0ec4e1 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -21028,6 +21028,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 Services diff --git a/gnu/services/version-control.scm b/gnu/services/version-control.scm index 58274c8bee..cc8cd22021 100644 --- a/gnu/services/version-control.scm +++ b/gnu/services/version-control.scm @@ -3,6 +3,7 @@ ;;; Copyright © 2016 Sou Bunnbu ;;; Copyright © 2017 Oleg Pykhalov ;;; Copyright © 2017 Clément Lassieur +;;; Copyright © 2018 Christopher Baines ;;; ;;; 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-package + gitolite-configuration-user + gitolite-configuration-rc-file + gitolite-configuration-admin-pubkey + + + 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 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 ) system target) + (match 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 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 + (($ 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 + (($ 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.scm index 3b935a1b48..4409b8a12b 100644 --- a/gnu/tests/version-control.scm +++ b/gnu/tests/version-control.scm @@ -2,6 +2,7 @@ ;;; Copyright © 2017, 2018 Oleg Pykhalov ;;; Copyright © 2017, 2018 Ludovic Courtès ;;; Copyright © 2017, 2018 Clément Lassieur +;;; Copyright © 2018 Christopher Baines ;;; ;;; 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)))) -- cgit v1.2.3 From 17bea1803cf706d8db053d8d73302a4455684d29 Mon Sep 17 00:00:00 2001 From: Mark H Weaver Date: Sat, 29 Sep 2018 21:18:45 -0400 Subject: Revert "services: Add Gitolite." This reverts commit 258a6d944ed891fa92fa87a16731e5dfe0bac477. --- doc/guix.texi | 94 -------------------- gnu/services/version-control.scm | 179 +-------------------------------------- gnu/tests/version-control.scm | 114 +------------------------ 3 files changed, 2 insertions(+), 385 deletions(-) (limited to 'gnu/tests') diff --git a/doc/guix.texi b/doc/guix.texi index 94bb0ec4e1..e1046eb512 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -21028,100 +21028,6 @@ 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 Services diff --git a/gnu/services/version-control.scm b/gnu/services/version-control.scm index cc8cd22021..58274c8bee 100644 --- a/gnu/services/version-control.scm +++ b/gnu/services/version-control.scm @@ -3,7 +3,6 @@ ;;; Copyright © 2016 Sou Bunnbu ;;; Copyright © 2017 Oleg Pykhalov ;;; Copyright © 2017 Clément Lassieur -;;; Copyright © 2018 Christopher Baines ;;; ;;; This file is part of GNU Guix. ;;; @@ -41,23 +40,7 @@ git-http-configuration git-http-configuration? - git-http-nginx-location-configuration - - - gitolite-configuration - gitolite-configuration-package - gitolite-configuration-user - gitolite-configuration-rc-file - gitolite-configuration-admin-pubkey - - - gitolite-rc-file - gitolite-rc-file-umask - gitolite-rc-file-git-config-keys - gitolite-rc-file-roles - gitolite-rc-file-enable - - gitolite-service-type)) + git-http-nginx-location-configuration)) ;;; Commentary: ;;; @@ -214,163 +197,3 @@ 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 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 ) system target) - (match 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 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 - (($ 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 - (($ 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.scm index 4409b8a12b..3b935a1b48 100644 --- a/gnu/tests/version-control.scm +++ b/gnu/tests/version-control.scm @@ -2,7 +2,6 @@ ;;; Copyright © 2017, 2018 Oleg Pykhalov ;;; Copyright © 2017, 2018 Ludovic Courtès ;;; Copyright © 2017, 2018 Clément Lassieur -;;; Copyright © 2018 Christopher Baines ;;; ;;; This file is part of GNU Guix. ;;; @@ -28,17 +27,14 @@ #: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-gitolite)) + %test-git-http)) (define README-contents "Hello! This is what goes inside the 'README' file.") @@ -304,111 +300,3 @@ 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)))) -- cgit v1.2.3 From f8e710684e5c3f866413dff825ba17bdffceac5d Mon Sep 17 00:00:00 2001 From: Christopher Baines Date: Fri, 13 Jul 2018 20:39:46 +0100 Subject: services: Add Gitolite. * gnu/services/version-control.scm (, ): 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 | 180 ++++++++++++++++++++++++++++++++++++++- gnu/tests/version-control.scm | 114 ++++++++++++++++++++++++- 3 files changed, 386 insertions(+), 2 deletions(-) (limited to 'gnu/tests') diff --git a/doc/guix.texi b/doc/guix.texi index e1046eb512..94bb0ec4e1 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -21028,6 +21028,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 Services diff --git a/gnu/services/version-control.scm b/gnu/services/version-control.scm index 58274c8bee..13669925ab 100644 --- a/gnu/services/version-control.scm +++ b/gnu/services/version-control.scm @@ -3,6 +3,7 @@ ;;; Copyright © 2016 Sou Bunnbu ;;; Copyright © 2017 Oleg Pykhalov ;;; Copyright © 2017 Clément Lassieur +;;; Copyright © 2018 Christopher Baines ;;; ;;; This file is part of GNU Guix. ;;; @@ -32,6 +33,7 @@ #:use-module (guix store) #:use-module (srfi srfi-1) #:use-module (srfi srfi-26) + #:use-module (ice-9 format) #:use-module (ice-9 match) #:export (git-daemon-service git-daemon-service-type @@ -40,7 +42,23 @@ git-http-configuration git-http-configuration? - git-http-nginx-location-configuration)) + git-http-nginx-location-configuration + + + gitolite-configuration + gitolite-configuration-package + gitolite-configuration-user + gitolite-configuration-rc-file + gitolite-configuration-admin-pubkey + + + 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 +215,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 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 ) system target) + (match 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 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 + (($ 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 + (($ 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.scm index 3b935a1b48..4409b8a12b 100644 --- a/gnu/tests/version-control.scm +++ b/gnu/tests/version-control.scm @@ -2,6 +2,7 @@ ;;; Copyright © 2017, 2018 Oleg Pykhalov ;;; Copyright © 2017, 2018 Ludovic Courtès ;;; Copyright © 2017, 2018 Clément Lassieur +;;; Copyright © 2018 Christopher Baines ;;; ;;; 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)))) -- cgit v1.2.3