mirror of
https://codeberg.org/guix/guix.git
synced 2025-10-02 02:15:12 +00:00
services: ci: Add Forgejo Runner service.
* gnu/services/ci.scm (<forgejo-runner-configuration>): New record type. (create-forgejo-runner-account, forgejo-runner-activation) (write-yaml, yaml-file, forgejo-runner-shepherd-service): New procedures. (forgejo-runner-service-type): New variable. * doc/guix.texi (Continuous Integration): Add “Forgejo Runner” heading. Co-authored-by: David Thompson <davet@gnu.org> Change-Id: Iba42d84da35812afa60e94773fbbadd68eca9813
This commit is contained in:
parent
821e517ea4
commit
6b42df3ad6
2 changed files with 301 additions and 1 deletions
107
doc/guix.texi
107
doc/guix.texi
|
@ -37870,6 +37870,113 @@ Base URL to use for links to laminar itself.
|
||||||
@end table
|
@end table
|
||||||
@end deftp
|
@end deftp
|
||||||
|
|
||||||
|
@subsubheading Forgejo Runner
|
||||||
|
|
||||||
|
@cindex continuous integration, Forgejo
|
||||||
|
@cindex Forgejo, continuous integration
|
||||||
|
The @code{(gnu services ci)} also provides a service for
|
||||||
|
@uref{https://code.forgejo.org/forgejo/runner, Forgejo Runner}, a daemon
|
||||||
|
that connects to an instance of the @uref{https://forgejo.org, Forgejo
|
||||||
|
code collaboration tool} and runs jobs for continuous integration.
|
||||||
|
|
||||||
|
A minimal configuration mostly with default values that can be added to
|
||||||
|
the @code{services} field of your operating system looks like this:
|
||||||
|
|
||||||
|
@lisp
|
||||||
|
(service forgejo-runner-service-type
|
||||||
|
(forgejo-runner-configuration
|
||||||
|
(name "my-runner")
|
||||||
|
(labels '("guix" "linux"))))
|
||||||
|
@end lisp
|
||||||
|
|
||||||
|
This provides a @code{forgejo-runner} Shepherd service. That service
|
||||||
|
will initially fail to start; you will have to manually @dfn{register}
|
||||||
|
the runner against the Forgejo server by running a command like:
|
||||||
|
|
||||||
|
@example
|
||||||
|
herd register forgejo-runner @var{url} @var{token}
|
||||||
|
@end example
|
||||||
|
|
||||||
|
@noindent
|
||||||
|
... where the arguments are as follows:
|
||||||
|
|
||||||
|
@table @var
|
||||||
|
@item url
|
||||||
|
the URL of the Forgejo server---e.g.,
|
||||||
|
@indicateurl{https://codeberg.org};
|
||||||
|
@item token
|
||||||
|
an access token
|
||||||
|
@uref{https://forgejo.org/docs/latest/admin/runner-installation/#standard-registration,
|
||||||
|
provided by the Forgejo server}.
|
||||||
|
@end table
|
||||||
|
|
||||||
|
Once registration has succeeded, you can start the runner:
|
||||||
|
|
||||||
|
@example
|
||||||
|
herd enable forgejo-runner
|
||||||
|
herd start forgejo-runner
|
||||||
|
@end example
|
||||||
|
|
||||||
|
The runner then receives orders from the Forgejo server to execute
|
||||||
|
@dfn{actions}. Actions are commands and workflows specified by YAML
|
||||||
|
files in the @file{.forgejo/workflows} directory of source code
|
||||||
|
repositories---see @uref{https://forgejo.org/docs/v7.0/user/actions/,
|
||||||
|
the Forgejo Action documentation} for more info.
|
||||||
|
|
||||||
|
Note that at the moment @code{forgejo-runner-service-type} lets you run
|
||||||
|
only one runner. Details about the configuration of this service
|
||||||
|
follow.
|
||||||
|
|
||||||
|
@defvar forgejo-runner-service-type
|
||||||
|
This is the service type for Forgejo Runner. Its value must be a
|
||||||
|
@code{forgejo-runner-configuration} record, documented below.
|
||||||
|
@end defvar
|
||||||
|
|
||||||
|
@deftp {Data Type} forgejo-runner-configuration
|
||||||
|
This data type represents the configuration of an instance of
|
||||||
|
@code{forgejo-runner-service-type}. It contains the following fields:
|
||||||
|
|
||||||
|
@table @asis
|
||||||
|
@item @code{package} (default: @code{forgejo-runner})
|
||||||
|
The Forgejo Runner package to use.
|
||||||
|
|
||||||
|
@item @code{name} (default: @code{#~(gethostname)})
|
||||||
|
Name of the runner as will be shown in the runner management interface
|
||||||
|
of Forgejo.
|
||||||
|
|
||||||
|
@item @code{labels} (default: @code{'("guix")})
|
||||||
|
List of
|
||||||
|
@uref{https://forgejo.org/docs/latest/admin/actions/#choosing-labels,
|
||||||
|
labels} representing the type of environment the runner provides and
|
||||||
|
that actions may refer to.
|
||||||
|
|
||||||
|
@item @code{capacity} (default: @code{1})
|
||||||
|
Number of tasks to be executed concurrently.
|
||||||
|
|
||||||
|
@item @code{timeout} (default: @code{(* 3 3600)})
|
||||||
|
Maximum duration of a job, in seconds.
|
||||||
|
|
||||||
|
@item @code{fetch-timeout} (default: @code{5})
|
||||||
|
Maximum duration for fetching the job from the Forgejo server, in
|
||||||
|
seconds.
|
||||||
|
|
||||||
|
@item @code{fetch-interval} (default: @code{2})
|
||||||
|
Interval (in seconds) for fetching the job from the Forgejo server.
|
||||||
|
|
||||||
|
@item @code{report-interval} (default: @code{1})
|
||||||
|
Interval (in seconds) for reporting the job status and log to the
|
||||||
|
Forgejo server.
|
||||||
|
|
||||||
|
@item @code{data-directory} (default: @code{"/var/lib/forgejo-runner"})
|
||||||
|
Directory where @command{forgejo-runner} will store persistent data such
|
||||||
|
as its configuration and access token.
|
||||||
|
|
||||||
|
@item @code{run-directory} (default: @code{"/var/run/forgejo-runner"})
|
||||||
|
Directory where @command{forgejo-runner} stores cached data.
|
||||||
|
|
||||||
|
@end table
|
||||||
|
@end deftp
|
||||||
|
|
||||||
@node Power Management Services
|
@node Power Management Services
|
||||||
@subsection Power Management Services
|
@subsection Power Management Services
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
;;; GNU Guix --- Functional package management for GNU
|
;;; GNU Guix --- Functional package management for GNU
|
||||||
;;; Copyright © 2018, 2019, 2020, 2021 Christopher Baines <mail@cbaines.net>
|
;;; Copyright © 2018, 2019, 2020, 2021 Christopher Baines <mail@cbaines.net>
|
||||||
;;; Copyright © 2021, 2022 Arun Isaac <arunisaac@systemreboot.net>
|
;;; Copyright © 2021, 2022 Arun Isaac <arunisaac@systemreboot.net>
|
||||||
|
;;; Copyright © 2025 David Thompson <davet@gnu.org>
|
||||||
|
;;; Copyright © 2025 Ludovic Courtès <ludo@gnu.org>
|
||||||
;;;
|
;;;
|
||||||
;;; This file is part of GNU Guix.
|
;;; This file is part of GNU Guix.
|
||||||
;;;
|
;;;
|
||||||
|
@ -20,6 +22,7 @@
|
||||||
(define-module (gnu services ci)
|
(define-module (gnu services ci)
|
||||||
#:use-module (guix gexp)
|
#:use-module (guix gexp)
|
||||||
#:use-module (guix records)
|
#:use-module (guix records)
|
||||||
|
#:autoload (guix modules) (source-module-closure)
|
||||||
#:use-module (gnu packages admin)
|
#:use-module (gnu packages admin)
|
||||||
#:use-module (gnu packages ci)
|
#:use-module (gnu packages ci)
|
||||||
#:use-module (gnu services)
|
#:use-module (gnu services)
|
||||||
|
@ -39,7 +42,22 @@
|
||||||
laminar-configuration-archive-url
|
laminar-configuration-archive-url
|
||||||
laminar-configuration-base-url
|
laminar-configuration-base-url
|
||||||
|
|
||||||
laminar-service-type))
|
laminar-service-type
|
||||||
|
|
||||||
|
forgejo-runner-configuration
|
||||||
|
forgejo-runner-configuration?
|
||||||
|
forgejo-runner-configuration-package
|
||||||
|
forgejo-runner-configuration-data-directory
|
||||||
|
forgejo-runner-configuration-run-directory
|
||||||
|
forgejo-runner-configuration-name
|
||||||
|
forgejo-runner-configuration-labels
|
||||||
|
forgejo-runner-configuration-capacity
|
||||||
|
forgejo-runner-configuration-timeout
|
||||||
|
forgejo-runner-configuration-fetch-timeout
|
||||||
|
forgejo-runner-configuration-fetch-interval
|
||||||
|
forgejo-runner-configuration-report-interval
|
||||||
|
|
||||||
|
forgejo-runner-service-type))
|
||||||
|
|
||||||
;;;; Commentary:
|
;;;; Commentary:
|
||||||
;;;
|
;;;
|
||||||
|
@ -146,3 +164,178 @@
|
||||||
(default-value (laminar-configuration))
|
(default-value (laminar-configuration))
|
||||||
(description
|
(description
|
||||||
"Run the Laminar continuous integration service.")))
|
"Run the Laminar continuous integration service.")))
|
||||||
|
|
||||||
|
|
||||||
|
;;;
|
||||||
|
;;; Forgejo runner.
|
||||||
|
;;;
|
||||||
|
|
||||||
|
(define-record-type* <forgejo-runner-configuration>
|
||||||
|
forgejo-runner-configuration
|
||||||
|
make-forgejo-runner-configuration
|
||||||
|
forgejo-runner-configuration?
|
||||||
|
(package forgejo-runner-configuration-package
|
||||||
|
(default forgejo-runner))
|
||||||
|
(data-directory forgejo-runner-configuration-data-directory
|
||||||
|
(default "/var/lib/forgejo-runner"))
|
||||||
|
(run-directory forgejo-runner-configuration-run-directory
|
||||||
|
(default "/var/run/forgejo-runner"))
|
||||||
|
|
||||||
|
;; Configuration options for the YAML config file:
|
||||||
|
;; <https://forgejo.org/docs/latest/admin/runner-installation/#configuration>.
|
||||||
|
(name forgejo-runner-configuration-name
|
||||||
|
(default #~(gethostname)))
|
||||||
|
(labels forgejo-runner-configuration-labels
|
||||||
|
(default '("guix")))
|
||||||
|
(capacity forgejo-runner-configuration-job-capacity
|
||||||
|
(default 1))
|
||||||
|
(timeout forgejo-runner-configuration-timeout
|
||||||
|
(default (* 3 3600)))
|
||||||
|
(fetch-timeout forgejo-runner-configuration-fetch-timeout
|
||||||
|
(default 5))
|
||||||
|
(fetch-interval forgejo-runner-configuration-fetch-interval
|
||||||
|
(default 2))
|
||||||
|
(report-interval forgejo-runner-configuration-report-interval
|
||||||
|
(default 1)))
|
||||||
|
|
||||||
|
(define (create-forgejo-runner-account config)
|
||||||
|
(list (user-account
|
||||||
|
(name "forgejo-runner")
|
||||||
|
(group "forgejo-runner")
|
||||||
|
(system? #t)
|
||||||
|
(comment "Forgejo Runner user")
|
||||||
|
(home-directory
|
||||||
|
(forgejo-runner-configuration-data-directory config)))
|
||||||
|
(user-group
|
||||||
|
(name "forgejo-runner")
|
||||||
|
(system? #t))))
|
||||||
|
|
||||||
|
(define (forgejo-runner-activation config)
|
||||||
|
(match-record config <forgejo-runner-configuration>
|
||||||
|
(data-directory run-directory)
|
||||||
|
#~(let* ((user (getpwnam "forgejo-runner")))
|
||||||
|
(mkdir-p #$run-directory)
|
||||||
|
(chown #$run-directory (passwd:uid user) (passwd:gid user)))))
|
||||||
|
|
||||||
|
;; Very naive YAML writer that does just enough for our needs.
|
||||||
|
(define* (write-yaml port exp depth)
|
||||||
|
(match exp
|
||||||
|
((? string? str)
|
||||||
|
(write str port))
|
||||||
|
((? number? n)
|
||||||
|
(display n port))
|
||||||
|
(('seconds (? number? n))
|
||||||
|
(format port "~as" n))
|
||||||
|
(#(values ...)
|
||||||
|
(display "[ " port)
|
||||||
|
(let ((strings
|
||||||
|
(map (lambda (value)
|
||||||
|
(call-with-output-string
|
||||||
|
(lambda (port)
|
||||||
|
(write-yaml port value depth))))
|
||||||
|
values)))
|
||||||
|
(display (string-join strings ", ") port))
|
||||||
|
(display " ]" port))
|
||||||
|
(() (values))
|
||||||
|
((((? symbol? k) . v) . rest)
|
||||||
|
(do ((i 0 (1+ i)))
|
||||||
|
((= i depth))
|
||||||
|
(display " " port))
|
||||||
|
(display k port)
|
||||||
|
(display ": " port)
|
||||||
|
(match v
|
||||||
|
(((k* . v*) . _) ; subtree
|
||||||
|
(newline port)
|
||||||
|
(write-yaml port v (1+ depth)))
|
||||||
|
(_ (write-yaml port v depth)))
|
||||||
|
(newline port)
|
||||||
|
(write-yaml port rest depth))))
|
||||||
|
|
||||||
|
(define (yaml-file name exp)
|
||||||
|
(plain-file name
|
||||||
|
(call-with-output-string
|
||||||
|
(lambda (port)
|
||||||
|
(write-yaml port exp 0)))))
|
||||||
|
|
||||||
|
(define (forgejo-runner-shepherd-service config)
|
||||||
|
(match-record config <forgejo-runner-configuration>
|
||||||
|
(package data-directory run-directory name
|
||||||
|
capacity timeout fetch-timeout fetch-interval report-interval
|
||||||
|
labels)
|
||||||
|
(define runner (file-append package "/bin/forgejo-runner"))
|
||||||
|
(define runner-file (string-append data-directory "/runner"))
|
||||||
|
(define config
|
||||||
|
(yaml-file
|
||||||
|
"forgejo-runner-config.yml"
|
||||||
|
`((runner . ((file . ,runner-file)
|
||||||
|
(capacity . ,capacity)
|
||||||
|
(timeout . (seconds ,timeout))
|
||||||
|
(fetch_timeout . (seconds ,fetch-timeout))
|
||||||
|
(fetch_interval . (seconds ,fetch-interval))
|
||||||
|
(report_interval . (seconds ,report-interval))
|
||||||
|
(labels . ,(list->vector labels))))
|
||||||
|
(cache . ((dir . ,(string-append run-directory "/cache"))))
|
||||||
|
(host . ((workdir_parent
|
||||||
|
. ,(string-append run-directory "/act")))))))
|
||||||
|
|
||||||
|
(list (shepherd-service
|
||||||
|
(provision '(forgejo-runner))
|
||||||
|
(requirement '(user-processes networking))
|
||||||
|
(start #~(make-forkexec-constructor
|
||||||
|
(list #$runner "daemon" "--config" #$config)
|
||||||
|
#:user "forgejo-runner"
|
||||||
|
#:group "forgejo-runner"
|
||||||
|
#:directory #$run-directory
|
||||||
|
#:environment-variables
|
||||||
|
;; Provide access to a fresh Guix obtained via 'guix
|
||||||
|
;; pull'.
|
||||||
|
(cons* (string-append "PATH="
|
||||||
|
#$data-directory "/.config/guix/current/bin"
|
||||||
|
":/run/current-system/profile/bin")
|
||||||
|
(string-append "HOME=" #$data-directory)
|
||||||
|
"GIT_SSL_CAINFO=/etc/ssl/certs/ca-certificates.crt"
|
||||||
|
(default-environment-variables))))
|
||||||
|
(stop #~(make-kill-destructor))
|
||||||
|
(actions
|
||||||
|
(list
|
||||||
|
(shepherd-configuration-action config)
|
||||||
|
(shepherd-action
|
||||||
|
(procedure
|
||||||
|
#~(lambda (running instance token)
|
||||||
|
(define status
|
||||||
|
(spawn-command (list #$runner "register"
|
||||||
|
"--no-interactive"
|
||||||
|
"--config" #$config
|
||||||
|
"--name" #$name
|
||||||
|
"--instance" instance
|
||||||
|
"--token" token)
|
||||||
|
#:user "forgejo-runner"
|
||||||
|
#:group "forgejo-runner"))
|
||||||
|
|
||||||
|
(if (zero? status)
|
||||||
|
(format #t "Successfully registered runner \
|
||||||
|
'~a' for '~a'.~%"
|
||||||
|
#$name instance)
|
||||||
|
(format #t "'~a register' failed with status ~a.~%"
|
||||||
|
#$runner status))
|
||||||
|
(zero? status)))
|
||||||
|
(name 'register)
|
||||||
|
(documentation "Register this runner with a Forgejo server.
|
||||||
|
This action takes two arguments: the Forgejo server URL and an access
|
||||||
|
token."))))
|
||||||
|
(documentation "Forgejo task runner")))))
|
||||||
|
|
||||||
|
(define forgejo-runner-service-type
|
||||||
|
(service-type
|
||||||
|
(name 'forgejo-runner)
|
||||||
|
(extensions
|
||||||
|
(list (service-extension activation-service-type
|
||||||
|
forgejo-runner-activation)
|
||||||
|
(service-extension account-service-type
|
||||||
|
create-forgejo-runner-account)
|
||||||
|
(service-extension shepherd-root-service-type
|
||||||
|
forgejo-runner-shepherd-service)))
|
||||||
|
(default-value (forgejo-runner-configuration))
|
||||||
|
(description
|
||||||
|
"Run @command{forgejo-runner}, a daemon to run tasks for the Forgejo
|
||||||
|
source code collaboration service.")))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue