;;; guix-forge --- Guix software forge meta-service ;;; Copyright © 2023 Arun Isaac ;;; ;;; This file is part of guix-forge. ;;; ;;; guix-forge is free software: you can redistribute it and/or modify ;;; it under the terms of the GNU General Public License as published ;;; by the Free Software Foundation, either version 3 of the License, ;;; or (at your option) any later version. ;;; ;;; guix-forge is distributed in the hope that it will be useful, but ;;; WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;; General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with guix-forge. If not, see ;;; . (define-module (forge klaus) #:use-module (forge gunicorn) #:use-module (forge socket) #:use-module ((gnu packages check) #:select (python-nose python-pytest)) #:use-module ((gnu packages python-web) #:select (python-flask python-werkzeug)) #:use-module ((gnu packages python-xyz) #:select (python-dulwich python-humanize python-pygments)) #:use-module ((gnu packages version-control) #:select (git-minimal)) #:use-module (gnu system file-systems) #:use-module (guix build-system pyproject) #:use-module (guix build-system python) #:use-module (guix download) #:use-module (guix gexp) #:use-module ((guix licenses) #:prefix license:) #:use-module (guix packages) #:use-module (guix utils) #:export (klaus-gunicorn-app)) (define-public python-httpauth (package (name "python-httpauth") (version "0.3") (source (origin (method url-fetch) (uri (pypi-uri "httpauth" version)) (sha256 (base32 "0qas7876igyz978pgldp5r7n7pis8n4vf0v87gxr9l7p7if5lr3l")))) (build-system pyproject-build-system) (native-inputs (list python-nose)) (home-page "https://github.com/jonashaag/httpauth") (synopsis "WSGI HTTP Digest Authentication middleware") (description "@code{python-httpauth} is WSGI middleware that secures some/all routes using HTTP Digest Authentication.") (license license:bsd-2))) ;; We use klaus to serve shared repositories. But, git's safe ;; directory check does not permit us to use shared ;; repositories. Disable it. The more long term solution is to rewrite ;; klaus to not use the git CLI at all. See ;; https://github.com/jonashaag/klaus/issues/322 (define-public git-without-safe-directory-check (package (inherit git-minimal) (name "git-without-safe-directory-check") (arguments (substitute-keyword-arguments (package-arguments git-minimal) ((#:phases phases #~%standard-phases) #~(modify-phases #$phases (add-after 'unpack 'disable-safe-directory-check (lambda _ ;; Disable the safe directory check. (substitute* "setup.c" (("return data\\.is_safe;") "return 1;")) ;; Disable tests broken by this change. (setenv "GIT_SKIP_TESTS" "t0033 t9700"))))))))) (define-public python-klaus (package (name "python-klaus") (version "2.0.3") (source (origin (method url-fetch) (uri (pypi-uri "klaus" version)) (sha256 (base32 "1y06xnynfah5d4zif2fc0n83zdr0d1vkh0rwcinsi6wjxalvnhjw")))) (build-system pyproject-build-system) (arguments (list #:tests? #f ; tests fail #:phases #~(modify-phases %standard-phases (add-after 'unpack 'configure-git (lambda* (#:key inputs #:allow-other-keys) (for-each (lambda (file) (substitute* file (("\"git\"") (string-append "\"" (search-input-file inputs "/bin/git") "\"")))) (list "klaus/ctagsutils.py" "klaus/repo.py" "klaus/utils.py" "tests/test_contrib.py" "tests/test_make_app.py"))))))) (inputs (list git-without-safe-directory-check)) (native-inputs (list python-pytest)) (propagated-inputs (list python-dulwich python-flask python-httpauth python-humanize python-pygments python-werkzeug)) (home-page "https://github.com/jonashaag/klaus") (synopsis "Simple git web viewer") (description "klaus is a simple, easy-to-set-up git web viewer. It features @itemize @item Super easy to set up -- no configuration required @item Syntax highlighting @item Markdown + RestructuredText rendering support @item Pull + push support (Git Smart HTTP) @item Code navigation using Exuberant ctags @end itemize") (license license:isc))) (define* (klaus-gunicorn-app repository-directory #:key (sockets (list (forge-unix-socket (path "/var/run/gunicorn-klaus/socket")))) site-name) "Return a @code{} object to deploy klaus. @var{repository-directory} is the path to the directory containing git repositories to serve. @var{sockets} is a list of @code{} or @code{} objects describing sockets to listen on. @var{site-name} is the name of the klaus site to be displayed in the banner." (gunicorn-app (name "klaus") (package python-klaus) (wsgi-app-module "klaus.contrib.wsgi_autoreload") (sockets sockets) (environment-variables `(("KLAUS_REPOS_ROOT" . ,repository-directory) ,@(if site-name `(("KLAUS_SITE_NAME" . ,site-name)) '()))) (mappings (list (file-system-mapping (source repository-directory) (target source))))))