summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--forge/webhook.scm192
1 files changed, 192 insertions, 0 deletions
diff --git a/forge/webhook.scm b/forge/webhook.scm
new file mode 100644
index 0000000..e61494b
--- /dev/null
+++ b/forge/webhook.scm
@@ -0,0 +1,192 @@
+;;; 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)))))))