aboutsummaryrefslogtreecommitdiff
path: root/etc/git/pre-push
blob: 325b23854bb92a4f93fb900e36c0bb61e5005654 (about) (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#!/bin/sh

# This hook script prevents the user from pushing to Savannah if any of the new
# commits' OpenPGP signatures cannot be verified, or if a commit is signed
# with an unauthorized key.

# Called by "git push" after it has checked the remote status, but before
# anything has been pushed.  If this script exits with a non-zero status nothing
# will be pushed.
#
# This hook is called with the following parameters:
#
# $1 -- Name of the remote to which the push is being done
# $2 -- URL to which the push is being done
#
# If pushing without using a named remote those arguments will be equal.
#
# Information about the commits which are being pushed is supplied as lines to
# the standard input in the form:
#
#   <local ref> <local sha1> <remote ref> <remote sha1>

# This is the "empty hash" used by Git when pushing a branch deletion.
z40=0000000000000000000000000000000000000000

while read local_ref local_hash remote_ref remote_hash
do
	# When deleting a remote branch, no commits are pushed to the remote, and
	# thus there are no signatures to be verified.
	if [ "$local_hash" != $z40 ]
	then
		# Only use the hook when pushing to Savannah.
		case "$2" in
		    *.gnu.org*)
			set -e
			make check-channel-news
			exec guix git authenticate
			exit 127
			;;
		    *)
			exit 0
			;;
		esac
	fi
done

exit 0
(define %cgit-os ;; Operating system under test. (let ((base-os (simple-operating-system (service dhcp-client-service-type) (service cgit-service-type (cgit-configuration (nginx %cgit-configuration-nginx))) %test-repository-service))) (operating-system (inherit base-os) (packages (cons* git (operating-system-packages base-os)))))) (define* (run-cgit-test #:optional (http-port 19418)) "Run tests in %CGIT-OS, which has nginx running and listening on HTTP-PORT." (define os (marionette-operating-system %cgit-os #:imported-modules '((gnu services herd) (guix combinators)))) (define vm (virtual-machine (operating-system os) (port-forwardings `((8080 . ,http-port))))) (define test (with-imported-modules '((gnu build marionette)) #~(begin (use-modules (srfi srfi-11) (srfi srfi-64) (gnu build marionette) (web uri) (web client) (web response)) (define marionette (make-marionette (list #$vm))) (test-runner-current (system-test-runner #$output)) (test-begin "cgit") ;; XXX: Shepherd reads the config file *before* binding its control ;; socket, so /var/run/shepherd/socket might not exist yet when the ;; 'marionette' service is started. (test-assert "shepherd socket ready" (marionette-eval `(begin (use-modules (gnu services herd)) (let loop ((i 10)) (cond ((file-exists? (%shepherd-socket-file)) #t) ((> i 0) (sleep 1) (loop (- i 1))) (else 'failure)))) marionette)) ;; Wait for nginx to be up and running. (test-assert "nginx running" (wait-for-file "/var/run/nginx/pid" marionette)) ;; Wait for fcgiwrap to be up and running. (test-assert "fcgiwrap running" (wait-for-tcp-port 9000 marionette)) ;; Make sure the PID file is created. (test-assert "PID file" (marionette-eval '(file-exists? "/var/run/nginx/pid") marionette)) ;; Make sure the configuration file is created. (test-assert "configuration file" (marionette-eval '(file-exists? "/etc/cgitrc") marionette)) ;; Make sure Git test repository is created. (test-assert "Git test repository" (marionette-eval '(file-exists? "/srv/git/test") marionette)) ;; Make sure we can access pages that correspond to our repository. (letrec-syntax ((test-url (syntax-rules () ((_ path code) (test-equal (string-append "GET " path) code (let-values (((response body) (http-get (string-append "http://localhost:8080" path)))) (response-code response)))) ((_ path) (test-url path 200))))) (test-url "/") (test-url "/test") (test-url "/test/log") (test-url "/test/tree") (test-url "/test/tree/README") (test-url "/test/does-not-exist" 404) (test-url "/test/tree/does-not-exist" 404) (test-url "/does-not-exist" 404)) (test-end)))) (gexp->derivation "cgit-test" test)) (define %test-cgit (system-test (name "cgit") (description "Connect to a running Cgit server.") (value (run-cgit-test)))) ;;; ;;; Git server. ;;; (define %git-nginx-configuration (nginx-configuration (server-blocks (list (nginx-server-configuration (listen '("19418")) (ssl-certificate #f) (ssl-certificate-key #f) (locations (list (git-http-nginx-location-configuration (git-http-configuration (export-all? #t) (uri-path "/git")))))))))) (define %git-http-os (simple-operating-system (service dhcp-client-service-type) (service fcgiwrap-service-type) (service nginx-service-type %git-nginx-configuration) %test-repository-service)) (define* (run-git-http-test #:optional (http-port 19418)) (define os (marionette-operating-system %git-http-os #:imported-modules '((gnu services herd) (guix combinators)))) (define vm (virtual-machine (operating-system os) (port-forwardings `((8080 . ,http-port))))) (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))) (test-runner-current (system-test-runner #$output)) (test-begin "git-http") ;; Wait for nginx to be up and running. (test-assert "nginx running" (wait-for-file "/var/run/nginx/pid" marionette)) ;; Make sure Git test repository is created. (test-assert "Git test repository" (marionette-eval '(file-exists? "/srv/git/test") marionette)) (test-assert "fcgiwrap listens" ;; Wait for fcgiwrap to be ready before cloning. (wait-for-tcp-port 9000 marionette)) ;; Make sure we can clone the repo from the host. (test-equal "clone" '#$README-contents (begin (invoke #$(file-append git "/bin/git") "clone" "-v" "http://localhost:8080/git/test" "/tmp/clone") (call-with-input-file "/tmp/clone/README" get-string-all))) (test-end)))) (gexp->derivation "git-http" test)) (define %test-git-http (system-test (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 (service dhcp-client-service-type) (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))) (test-runner-current (system-test-runner #$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)))) (gexp->derivation "gitolite" test)) (define %test-gitolite (system-test (name "gitolite") (description "Clone the Gitolite admin repository.") (value (run-gitolite-test)))) ;;; ;;; Gitile. ;;; (define %gitile-configuration-nginx (nginx-server-configuration (root "/does/not/exists") (try-files (list "$uri" "=404")) (listen '("19418")) (ssl-certificate #f) (ssl-certificate-key #f))) (define %gitile-os ;; Operating system under test. (simple-operating-system (service dhcp-client-service-type) (simple-service 'srv-git activation-service-type #~(mkdir-p "/srv/git")) (service gitile-service-type (gitile-configuration (base-git-url "http://localhost") (repositories "/srv/git") (nginx %gitile-configuration-nginx))) %test-repository-service)) (define* (run-gitile-test #:optional (http-port 19418)) "Run tests in %GITOLITE-OS, which has nginx running and listening on HTTP-PORT." (define os (marionette-operating-system %gitile-os #:imported-modules '((gnu services herd) (guix combinators)))) (define vm (virtual-machine (operating-system os) (port-forwardings `((8081 . ,http-port))) (memory-size 1024))) (define test (with-imported-modules '((gnu build marionette)) #~(begin (use-modules (srfi srfi-11) (srfi srfi-64) (gnu build marionette) (web uri) (web client) (web response)) (define marionette (make-marionette (list #$vm))) (test-runner-current (system-test-runner #$output)) (test-begin "gitile") ;; XXX: Shepherd reads the config file *before* binding its control ;; socket, so /var/run/shepherd/socket might not exist yet when the ;; 'marionette' service is started. (test-assert "shepherd socket ready" (marionette-eval `(begin (use-modules (gnu services herd)) (let loop ((i 10)) (cond ((file-exists? (%shepherd-socket-file)) #t) ((> i 0) (sleep 1) (loop (- i 1))) (else 'failure)))) marionette)) ;; Wait for nginx to be up and running. (test-assert "nginx running" (wait-for-file "/var/run/nginx/pid" marionette)) ;; Make sure Git test repository is created. (test-assert "Git test repository" (marionette-eval '(file-exists? "/srv/git/test") marionette)) (sleep 2) ;; Make sure we can access pages that correspond to our repository. (letrec-syntax ((test-url (syntax-rules () ((_ path code) (test-equal (string-append "GET " path) code (let-values (((response body) (http-get (string-append "http://localhost:8081" path)))) (response-code response)))) ((_ path) (test-url path 200))))) (test-url "/") (test-url "/css/gitile.css") (test-url "/test") (test-url "/test/commits") (test-url "/test/tree" 404) (test-url "/test/tree/-") (test-url "/test/tree/-/README") (test-url "/test/does-not-exist" 404) (test-url "/test/tree/-/does-not-exist" 404) (test-url "/does-not-exist" 404)) (test-end)))) (gexp->derivation "gitile-test" test)) (define %test-gitile (system-test (name "gitile") (description "Connect to a running Gitile server.") (value (run-gitile-test))))