summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulien Lepiller <julien@lepiller.eu>2021-08-05 03:46:40 +0200
committerJulien Lepiller <julien@lepiller.eu>2021-09-02 22:56:55 +0200
commitc60daa8e9dfa5f641ecb5f4f3a9135e27b58d2d7 (patch)
tree70f8f431c5ccd7a04f43255b2b7ab079f661bd45
parentcc16103861b26836908a7d16e0751739a0e20da2 (diff)
gnu: version-control: Add gitile service.
* gnu/services/version-control.scm (gitile-service-type): New variable. * doc/guix.texi (Version Control Services): Document it. * gnu/tests/version-control.scm (%test-gitile): New variable.
-rw-r--r--doc/guix.texi132
-rw-r--r--gnu/services/version-control.scm128
-rw-r--r--gnu/tests/version-control.scm138
3 files changed, 395 insertions, 3 deletions
diff --git a/doc/guix.texi b/doc/guix.texi
index ab178a6b068..36a0c7f5ec7 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -25144,6 +25144,7 @@ of strings and G-expressions.
25144@end table 25144@end table
25145@end deffn 25145@end deffn
25146 25146
25147@anchor{NGINX}
25147@subsubheading NGINX 25148@subsubheading NGINX
25148 25149
25149@deffn {Scheme Variable} nginx-service-type 25150@deffn {Scheme Variable} nginx-service-type
@@ -31544,6 +31545,137 @@ This setting controls the commands and features to enable within Gitolite.
31544@end deftp 31545@end deftp
31545 31546
31546 31547
31548@subsubheading Gitile Service
31549
31550@cindex Gitile service
31551@cindex Git, forge
31552@uref{https://git.lepiller.eu/gitile, Gitile} is a Git forge for viewing
31553public git repository contents from a web browser.
31554
31555Gitile works best in collaboration with Gitolite, and will serve the public
31556repositories from Gitolite by default. The service should listen only on
31557a local port, and a webserver should be configured to serve static resources.
31558The gitile service provides an easy way to extend the Nginx service for
31559that purpose (@pxref{NGINX}).
31560
31561The following example will configure Gitile to serve repositories from a
31562custom location, with some default messages for the home page and the
31563footers.
31564
31565@lisp
31566(service gitile-service-type
31567 (gitile-configuration
31568 (repositories "/srv/git")
31569 (base-git-url "https://myweb.site/git")
31570 (index-title "My git repositories")
31571 (intro '((p "This is all my public work!")))
31572 (footer '((p "This is the end")))
31573 (nginx-server-block
31574 (nginx-server-configuration
31575 (ssl-certificate
31576 "/etc/letsencrypt/live/myweb.site/fullchain.pem")
31577 (ssl-certificate-key
31578 "/etc/letsencrypt/live/myweb.site/privkey.pem")
31579 (listen '("443 ssl http2" "[::]:443 ssl http2"))
31580 (locations
31581 (list
31582 ;; Allow for https anonymous fetch on /git/ urls.
31583 (git-http-nginx-location-configuration
31584 (git-http-configuration
31585 (uri-path "/git/")
31586 (git-root "/var/lib/gitolite/repositories")))))))))
31587@end lisp
31588
31589In addition to the configuration record, you should configure your git
31590repositories to contain some optional information. First, your public
31591repositories need to contain the @file{git-daemon-export-ok} magic file
31592that allows Git to export the repository. Gitile uses the presence of this
31593file to detect public repositories it should make accessible. To do so with
31594Gitolite for instance, modify your @file{conf/gitolite.conf} to include
31595this in the repositories you want to make public:
31596
31597@example
31598repo foo
31599 R = daemon
31600@end example
31601
31602In addition, Gitile can read the repository configuration to display more
31603infomation on the repository. Gitile uses the gitweb namespace for its
31604configuration. As an example, you can use the following in your
31605@file{conf/gitolite.conf}:
31606
31607@example
31608repo foo
31609 R = daemon
31610 desc = A long description, optionally with <i>HTML</i>, shown on the index page
31611 config gitweb.name = The Foo Project
31612 config gitweb.synopsis = A short description, shown on the main page of the project
31613@end example
31614
31615Do not forget to commit and push these changes once you are satisfied. You
31616may need to change your gitolite configuration to allow the previous
31617configuration options to be set. One way to do that is to add the
31618following service definition:
31619
31620@lisp
31621(service gitolite-service-type
31622 (gitolite-configuration
31623 (admin-pubkey (local-file "key.pub"))
31624 (rc-file
31625 (gitolite-rc-file
31626 (umask #o0027)
31627 ;; Allow to set any configuration key
31628 (git-config-keys ".*")
31629 ;; Allow any text as a valid configuration value
31630 (unsafe-patt "^$")))))
31631@end lisp
31632
31633@deftp {Data Type} gitile-configuration
31634Data type representing the configuration for @code{gitile-service-type}.
31635
31636@table @asis
31637@item @code{package} (default: @var{gitile})
31638Gitile package to use.
31639
31640@item @code{host} (default: @code{"localhost"})
31641The host on which gitile is listening.
31642
31643@item @code{port} (default: @code{8080})
31644The port on which gitile is listening.
31645
31646@item @code{database} (default: @code{"/var/lib/gitile/gitile-db.sql"})
31647The location of the database.
31648
31649@item @code{repositories} (default: @code{"/var/lib/gitolite/repositories"})
31650The location of the repositories. Note that only public repositories will
31651be shown by Gitile. To make a repository public, add an empty
31652@file{git-daemon-export-ok} file at the root of that repository.
31653
31654@item @code{base-git-url}
31655The base git url that will be used to show clone commands.
31656
31657@item @code{index-title} (default: @code{"Index"})
31658The page title for the index page that lists all the available repositories.
31659
31660@item @code{intro} (default: @code{'()})
31661The intro content, as a list of sxml expressions. This is shown above the list
31662of repositories, on the index page.
31663
31664@item @code{footer} (default: @code{'()})
31665The footer content, as a list of sxml expressions. This is shown on every
31666page served by Gitile.
31667
31668@item @code{nginx-server-block}
31669An nginx server block that will be extended and used as a reverse proxy by
31670Gitile to serve its pages, and as a normal web server to serve its assets.
31671
31672You can use this block to add more custom URLs to your domain, such as a
31673@code{/git/} URL for anonymous clones, or serving any other files you would
31674like to serve.
31675@end table
31676@end deftp
31677
31678
31547@node Game Services 31679@node Game Services
31548@subsection Game Services 31680@subsection Game Services
31549 31681
diff --git a/gnu/services/version-control.scm b/gnu/services/version-control.scm
index ab86f82e620..3315e80c6ff 100644
--- a/gnu/services/version-control.scm
+++ b/gnu/services/version-control.scm
@@ -4,6 +4,7 @@
4;;; Copyright © 2017 Oleg Pykhalov <go.wigust@gmail.com> 4;;; Copyright © 2017 Oleg Pykhalov <go.wigust@gmail.com>
5;;; Copyright © 2017 Clément Lassieur <clement@lassieur.org> 5;;; Copyright © 2017 Clément Lassieur <clement@lassieur.org>
6;;; Copyright © 2018 Christopher Baines <mail@cbaines.net> 6;;; Copyright © 2018 Christopher Baines <mail@cbaines.net>
7;;; Copyright © 2021 Julien Lepiller <julien@lepiller.eu>
7;;; 8;;;
8;;; This file is part of GNU Guix. 9;;; This file is part of GNU Guix.
9;;; 10;;;
@@ -59,7 +60,21 @@
59 gitolite-rc-file-roles 60 gitolite-rc-file-roles
60 gitolite-rc-file-enable 61 gitolite-rc-file-enable
61 62
62 gitolite-service-type)) 63 gitolite-service-type
64
65 gitile-configuration
66 gitile-configuration-package
67 gitile-configuration-host
68 gitile-configuration-port
69 gitile-configuration-database
70 gitile-configuration-repositories
71 gitile-configuration-git-base-url
72 gitile-configuration-index-title
73 gitile-configuration-intro
74 gitile-configuration-footer
75 gitile-configuration-nginx
76
77 gitile-service-type))
63 78
64;;; Commentary: 79;;; Commentary:
65;;; 80;;;
@@ -386,3 +401,114 @@ access to exported repositories under @file{/srv/git}."
386By default, the @code{git} user is used, but this is configurable. 401By default, the @code{git} user is used, but this is configurable.
387Additionally, Gitolite can integrate with with tools like gitweb or cgit to 402Additionally, Gitolite can integrate with with tools like gitweb or cgit to
388provide a web interface to view selected repositories."))) 403provide a web interface to view selected repositories.")))
404
405;;;
406;;; Gitile
407;;;
408
409(define-record-type* <gitile-configuration>
410 gitile-configuration make-gitile-configuration gitile-configuration?
411 (package gitile-configuration-package
412 (default gitile))
413 (host gitile-configuration-host
414 (default "127.0.0.1"))
415 (port gitile-configuration-port
416 (default 8080))
417 (database gitile-configuration-database
418 (default "/var/lib/gitile/gitile-db.sql"))
419 (repositories gitile-configuration-repositories
420 (default "/var/lib/gitolite/repositories"))
421 (base-git-url gitile-configuration-base-git-url)
422 (index-title gitile-configuration-index-title
423 (default "Index"))
424 (intro gitile-configuration-intro
425 (default '()))
426 (footer gitile-configuration-footer
427 (default '()))
428 (nginx gitile-configuration-nginx))
429
430(define (gitile-config-file host port database repositories base-git-url
431 index-title intro footer)
432 (define build
433 #~(write `(config
434 (port #$port)
435 (host #$host)
436 (database #$database)
437 (repositories #$repositories)
438 (base-git-url #$base-git-url)
439 (index-title #$index-title)
440 (intro #$intro)
441 (footer #$footer))
442 (open-output-file #$output)))
443
444 (computed-file "gitile.conf" build))
445
446(define gitile-nginx-server-block
447 (match-lambda
448 (($ <gitile-configuration> package host port database repositories
449 base-git-url index-title intro footer nginx)
450 (list (nginx-server-configuration
451 (inherit nginx)
452 (locations
453 (append
454 (list
455 (nginx-location-configuration
456 (uri "/")
457 (body
458 (list
459 #~(string-append "proxy_pass http://" #$host
460 ":" (number->string #$port)
461 "/;")))))
462 (map
463 (lambda (loc)
464 (nginx-location-configuration
465 (uri loc)
466 (body
467 (list
468 #~(string-append "root " #$package "/share/gitile/assets;")))))
469 '("/css" "/js" "/images"))
470 (nginx-server-configuration-locations nginx))))))))
471
472(define gitile-shepherd-service
473 (match-lambda
474 (($ <gitile-configuration> package host port database repositories
475 base-git-url index-title intro footer nginx)
476 (list (shepherd-service
477 (provision '(gitile))
478 (requirement '(loopback))
479 (documentation "gitile")
480 (start (let ((gitile (file-append package "/bin/gitile")))
481 #~(make-forkexec-constructor
482 `(,#$gitile "-c" #$(gitile-config-file
483 host port database
484 repositories
485 base-git-url index-title
486 intro footer))
487 #:user "gitile"
488 #:group "git")))
489 (stop #~(make-kill-destructor)))))))
490
491(define %gitile-accounts
492 (list (user-group
493 (name "git")
494 (system? #t))
495 (user-account
496 (name "gitile")
497 (group "git")
498 (system? #t)
499 (comment "Gitile user")
500 (home-directory "/var/empty")
501 (shell (file-append shadow "/sbin/nologin")))))
502
503(define gitile-service-type
504 (service-type
505 (name 'gitile)
506 (description "Run Gitile, a small Git forge. Expose public repositories
507on the web.")
508 (extensions
509 (list (service-extension account-service-type
510 (const %gitile-accounts))
511 (service-extension shepherd-root-service-type
512 gitile-shepherd-service)
513 (service-extension nginx-service-type
514 gitile-nginx-server-block)))))
diff --git a/gnu/tests/version-control.scm b/gnu/tests/version-control.scm
index d3cf19c9138..a7cde1f1632 100644
--- a/gnu/tests/version-control.scm
+++ b/gnu/tests/version-control.scm
@@ -38,7 +38,8 @@
38 #:use-module (guix modules) 38 #:use-module (guix modules)
39 #:export (%test-cgit 39 #:export (%test-cgit
40 %test-git-http 40 %test-git-http
41 %test-gitolite)) 41 %test-gitolite
42 %test-gitile))
42 43
43(define README-contents 44(define README-contents
44 "Hello! This is what goes inside the 'README' file.") 45 "Hello! This is what goes inside the 'README' file.")
@@ -63,7 +64,10 @@
63 (invoke git "commit" "-m" "That's a commit.")) 64 (invoke git "commit" "-m" "That's a commit."))
64 65
65 (mkdir-p "/srv/git") 66 (mkdir-p "/srv/git")
66 (rename-file "/tmp/test-repo/.git" "/srv/git/test"))))) 67 (rename-file "/tmp/test-repo/.git" "/srv/git/test")
68 (with-output-to-file "/srv/git/test/git-daemon-export-ok"
69 (lambda _
70 (display "")))))))
67 71
68(define %test-repository-service 72(define %test-repository-service
69 ;; Service that creates /srv/git/test. 73 ;; Service that creates /srv/git/test.
@@ -416,3 +420,133 @@ HTTP-PORT."
416 (name "gitolite") 420 (name "gitolite")
417 (description "Clone the Gitolite admin repository.") 421 (description "Clone the Gitolite admin repository.")
418 (value (run-gitolite-test)))) 422 (value (run-gitolite-test))))
423
424;;;
425;;; Gitile.
426;;;
427
428(define %gitile-configuration-nginx
429 (nginx-server-configuration
430 (root "/does/not/exists")
431 (try-files (list "$uri" "=404"))
432 (listen '("19418"))
433 (ssl-certificate #f)
434 (ssl-certificate-key #f)))
435
436(define %gitile-os
437 ;; Operating system under test.
438 (simple-operating-system
439 (service dhcp-client-service-type)
440 (simple-service 'srv-git activation-service-type
441 #~(mkdir-p "/srv/git"))
442 (service gitile-service-type
443 (gitile-configuration
444 (base-git-url "http://localhost")
445 (repositories "/srv/git")
446 (nginx %gitile-configuration-nginx)))
447 %test-repository-service))
448
449(define* (run-gitile-test #:optional (http-port 19418))
450 "Run tests in %GITOLITE-OS, which has nginx running and listening on
451HTTP-PORT."
452 (define os
453 (marionette-operating-system
454 %gitile-os
455 #:imported-modules '((gnu services herd)
456 (guix combinators))))
457
458 (define vm
459 (virtual-machine
460 (operating-system os)
461 (port-forwardings `((8081 . ,http-port)))))
462
463 (define test
464 (with-imported-modules '((gnu build marionette))
465 #~(begin
466 (use-modules (srfi srfi-11) (srfi srfi-64)
467 (gnu build marionette)
468 (web uri)
469 (web client)
470 (web response))
471
472 (define marionette
473 (make-marionette (list #$vm)))
474
475 (mkdir #$output)
476 (chdir #$output)
477
478 (test-begin "gitile")
479
480 ;; XXX: Shepherd reads the config file *before* binding its control
481 ;; socket, so /var/run/shepherd/socket might not exist yet when the
482 ;; 'marionette' service is started.
483 (test-assert "shepherd socket ready"
484 (marionette-eval
485 `(begin
486 (use-modules (gnu services herd))
487 (let loop ((i 10))
488 (cond ((file-exists? (%shepherd-socket-file))
489 #t)
490 ((> i 0)
491 (sleep 1)
492 (loop (- i 1)))
493 (else
494 'failure))))
495 marionette))
496
497 ;; Wait for nginx to be up and running.
498 (test-assert "nginx running"
499 (marionette-eval
500 '(begin
501 (use-modules (gnu services herd))
502 (start-service 'nginx))
503 marionette))
504
505 ;; Make sure the PID file is created.
506 (test-assert "PID file"
507 (marionette-eval
508 '(file-exists? "/var/run/nginx/pid")
509 marionette))
510
511 ;; Make sure Git test repository is created.
512 (test-assert "Git test repository"
513 (marionette-eval
514 '(file-exists? "/srv/git/test")
515 marionette))
516
517 (sleep 2)
518
519 ;; Make sure we can access pages that correspond to our repository.
520 (letrec-syntax ((test-url
521 (syntax-rules ()
522 ((_ path code)
523 (test-equal (string-append "GET " path)
524 code
525 (let-values (((response body)
526 (http-get (string-append
527 "http://localhost:8081"
528 path))))
529 (response-code response))))
530 ((_ path)
531 (test-url path 200)))))
532 (test-url "/")
533 (test-url "/css/gitile.css")
534 (test-url "/test")
535 (test-url "/test/commits")
536 (test-url "/test/tree" 404)
537 (test-url "/test/tree/-")
538 (test-url "/test/tree/-/README")
539 (test-url "/test/does-not-exist" 404)
540 (test-url "/test/tree/-/does-not-exist" 404)
541 (test-url "/does-not-exist" 404))
542
543 (test-end)
544 (exit (= (test-runner-fail-count (test-runner-current)) 0)))))
545
546 (gexp->derivation "gitile-test" test))
547
548(define %test-gitile
549 (system-test
550 (name "gitile")
551 (description "Connect to a running Gitile server.")
552 (value (run-gitile-test))))