services: bitlbee: Use 'make-inetd-constructor'.
[jackhill/guix/guix.git] / gnu / services / cuirass.scm
1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2016 Mathieu Lirzin <mthl@gnu.org>
3 ;;; Copyright © 2016, 2017, 2018, 2019, 2020, 2021 Ludovic Courtès <ludo@gnu.org>
4 ;;; Copyright © 2017, 2020 Mathieu Othacehe <m.othacehe@gmail.com>
5 ;;; Copyright © 2017 Jan Nieuwenhuizen <janneke@gnu.org>
6 ;;; Copyright © 2018, 2019 Ricardo Wurmus <rekado@elephly.net>
7 ;;; Copyright © 2018 Clément Lassieur <clement@lassieur.org>
8 ;;;
9 ;;; This file is part of GNU Guix.
10 ;;;
11 ;;; GNU Guix is free software; you can redistribute it and/or modify
12 ;;; it under the terms of the GNU General Public License as published by
13 ;;; the Free Software Foundation, either version 3 of the License, or
14 ;;; (at your option) any later version.
15 ;;;
16 ;;; GNU Guix is distributed in the hope that it will be useful,
17 ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;;; GNU General Public License for more details.
20 ;;;
21 ;;; You should have received a copy of the GNU General Public License
22 ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
23
24 (define-module (gnu services cuirass)
25 #:use-module (guix channels)
26 #:use-module (guix gexp)
27 #:use-module (guix records)
28 #:use-module (guix store)
29 #:use-module (guix utils)
30 #:use-module (gnu packages admin)
31 #:use-module (gnu packages ci)
32 #:use-module (gnu packages databases)
33 #:use-module (gnu packages version-control)
34 #:use-module (gnu services)
35 #:use-module (gnu services base)
36 #:use-module (gnu services databases)
37 #:use-module (gnu services shepherd)
38 #:use-module (gnu services admin)
39 #:use-module (gnu system shadow)
40 #:use-module (srfi srfi-1)
41 #:use-module (ice-9 match)
42 #:export (cuirass-remote-server-configuration
43 cuirass-remote-server-configuration?
44
45 cuirass-configuration
46 cuirass-configuration?
47 cuirass-service-type
48
49 cuirass-remote-worker-configuration
50 cuirass-remote-worker-configuration?
51 cuirass-remote-worker-service-type))
52
53 ;;;; Commentary:
54 ;;;
55 ;;; This module implements a service that to run instances of Cuirass, a
56 ;;; continuous integration tool.
57 ;;;
58 ;;;; Code:
59
60 (define %cuirass-default-database
61 "dbname=cuirass")
62
63 (define-record-type* <cuirass-remote-server-configuration>
64 cuirass-remote-server-configuration make-cuirass-remote-server-configuration
65 cuirass-remote-server-configuration?
66 (backend-port cuirass-remote-server-configuration-backend-port ;int
67 (default 5555))
68 (log-port cuirass-remote-server-configuration-log-port ;int
69 (default 5556))
70 (publish-port cuirass-remote-server-configuration-publish-port ;int
71 (default 5557))
72 (log-file cuirass-remote-server-log-file ;string
73 (default "/var/log/cuirass-remote-server.log"))
74 (cache cuirass-remote-server-configuration-cache ;string
75 (default "/var/cache/cuirass/remote/"))
76 (publish? cuirass-remote-server-configuration-publish? ;boolean
77 (default #t))
78 (trigger-url cuirass-remote-server-trigger-url ;string
79 (default #f))
80 (public-key cuirass-remote-server-configuration-public-key ;string
81 (default #f))
82 (private-key cuirass-remote-server-configuration-private-key ;string
83 (default #f)))
84
85 (define-record-type* <cuirass-configuration>
86 cuirass-configuration make-cuirass-configuration
87 cuirass-configuration?
88 (cuirass cuirass-configuration-cuirass ;file-like
89 (default cuirass))
90 (log-file cuirass-configuration-log-file ;string
91 (default "/var/log/cuirass.log"))
92 (web-log-file cuirass-configuration-web-log-file ;string
93 (default "/var/log/cuirass-web.log"))
94 (cache-directory cuirass-configuration-cache-directory ;string (dir-name)
95 (default "/var/cache/cuirass"))
96 (user cuirass-configuration-user ;string
97 (default "cuirass"))
98 (group cuirass-configuration-group ;string
99 (default "cuirass"))
100 (interval cuirass-configuration-interval ;integer (seconds)
101 (default 60))
102 (parameters cuirass-configuration-parameters ;string
103 (default #f))
104 (remote-server cuirass-configuration-remote-server
105 (default #f))
106 (database cuirass-configuration-database ;string
107 (default %cuirass-default-database))
108 (port cuirass-configuration-port ;integer (port)
109 (default 8081))
110 (host cuirass-configuration-host ;string
111 (default "localhost"))
112 (specifications cuirass-configuration-specifications)
113 ;gexp that evaluates to specification-alist
114 (use-substitutes? cuirass-configuration-use-substitutes? ;boolean
115 (default #f))
116 (one-shot? cuirass-configuration-one-shot? ;boolean
117 (default #f))
118 (fallback? cuirass-configuration-fallback? ;boolean
119 (default #f))
120 (extra-options cuirass-configuration-extra-options
121 (default '())))
122
123 (define (cuirass-shepherd-service config)
124 "Return a <shepherd-service> for the Cuirass service with CONFIG."
125 (let ((cuirass (cuirass-configuration-cuirass config))
126 (cache-directory (cuirass-configuration-cache-directory config))
127 (web-log-file (cuirass-configuration-web-log-file config))
128 (log-file (cuirass-configuration-log-file config))
129 (user (cuirass-configuration-user config))
130 (group (cuirass-configuration-group config))
131 (interval (cuirass-configuration-interval config))
132 (parameters (cuirass-configuration-parameters config))
133 (remote-server (cuirass-configuration-remote-server config))
134 (database (cuirass-configuration-database config))
135 (port (cuirass-configuration-port config))
136 (host (cuirass-configuration-host config))
137 (specs (cuirass-configuration-specifications config))
138 (use-substitutes? (cuirass-configuration-use-substitutes? config))
139 (one-shot? (cuirass-configuration-one-shot? config))
140 (fallback? (cuirass-configuration-fallback? config))
141 (extra-options (cuirass-configuration-extra-options config)))
142 `(,(shepherd-service
143 (documentation "Run Cuirass.")
144 (provision '(cuirass))
145 (requirement '(guix-daemon postgres postgres-roles networking))
146 (start #~(make-forkexec-constructor
147 (list (string-append #$cuirass "/bin/cuirass")
148 "register"
149 "--cache-directory" #$cache-directory
150 "--specifications"
151 #$(scheme-file "cuirass-specs.scm" specs)
152 "--database" #$database
153 "--interval" #$(number->string interval)
154 #$@(if parameters
155 (list (string-append
156 "--parameters="
157 parameters))
158 '())
159 #$@(if remote-server '("--build-remote") '())
160 #$@(if use-substitutes? '("--use-substitutes") '())
161 #$@(if one-shot? '("--one-shot") '())
162 #$@(if fallback? '("--fallback") '())
163 #$@extra-options)
164
165 #:environment-variables
166 (list "GIT_SSL_CAINFO=/etc/ssl/certs/ca-certificates.crt"
167 (string-append "GIT_EXEC_PATH=" #$git
168 "/libexec/git-core"))
169
170 #:user #$user
171 #:group #$group
172 #:log-file #$log-file))
173 (stop #~(make-kill-destructor)))
174 ,(shepherd-service
175 (documentation "Run Cuirass web interface.")
176 (provision '(cuirass-web))
177 (requirement '(cuirass))
178 (start #~(make-forkexec-constructor
179 (list (string-append #$cuirass "/bin/cuirass")
180 "web"
181 "--database" #$database
182 "--listen" #$host
183 "--port" #$(number->string port)
184 #$@(if parameters
185 (list (string-append
186 "--parameters="
187 parameters))
188 '())
189 #$@extra-options)
190
191 #:user #$user
192 #:group #$group
193 #:log-file #$web-log-file))
194 (stop #~(make-kill-destructor)))
195 ,@(if remote-server
196 (match-record remote-server <cuirass-remote-server-configuration>
197 (backend-port publish-port log-file cache publish?
198 trigger-url public-key private-key)
199 (list
200 (shepherd-service
201 (documentation "Run Cuirass remote build server.")
202 (provision '(cuirass-remote-server))
203 (requirement '(avahi-daemon cuirass))
204 (start #~(make-forkexec-constructor
205 (list (string-append #$cuirass "/bin/cuirass")
206 "remote-server"
207 (string-append "--database=" #$database)
208 (string-append "--cache=" #$cache)
209 (string-append "--user=" #$user)
210 #$@(if backend-port
211 (list (string-append
212 "--backend-port="
213 (number->string backend-port)))
214 '())
215 #$@(if publish-port
216 (list (string-append
217 "--publish-port="
218 (number->string publish-port)))
219 '())
220 #$@(if parameters
221 (list (string-append
222 "--parameters="
223 parameters))
224 '())
225 #$@(if trigger-url
226 (list
227 (string-append
228 "--trigger-substitute-url="
229 trigger-url))
230 '())
231 #$@(if publish?
232 '()
233 (list "--no-publish"))
234 #$@(if public-key
235 (list
236 (string-append "--public-key="
237 public-key))
238 '())
239 #$@(if private-key
240 (list
241 (string-append "--private-key="
242 private-key))
243 '()))
244 #:log-file #$log-file))
245 (stop #~(make-kill-destructor)))))
246 '()))))
247
248 (define (cuirass-account config)
249 "Return the user accounts and user groups for CONFIG."
250 (let ((cuirass-user (cuirass-configuration-user config))
251 (cuirass-group (cuirass-configuration-group config)))
252 (list (user-group
253 (name cuirass-group)
254 (system? #t))
255 (user-account
256 (name cuirass-user)
257 (group cuirass-group)
258 (system? #t)
259 (comment "Cuirass privilege separation user")
260 (home-directory (string-append "/var/lib/" cuirass-user))
261 (shell (file-append shadow "/sbin/nologin"))))))
262
263 (define (cuirass-postgresql-role config)
264 (let ((user (cuirass-configuration-user config)))
265 (list (postgresql-role
266 (name user)
267 (create-database? #t)))))
268
269 (define (cuirass-activation config)
270 "Return the activation code for CONFIG."
271 (let* ((cache (cuirass-configuration-cache-directory config))
272 (remote-server (cuirass-configuration-remote-server config))
273 (remote-cache (and remote-server
274 (cuirass-remote-server-configuration-cache
275 remote-server)))
276 (user (cuirass-configuration-user config))
277 (log "/var/log/cuirass")
278 (profile (string-append "/var/guix/profiles/per-user/" user))
279 (roots (string-append profile "/cuirass"))
280 (group (cuirass-configuration-group config)))
281 (with-imported-modules '((guix build utils))
282 #~(begin
283 (use-modules (guix build utils))
284
285 (mkdir-p #$cache)
286 (mkdir-p #$log)
287 (mkdir-p #$roots)
288
289 (when #$remote-cache
290 (mkdir-p #$remote-cache))
291
292 (let ((uid (passwd:uid (getpw #$user)))
293 (gid (group:gid (getgr #$group))))
294 (chown #$cache uid gid)
295 (chown #$log uid gid)
296 (chown #$roots uid gid)
297 (chown #$profile uid gid)
298
299 (when #$remote-cache
300 (chown #$remote-cache uid gid)))))))
301
302 (define (cuirass-log-rotations config)
303 "Return the list of log rotations that corresponds to CONFIG."
304 (list (log-rotation
305 (files (list (cuirass-configuration-log-file config)
306 (cuirass-configuration-web-log-file config)))
307 (frequency 'weekly)
308 (options '("rotate 40"))))) ;worth keeping
309
310 (define cuirass-service-type
311 (service-type
312 (name 'cuirass)
313 (extensions
314 (list
315 (service-extension profile-service-type ;for 'info cuirass'
316 (compose list cuirass-configuration-cuirass))
317 (service-extension rottlog-service-type cuirass-log-rotations)
318 (service-extension activation-service-type cuirass-activation)
319 (service-extension shepherd-root-service-type cuirass-shepherd-service)
320 (service-extension account-service-type cuirass-account)
321 ;; Make sure postgresql and postgresql-role are instantiated.
322 (service-extension postgresql-service-type (const #t))
323 (service-extension postgresql-role-service-type
324 cuirass-postgresql-role)))
325 (description
326 "Run the Cuirass continuous integration service.")))
327
328 (define-record-type* <cuirass-remote-worker-configuration>
329 cuirass-remote-worker-configuration make-cuirass-remote-worker-configuration
330 cuirass-remote-worker-configuration?
331 (cuirass cuirass-remote-worker-configuration-cuirass ;file-like
332 (default cuirass))
333 (workers cuirass-remote-worker-workers ;int
334 (default 1))
335 (server cuirass-remote-worker-server ;string
336 (default #f))
337 (systems cuirass-remote-worker-systems ;list
338 (default (list (%current-system))))
339 (log-file cuirass-remote-worker-log-file ;string
340 (default "/var/log/cuirass-remote-worker.log"))
341 (publish-port cuirass-remote-worker-configuration-publish-port ;int
342 (default 5558))
343 (substitute-urls cuirass-remote-worker-configuration-substitute-urls
344 (default %default-substitute-urls)) ;list of strings
345 (public-key cuirass-remote-worker-configuration-public-key ;string
346 (default #f))
347 (private-key cuirass-remote-worker-configuration-private-key ;string
348 (default #f)))
349
350 (define (cuirass-remote-worker-shepherd-service config)
351 "Return a <shepherd-service> for the Cuirass remote worker service with
352 CONFIG."
353 (match-record config <cuirass-remote-worker-configuration>
354 (cuirass workers server systems log-file publish-port
355 substitute-urls public-key private-key)
356 (list (shepherd-service
357 (documentation "Run Cuirass remote build worker.")
358 (provision '(cuirass-remote-worker))
359 (requirement '(avahi-daemon guix-daemon networking))
360 (start #~(make-forkexec-constructor
361 (list (string-append #$cuirass "/bin/cuirass")
362 "remote-worker"
363 (string-append "--workers="
364 #$(number->string workers))
365 #$@(if server
366 (list (string-append "--server=" server))
367 '())
368 #$@(if systems
369 (list (string-append
370 "--systems="
371 (string-join systems ",")))
372 '())
373 #$@(if publish-port
374 (list (string-append
375 "--publish-port="
376 (number->string publish-port)))
377 '())
378 #$@(if substitute-urls
379 (list (string-append
380 "--substitute-urls="
381 (string-join substitute-urls)))
382 '())
383 #$@(if public-key
384 (list
385 (string-append "--public-key="
386 public-key))
387 '())
388 #$@(if private-key
389 (list
390 (string-append "--private-key="
391 private-key))
392 '()))
393 #:log-file #$log-file))
394 (stop #~(make-kill-destructor))))))
395
396 (define cuirass-remote-worker-service-type
397 (service-type
398 (name 'cuirass-remote-worker)
399 (extensions
400 (list
401 (service-extension shepherd-root-service-type
402 cuirass-remote-worker-shepherd-service)))
403 (description
404 "Run the Cuirass remote build worker service.")))