summary refs log tree commit diff
path: root/forge
diff options
context:
space:
mode:
Diffstat (limited to 'forge')
-rw-r--r--forge/build/git.scm76
-rw-r--r--forge/forge.scm287
-rw-r--r--forge/laminar.scm135
-rw-r--r--forge/utils.scm70
-rw-r--r--forge/webhook.scm193
5 files changed, 0 insertions, 761 deletions
diff --git a/forge/build/git.scm b/forge/build/git.scm
deleted file mode 100644
index 1434d07..0000000
--- a/forge/build/git.scm
+++ /dev/null
@@ -1,76 +0,0 @@
-;;; guix-forge --- Guix software forge meta-service
-;;; Copyright © 2022 Arun Isaac <arunisaac@systemreboot.net>
-;;;
-;;; 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
-;;; <https://www.gnu.org/licenses/>.
-
-(define-module (forge build git)
-  #:use-module (rnrs exceptions)
-  #:use-module (guix build utils)
-  #:use-module (guix store)
-  #:use-module (guix utils)
-  #:export (download-git-to-store
-            latest-git-checkout))
-
-;;;
-;;; Commentary:
-;;;
-;;; This module provides build-side code to download a git repository
-;;; to the store.
-;;;
-
-;;; Code:
-
-(define (hline)
-  "Print a horizontal line 50 '=' characters long."
-  (display (make-string 50 #\=))
-  (newline)
-  (force-output))
-
-(define* (download-git-to-store store name url #:key branch show-commit?)
-  "Download BRANCH of git repository from URL to STORE under NAME and
-return store path. If BRANCH is not specified, the default branch is
-downloaded. git and certificates should be in the environment."
-  (call-with-temporary-directory
-   (lambda (directory)
-     (with-directory-excursion directory
-       (guard (condition ((invoke-error? condition)
-                          (format (current-error-port)
-                                  "'~a~{ ~a~}' failed with exit code ~a~%"
-                                  (invoke-error-program condition)
-                                  (invoke-error-arguments condition)
-                                  (invoke-error-exit-status condition))
-                          (exit #f)))
-         (apply invoke
-                "git" "clone" "--quiet" "--depth" "1"
-                ;; Append file:// to local repository path so that
-                ;; shallow clone works.
-                (if (string-prefix? "/" url)
-                    (string-append "file://" url)
-                    url)
-                (append (if branch
-                            (list "--branch" branch)
-                            (list))
-                        (list "."))))
-       (when show-commit?
-         (hline)
-         (invoke "git" "--no-pager" "log")
-         (hline))
-       (delete-file-recursively ".git"))
-     (add-to-store store name #t "sha256" directory))))
-
-(define latest-git-checkout
-  (store-lift download-git-to-store))
diff --git a/forge/forge.scm b/forge/forge.scm
deleted file mode 100644
index e88edb0..0000000
--- a/forge/forge.scm
+++ /dev/null
@@ -1,287 +0,0 @@
-;;; guix-forge --- Guix software forge meta-service
-;;; Copyright © 2021, 2022 Arun Isaac <arunisaac@systemreboot.net>
-;;;
-;;; 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
-;;; <https://www.gnu.org/licenses/>.
-
-(define-module (forge forge)
-  #:use-module (gnu)
-  #:use-module (srfi srfi-1)
-  #:use-module (srfi srfi-26)
-  #:use-module (ice-9 match)
-  #:use-module ((gnu packages certs) #:select (nss-certs))
-  #:use-module (gnu packages ci)
-  #:use-module ((gnu packages gnupg) #:select (guile-gcrypt))
-  #:use-module ((gnu packages guile) #:select (guile-3.0 guile-zlib))
-  #:use-module ((gnu packages version-control) #:select (git-minimal))
-  #:use-module (gnu services mcron)
-  #:use-module (guix modules)
-  #:use-module (guix packages)
-  #:use-module (guix records)
-  #:use-module (guix store)
-  #:use-module (forge laminar)
-  #:use-module (forge utils)
-  #:use-module (forge webhook)
-  #:export (forge-service-type
-            forge-configuration
-            forge-configuration?
-            forge-configuration-projects
-            forge-project
-            forge-project?
-            this-forge-project
-            forge-project-name
-            forge-project-user
-            forge-project-repository
-            forge-project-repository-branch
-            forge-project-website-directory
-            forge-project-ci-jobs
-            forge-project-ci-jobs-trigger
-            derivation-job-gexp))
-
-(define-record-type* <forge-project>
-  forge-project make-forge-project
-  forge-project?
-  this-forge-project
-  (name forge-project-name)
-  ;; The user field is optional because the repository may be remote
-  ;; and not need to be owned by any user.
-  (user forge-project-user
-        (default #f))
-  (repository forge-project-repository)
-  (repository-branch forge-project-repository-branch
-                     (default "main"))
-  (description forge-project-description
-               (default #f))
-  (website-directory forge-project-website-directory
-                     (default #f))
-  (ci-jobs forge-project-ci-jobs
-           (default '()) (thunked))
-  (ci-jobs-trigger forge-project-ci-jobs-trigger ; one of 'post-receive-hook, 'cron, 'webhook
-                   (default (cond
-                             ;; 'post-receive-hook for local repositories
-                             ((string-prefix? "/" (forge-project-repository this-forge-project))
-                              'post-receive-hook)
-                             ;; 'cron for remote repositories
-                             (else 'cron)))
-                   (thunked)))
-
-(define-record-type* <forge-configuration>
-  forge-configuration make-forge-configuration
-  forge-configuration?
-  (projects forge-configuration-projects
-            (default '())))
-
-(define* (ci-jobs-trigger-gexp ci-jobs #:key reason)
-  "Return a G-expression that triggers CI-JOBS. CI-JOBS is a list of
-<forge-laminar-job> objects."
-  (with-imported-modules '((guix build utils))
-    #~(begin
-        (use-modules (guix build utils))
-        ;; TODO: Only trigger on updates to the main/master branch.
-        (display "Triggering continuous integration jobs..." (current-error-port))
-        (newline (current-error-port))
-        (when #$reason
-          (setenv "LAMINAR_REASON" #$reason))
-        (apply invoke
-               #$(file-append laminar "/bin/laminarc")
-               "queue" '#$(map forge-laminar-job-name ci-jobs)))))
-
-(define (forge-activation config)
-  (let ((projects
-         (map (lambda (project)
-                (list (forge-project-user project)
-                      (forge-project-repository project)
-                      (forge-project-description project)
-                      (forge-project-website-directory project)
-                      (program-file
-                       (forge-project-name project)
-                       (ci-jobs-trigger-gexp
-                        (forge-project-ci-jobs project)
-                        #:reason "post-receive hook"))
-                      (forge-project-ci-jobs-trigger project)))
-              (forge-configuration-projects config))))
-    #~(begin
-        (use-modules (rnrs io ports)
-                     (srfi srfi-26)
-                     (ice-9 match))
-        
-        (define (find-regular-files dir)
-          (find-files dir (lambda (file stat)
-                            (memq (stat:type stat)
-                                  '(regular directory)))
-                      #:directories? #t))
-        
-        (for-each (match-lambda
-                    ((username repository description website-directory ci-jobs-trigger ci-jobs-trigger-type)
-                     ;; For local repositories only
-                     (when (string-prefix? "/" repository)
-                       ;; Set description.
-                       (when description
-                         (call-with-output-file (string-append repository "/description")
-                           (cut put-string <> description)))
-                       ;; Set ownership of repository files.
-                       (for-each (lambda (file)
-                                   (let ((user (getpw username)))
-                                     (chown file (passwd:uid user) (passwd:gid user))))
-                                 (append (find-regular-files repository))))
-                     ;; Install post receive hook.
-                     (when (eq? ci-jobs-trigger-type 'post-receive-hook)
-                       (let ((hook-link (string-append repository "/hooks/post-receive")))
-                         (when (file-exists? hook-link)
-                           (delete-file hook-link))
-                         (symlink ci-jobs-trigger hook-link)))
-                     ;; Set ownership of website directory.
-                     (when website-directory
-                       (let ((user (getpw "laminar")))
-                         (chown website-directory (passwd:uid user) (passwd:gid user))))))
-                  '#$projects))))
-
-(define (import-module? name)
-  "Return #t if module NAME may be imported.  Else, return #f."
-  (match name
-    (('forge _ ...) #t)
-    (name (guix-module-name? name))))
-
-(define* (derivation-job-gexp project job gexp-producer
-                              #:key (guix-daemon-uri (%daemon-socket-uri)))
-  "Return a G-expression that builds another G-expression as a
-derivation and returns its output path. GEXP-PRODUCER is a
-G-expression that expands to a lambda function. The lambda function
-takes one argument---the latest git checkout of PROJECT, a
-<forge-project> object---and returns a G-expression describing a
-derivation to run. JOB is a <forge-laminar-job> object representing
-the job that this derivation will be part of. GUIX_DAEMON_URI is a
-file name or URI designating the Guix daemon endpoint."
-  (with-imported-modules (source-module-closure '((forge build git)
-                                                  (guix gexp)
-                                                  (guix profiles))
-                                                #:select? import-module?)
-    (with-extensions (list guile-gcrypt guile-zlib)
-      (with-packages (list git-minimal nss-certs)
-        #~(begin
-            ;; We pull out macros using module-ref and functions using
-            ;; @@ instead of using use-modules because this gexp might
-            ;; be substituted into other gexps and use-modules only
-            ;; works at the top-level.
-            (let-syntax ((guard (macro-transformer
-                                 (module-ref (resolve-module '(rnrs exceptions))
-                                             'guard)))
-                         (mbegin (macro-transformer
-                                  (module-ref (resolve-module '(guix monads))
-                                              'mbegin)))
-                         (mlet* (macro-transformer
-                                 (module-ref (resolve-module '(guix monads))
-                                             'mlet*)))
-                         (with-store (macro-transformer
-                                      (module-ref (resolve-module '(guix store))
-                                                  'with-store)))
-                         (return (identifier-syntax ((@@ (guix store) %store-monad)
-                                                     %return))))
-              (let* ((latest-git-checkout (@@ (forge build git) latest-git-checkout))
-                     (built-derivations (@@ (guix derivations) built-derivations))
-                     (derivation->output-path (@@ (guix derivations) derivation->output-path))
-                     (read-derivation-from-file (@@ (guix derivations) read-derivation-from-file))
-                     (gexp->derivation (@@ (guix gexp) gexp->derivation))
-                     (%daemon-socket-uri (@@ (guix store) %daemon-socket-uri))
-                     (%store-monad (@@ (guix store) %store-monad))
-                     (store-protocol-error? (@@ (guix store) store-protocol-error?))
-                     (run-with-store (@@ (guix store) run-with-store))
-                     (derivation-output
-                      (parameterize ((%daemon-socket-uri #$guix-daemon-uri))
-                        (with-store store
-                          (guard (condition ((store-protocol-error? condition)
-                                             (exit #f)))
-                            (run-with-store store
-                              (mlet* %store-monad ((git-checkout (latest-git-checkout
-                                                                  #$(string-append (forge-project-name project)
-                                                                                   "-checkout")
-                                                                  #$(forge-project-repository project)
-                                                                  #:show-commit? #t))
-                                                   (drv (gexp->derivation #$(string-append
-                                                                             (forge-laminar-job-name job)
-                                                                             "-derivation")
-                                                          (#$gexp-producer git-checkout)
-                                                          #:guile-for-build (read-derivation-from-file
-                                                                             #$(raw-derivation-file
-                                                                                (with-store store
-                                                                                  (package-derivation store guile-3.0))))
-                                                          #:substitutable? #f)))
-                                (mbegin %store-monad
-                                  (built-derivations (list drv))
-                                  (return (derivation->output-path drv))))))))))
-                (format (current-error-port) "Built ~a successfully~%" derivation-output)
-                derivation-output)))))))
-
-(define forge-service-type
-  (service-type
-   (name 'forge)
-   (description "Run guix-forge.")
-   (extensions (list (service-extension activation-service-type
-                                        forge-activation)
-                     (service-extension forge-laminar-service-type
-                                        (lambda (config)
-                                          (append
-                                           ;; jobs
-                                           (append-map forge-project-ci-jobs
-                                                       (forge-configuration-projects config))
-                                           ;; group jobs by project
-                                           (filter-map (lambda (project)
-                                                         (match (forge-project-ci-jobs project)
-                                                           (() #f)
-                                                           ((job) #f)
-                                                           (jobs
-                                                            (forge-laminar-group
-                                                             (name (forge-project-name project))
-                                                             (regex (string-append "^(?:"
-                                                                                   (string-join (map forge-laminar-job-name jobs)
-                                                                                                "|")
-                                                                                   ")$"))))))
-                                                       (forge-configuration-projects config)))))
-                     ;; Set up cron jobs to trigger CI jobs for remote
-                     ;; repositories.
-                     ;; TODO: Run CI job only if there are new commits
-                     ;; in the remote repository.
-                     (service-extension mcron-service-type
-                                        (lambda (config)
-                                          (filter-map (lambda (project)
-                                                        (and (eq? (forge-project-ci-jobs-trigger project)
-                                                                  'cron)
-                                                             #~(job '(next-day)
-                                                                    #$(program-file
-                                                                       (forge-project-name project)
-                                                                       (ci-jobs-trigger-gexp
-                                                                        (forge-project-ci-jobs project)
-                                                                        #:reason "Cron job"))
-                                                                    #:user "laminar")))
-                                                      (forge-configuration-projects config))))
-                     (service-extension webhook-service-type
-                                        (lambda (config)
-                                          (filter-map (lambda (project)
-                                                        (and (eq? (forge-project-ci-jobs-trigger project)
-                                                                  'webhook)
-                                                             (webhook-hook
-                                                              (id (forge-project-name project))
-                                                              (run (ci-jobs-trigger-gexp
-                                                                    (forge-project-ci-jobs project)
-                                                                    #:reason "Webhook")))))
-                                                      (forge-configuration-projects config))))))
-   (compose concatenate)
-   (extend (lambda (config projects)
-             (forge-configuration
-              (inherit config)
-              (projects (append (forge-configuration-projects config)
-                                projects)))))
-   (default-value (forge-configuration))))
diff --git a/forge/laminar.scm b/forge/laminar.scm
deleted file mode 100644
index 5d95372..0000000
--- a/forge/laminar.scm
+++ /dev/null
@@ -1,135 +0,0 @@
-;;; guix-forge --- Guix software forge meta-service
-;;; Copyright © 2021, 2022 Arun Isaac <arunisaac@systemreboot.net>
-;;;
-;;; 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
-;;; <https://www.gnu.org/licenses/>.
-
-(define-module (forge laminar)
-  #:use-module (gnu)
-  #:use-module (srfi srfi-1)
-  #:use-module (gnu packages ci)
-  #:use-module (gnu services ci)
-  #:use-module (guix records)
-  #:export (forge-laminar-service-type
-            forge-laminar-configuration
-            forge-laminar-configuration?
-            forge-laminar-configuration-state-directory
-            forge-laminar-configuration-jobs
-            forge-laminar-job
-            forge-laminar-job?
-            this-forge-laminar-job
-            forge-laminar-job-name
-            forge-laminar-job-run
-            forge-laminar-job-after
-            forge-laminar-group
-            forge-laminar-group?
-            forge-laminar-group-name
-            forge-laminar-group-regex))
-
-(define-record-type* <forge-laminar-configuration>
-  forge-laminar-configuration make-forge-laminar-configuration
-  forge-laminar-configuration?
-  (state-directory forge-laminar-configuration-state-directory
-                   (default "/var/lib/laminar"))
-  (jobs forge-laminar-configuration-jobs
-        (default '()))
-  (groups forge-laminar-configuration-groups
-          (default '())))
-
-(define-record-type* <forge-laminar-job>
-  forge-laminar-job make-forge-laminar-job
-  forge-laminar-job?
-  this-forge-laminar-job
-  (name forge-laminar-job-name)
-  (run forge-laminar-job-run (thunked))
-  (after forge-laminar-job-after
-         (default #f)))
-
-(define-record-type* <forge-laminar-group>
-  forge-laminar-group make-forge-laminar-group
-  forge-laminar-group?
-  (name forge-laminar-group-name)
-  (regex forge-laminar-group-regex))
-
-(define (forge-laminar-activation config)
-  (let* ((state-directory (forge-laminar-configuration-state-directory config))
-         (configuration-directory (string-append state-directory "/cfg"))
-         (groups-configuration (string-append configuration-directory "/groups.conf"))
-         (jobs-directory (string-append configuration-directory "/jobs")))
-    #~(begin
-        (use-modules (srfi srfi-26))
-
-        ;; Ensure configuration directory exists.
-        (mkdir-p #$configuration-directory)
-        ;; Configure groups.
-        (when (file-exists? #$groups-configuration)
-          (delete-file #$groups-configuration))
-        (symlink
-         #$(plain-file "laminar-groups"
-                       (string-join (map (lambda (group)
-                                           (string-append (forge-laminar-group-name group)
-                                                          "="
-                                                          (forge-laminar-group-regex group)))
-                                         (forge-laminar-configuration-groups config))
-                                    "\n"))
-         #$groups-configuration)
-        ;; Create jobs directory and populate with job scripts.
-        (mkdir-p #$(dirname jobs-directory))
-        (when (file-exists? #$jobs-directory)
-          (delete-file #$jobs-directory))
-        (symlink
-         #$(file-union "laminar-jobs"
-                       (append-map (lambda (job)
-                                     (let ((name (forge-laminar-job-name job))
-                                           (run (forge-laminar-job-run job))
-                                           (after (forge-laminar-job-after job)))
-                                       (cons (list (string-append name ".run")
-                                                   (program-file name run))
-                                             (if after
-                                                 (list (list (string-append name ".after")
-                                                             (program-file name after)))
-                                                 (list)))))
-                                   (forge-laminar-configuration-jobs config)))
-         #$jobs-directory)
-        ;; Set permissions for laminar directory.
-        (for-each (lambda (file)
-                    (let ((user (getpw "laminar")))
-                      (chown file (passwd:uid user) (passwd:gid user))))
-                  (find-files #$state-directory
-                              (lambda (file stat)
-                                (memq (stat:type stat)
-                                      '(regular directory)))
-                              #:directories? #t)))))
-
-(define forge-laminar-service-type
-  (service-type
-   (name 'forge-laminar)
-   (description "Run forge-laminar.")
-   (extensions (list (service-extension activation-service-type
-                                        forge-laminar-activation)
-                     ;; Extend the laminar service with a dummy value,
-                     ;; thus requiring it.
-                     (service-extension laminar-service-type
-                                        (const #t))))
-   (compose concatenate)
-   (extend (lambda (config extended-values)
-             (forge-laminar-configuration
-              (inherit config)
-              (jobs (append (forge-laminar-configuration-jobs config)
-                            (filter forge-laminar-job? extended-values)))
-              (groups (append (forge-laminar-configuration-groups config)
-                              (filter forge-laminar-group? extended-values))))))
-   (default-value (forge-laminar-configuration))))
diff --git a/forge/utils.scm b/forge/utils.scm
deleted file mode 100644
index dd980ef..0000000
--- a/forge/utils.scm
+++ /dev/null
@@ -1,70 +0,0 @@
-;;; guix-forge --- Guix software forge meta-service
-;;; Copyright © 2022 Arun Isaac <arunisaac@systemreboot.net>
-;;;
-;;; 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
-;;; <https://www.gnu.org/licenses/>.
-
-(define-module (forge utils)
-  #:use-module (ice-9 match)
-  #:use-module (guix derivations)
-  #:use-module (guix gexp)
-  #:use-module (guix monads)
-  #:use-module (guix profiles)
-  #:use-module (guix search-paths)
-  #:use-module (guix store)
-  #:export (with-packages))
-
-(define (profile-with-packages packages)
-  "Return profile with PACKAGES."
-  (with-store store
-    (run-with-store store
-      (mlet* %store-monad ((prof-drv (profile-derivation
-                                      (packages->manifest packages)))
-                           (profile -> (derivation->output-path prof-drv)))
-        (mbegin %store-monad
-          (built-derivations (list prof-drv))
-          (return profile))))))
-
-(define (environment-with-packages packages)
-  "Return environment of a profile with PACKAGES. Return value is an
-association list mapping the name of an environment variable to its
-value."
-  (map (match-lambda
-         ((search-path . value)
-          (cons (search-path-specification-variable search-path)
-                value)))
-       (profile-search-paths (profile-with-packages packages))))
-
-(define (with-packages packages exp)
-  "Return a gexp executing EXP, another gexp, in an environment where
-PACKAGES are available and their search path environment variables
-have been set."
-  #~(begin
-      ;; Add a reference to the profile.
-      #$(profile-with-packages packages)
-      ;; Set the environment.
-      ;; We pull out match-lambda using module-ref instead of using
-      ;; use-modules because this gexp will be substituted into other
-      ;; gexps and use-modules only works at the top-level.
-      (let-syntax ((match-lambda (macro-transformer
-                                  (module-ref (resolve-module '(ice-9 match))
-                                              'match-lambda))))
-        (for-each (match-lambda
-                    ((variable . value)
-                     (setenv variable value)))
-                  '#$(environment-with-packages packages)))
-      ;; Run the provided expression.
-      #$exp))
diff --git a/forge/webhook.scm b/forge/webhook.scm
deleted file mode 100644
index 737b9e6..0000000
--- a/forge/webhook.scm
+++ /dev/null
@@ -1,193 +0,0 @@
-;;; guix-forge --- Guix software forge meta-service
-;;; Copyright © 2022 Arun Isaac <arunisaac@systemreboot.net>
-;;;
-;;; 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
-;;; <https://www.gnu.org/licenses/>.
-
-(define-module (forge webhook)
-  #:use-module (srfi srfi-1)
-  #:use-module ((gnu packages admin) #:select (shadow))
-  #:use-module ((gnu packages guile) #:select (guile-json-4))
-  #:use-module (gnu services)
-  #:use-module (gnu services shepherd)
-  #:use-module (gnu system accounts)
-  #:use-module (gnu system shadow)
-  #:use-module (guix gexp)
-  #:use-module (guix modules)
-  #:use-module (guix records)
-  #:use-module (guix packages)
-  #:use-module (guix git-download)
-  #:use-module (guix build-system go)
-  #:use-module ((guix licenses) #:prefix license:)
-  #:export (webhook-service-type
-            webhook-configuration
-            webhook-configuration?
-            webhook-configuration-package
-            webhook-configuration-port
-            webhook-configuration-log-directory
-            webhook-configuration-hooks
-            webhook-hook
-            webhook-hook?
-            webhook-hook-id
-            webhook-hook-run))
-
-(define webhook
-  (package
-    (name "webhook")
-    (version "2.8.0")
-    (source (origin
-              (method git-fetch)
-              (uri (git-reference
-                    (url "https://github.com/adnanh/webhook")
-                    (commit version)))
-              (file-name (git-file-name name version))
-              (sha256
-               (base32
-                "0n03xkgwpzans0cymmzb0iiks8mi2c76xxdak780dk0jbv6qgp5i"))))
-    (build-system go-build-system)
-    (arguments
-     `(#:import-path "github.com/adnanh/webhook"
-       #:phases
-       (modify-phases %standard-phases
-         (add-after 'unpack 'configure
-           (lambda* (#:key inputs #:allow-other-keys)
-             (substitute* "src/github.com/adnanh/webhook/webhook_test.go"
-               (("/bin/echo")
-                (string-append (assoc-ref inputs "coreutils")
-                               "/bin/echo"))))))))
-    (home-page "https://github.com/adnanh/webhook")
-    (synopsis "Lightweight incoming webhook server")
-    (description "webhook is a lightweight configurable tool written
-in Go, that allows you to easily create HTTP endpoints (hooks) on your
-server, which you can use to execute configured commands. You can also
-pass data from the HTTP request (such as headers, payload or query
-variables) to your commands. webhook also allows you to specify rules
-which have to be satisfied in order for the hook to be triggered.
-
-For example, if you're using Github or Bitbucket, you can use webhook
-to set up a hook that runs a redeploy script for your project on your
-staging server, whenever you push changes to the master branch of your
-project.
-
-If you use Mattermost or Slack, you can set up an \"Outgoing webhook
-integration\" or \"Slash command\" to run various commands on your
-server, which can then report back directly to you or your channels
-using the \"Incoming webhook integrations\", or the appropriate
-response body.
-
-webhook aims to do nothing more than it should do, and that is:
-
-@itemize
-@item receive the request,
-@item parse the headers, payload and query variables,
-@item check if the specified rules for the hook are satisfied,
-@item and finally, pass the specified arguments to the specified
-command via command line arguments or via environment variables.
-@end itemize
-
-Everything else is the responsibility of the command's author.")
-    (license license:expat)))
-
-(define-record-type* <webhook-configuration>
-  webhook-configuration make-webhook-configuration
-  webhook-configuration?
-  (package webhook-configuration-package
-           (default webhook))
-  (ip webhook-configuration-ip
-      (default "127.0.0.1"))
-  (port webhook-configuration-port
-        (default 9000))
-  (log-directory webhook-configuration-log-directory
-                 (default "/var/log/webhook"))
-  (hooks webhook-configuration-hooks
-         (default '())))
-
-(define-record-type* <webhook-hook>
-  webhook-hook make-webhook-hook
-  webhook-hook?
-  (id webhook-hook-id)
-  (run webhook-hook-run))
-
-(define (webhook-activation config)
-  ;; Create log directory.
-  #~(mkdir-p #$(webhook-configuration-log-directory config)))
-
-(define (hooks-json-gexp config)
-  (with-extensions (list guile-json-4)
-    #~(begin
-        (use-modules (srfi srfi-26)
-                     (json))
-        
-        (call-with-output-file #$output
-          (cut scm->json
-               ;; We convert from list to vector on the build-side
-               ;; because a vector cannot be lowered correctly into a
-               ;; G-expression.
-               (list->vector
-                ;; We build a true dotted association list in this
-                ;; roundabout way because a true dotted association
-                ;; list cannot be lowered correctly into a
-                ;; G-expression.
-                (map (cut map (cut apply cons <>) <>)
-                     '#$(map (lambda (hook)
-                               `(("id" ,(webhook-hook-id hook))
-                                 ("execute-command" ,(program-file (webhook-hook-id hook)
-                                                                   (webhook-hook-run hook)))))
-                             (webhook-configuration-hooks config))))
-               <>)))))
-
-(define webhook-shepherd-service
-  (lambda (config)
-    (shepherd-service
-     (documentation "Run webhook.")
-     (provision '(webhook))
-     (requirement '(networking))
-     (modules '((gnu build shepherd)
-                (gnu system file-systems)))
-     (start (with-imported-modules (source-module-closure
-                                    '((gnu build shepherd)
-                                      (gnu system file-systems)))
-              #~(make-forkexec-constructor/container
-                 (list #$(file-append (webhook-configuration-package config)
-                                      "/bin/webhook")
-                       "-hooks" #$(computed-file "hooks.json"
-                                                 (hooks-json-gexp config))
-                       "-ip" #$(webhook-configuration-ip config)
-                       "-port" #$(number->string (webhook-configuration-port config))
-                       "-logfile" #$(string-append (webhook-configuration-log-directory config)
-                                                   "/webhook.log"))
-                 #:mappings (list (file-system-mapping
-                                   (source #$(webhook-configuration-log-directory config))
-                                   (target source)
-                                   (writable? #t)))
-                 #:log-file "/var/log/webhook.log")))
-     (stop #~(make-kill-destructor)))))
-
-(define webhook-service-type
-  (service-type
-   (name 'webhook)
-   (description "Run webhook.")
-   (extensions (list (service-extension activation-service-type
-                                        webhook-activation)
-                     (service-extension shepherd-root-service-type
-                                        (compose list webhook-shepherd-service))))
-   (compose concatenate)
-   (extend (lambda (config hook-extensions)
-             (webhook-configuration
-              (inherit config)
-              (hooks (append (webhook-configuration-hooks config)
-                             hook-extensions)))))
-   (default-value (webhook-configuration))))