diff options
Diffstat (limited to 'gnu')
| -rw-r--r-- | gnu/ci.scm | 448 | 
1 files changed, 203 insertions, 245 deletions
| diff --git a/gnu/ci.scm b/gnu/ci.scm index 96bff64875..6edcdd0e19 100644 --- a/gnu/ci.scm +++ b/gnu/ci.scm @@ -3,7 +3,7 @@  ;;; Copyright © 2017, 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>  ;;; Copyright © 2018, 2019 Clément Lassieur <clement@lassieur.org>  ;;; Copyright © 2020 Julien Lepiller <julien@lepiller.eu> -;;; Copyright © 2020 Mathieu Othacehe <othacehe@gnu.org> +;;; Copyright © 2020, 2021 Mathieu Othacehe <othacehe@gnu.org>  ;;;  ;;; This file is part of GNU Guix.  ;;; @@ -21,6 +21,7 @@  ;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.  (define-module (gnu ci) +  #:use-module (guix channels)    #:use-module (guix config)    #:use-module (guix store)    #:use-module (guix grafts) @@ -64,67 +65,69 @@    #:use-module (srfi srfi-1)    #:use-module (srfi srfi-26)    #:use-module (ice-9 match) -  #:export (%cross-targets +  #:export (%core-packages +            %cross-targets              channel-source->package -            hydra-jobs)) +            cuirass-jobs))  ;;; Commentary:  ;;; -;;; This file defines build jobs for the Hydra and Cuirass continuation -;;; integration tools. +;;; This file defines build jobs for Cuirass.  ;;;  ;;; Code: -(define* (package->alist store package system -                         #:optional (package-derivation package-derivation)) -  "Convert PACKAGE to an alist suitable for Hydra." -  (parameterize ((%graft? #f)) -    (let ((drv (package-derivation store package system -                                   #:graft? #f))) -      `((derivation . ,(derivation-file-name drv)) -        (log . ,(log-file store (derivation-file-name drv))) -        (outputs . ,(filter-map (lambda (res) -                                  (match res -                                    ((name . path) -                                     `(,name . ,path)))) -                                (derivation->output-paths drv))) -        (nix-name . ,(derivation-name drv)) -        (system . ,(derivation-system drv)) -        (description . ,(package-synopsis package)) -        (long-description . ,(package-description package)) - -        ;; XXX: Hydra ignores licenses that are not a <license> structure or a -        ;; list thereof. -        (license . ,(let loop ((license (package-license package))) -                      (match license -                        ((? license?) -                         (license-name license)) -                        ((lst ...) -                         (map loop license))))) +(define* (derivation->job name drv +                          #:key +                          period +                          (max-silent-time 3600) +                          (timeout 3600)) +  "Return a Cuirass job called NAME and describing DRV.  PERIOD is the minimal +duration that must separate two evaluations of the same job. If PERIOD is +false, then the job will be evaluated as soon as possible. -        (home-page . ,(package-home-page package)) -        (maintainers . ("bug-guix@gnu.org")) -        (max-silent-time . ,(or (assoc-ref (package-properties package) -                                           'max-silent-time) -                                3600))              ;1 hour by default -        (timeout . ,(or (assoc-ref (package-properties package) 'timeout) -                        72000))))))                  ;20 hours by default +MAX-SILENT-TIME and TIMEOUT are build options passed to the daemon when +building the derivation." +  `((#:job-name . ,name) +    (#:derivation . ,(derivation-file-name drv)) +    (#:outputs . ,(filter-map +                   (lambda (res) +                     (match res +                       ((name . path) +                        `(,name . ,path)))) +                   (derivation->output-paths drv))) +    (#:nix-name . ,(derivation-name drv)) +    (#:system . ,(derivation-system drv)) +    (#:period . ,period) +    (#:max-silent-time . ,max-silent-time) +    (#:timeout . ,timeout))) -(define (package-job store job-name package system) +(define* (package-job store job-name package system +                      #:key cross? target)    "Return a job called JOB-NAME that builds PACKAGE on SYSTEM." -  (let ((job-name (symbol-append job-name (string->symbol ".") -                                 (string->symbol system)))) -    `(,job-name . ,(cut package->alist store package system)))) +  (let ((job-name (string-append job-name "." system))) +    (parameterize ((%graft? #f)) +      (let* ((drv (if cross? +                      (package-cross-derivation store package target system +                                                #:graft? #f) +                      (package-derivation store package system +                                          #:graft? #f))) +             (max-silent-time (or (assoc-ref (package-properties package) +                                             'max-silent-time) +                                  3600)) +             (timeout (or (assoc-ref (package-properties package) +                                     'timeout) +                          72000))) +        (derivation->job job-name drv +                         #:max-silent-time max-silent-time +                         #:timeout timeout)))))  (define (package-cross-job store job-name package target system)    "Return a job called TARGET.JOB-NAME that cross-builds PACKAGE for TARGET on  SYSTEM." -  `(,(symbol-append (string->symbol target) (string->symbol ".") job-name -                    (string->symbol ".") (string->symbol system)) . -    ,(cute package->alist store package system -           (lambda* (store package system #:key graft?) -             (package-cross-derivation store package target system -                                       #:graft? graft?))))) +  (let ((name (string-append target "." job-name "." system))) +    (package-job store name package system +                 #:cross? #t +                 #:target target)))  (define %core-packages    ;; Note: Don't put the '-final' package variants because (1) that's @@ -200,6 +203,22 @@ SYSTEM."                (remove (either from-32-to-64? same? pointless?)                        %cross-targets))) +(define* (guix-jobs store systems #:key source commit) +  "Return a list of jobs for Guix itself." +  (define build +    (primitive-load (string-append source "/build-aux/build-self.scm"))) + +  (map +   (lambda (system) +     (let ((name (string->symbol +                  (string-append "guix." system))) +           (drv (run-with-store store +                  (build source #:version commit #:system system +                         #:pull-version 1 +                         #:guile-version "2.2")))) +       (derivation->job name drv))) +   systems)) +  ;; Architectures that are able to build or cross-build Guix System images.  ;; This does not mean that other architectures are not supported, only that  ;; they are often not fast enough to support Guix System images building. @@ -219,32 +238,11 @@ SYSTEM."    "Return a list of jobs that build images for SYSTEM.  Those jobs are  expensive in storage and I/O operations, hence their periodicity is limited by  passing the PERIOD argument." -  (define (->alist drv) -    `((derivation . ,(derivation-file-name drv)) -      (log . ,(log-file store (derivation-file-name drv))) -      (outputs . ,(filter-map (lambda (res) -                                (match res -                                  ((name . path) -                                   `(,name . ,path)))) -                              (derivation->output-paths drv))) -      (nix-name . ,(derivation-name drv)) -      (system . ,(derivation-system drv)) -      (description . "Stand-alone image of the GNU system") -      (long-description . "This is a demo stand-alone image of the GNU -system.") -      (license . ,(license-name gpl3+)) -      (period . ,(hours 48)) -      (max-silent-time . 3600) -      (timeout . 3600) -      (home-page . ,%guix-home-page-url) -      (maintainers . ("bug-guix@gnu.org")))) -    (define (->job name drv) -    (let ((name (symbol-append name (string->symbol ".") -                               (string->symbol system)))) -      `(,name . ,(lambda () -                   (parameterize ((%graft? #f)) -                     (->alist drv)))))) +    (let ((name (string-append name "." system))) +      (parameterize ((%graft? #f)) +        (derivation->job name drv +                         #:period (hours 48)))))    (define (build-image image)      (run-with-store store @@ -256,25 +254,26 @@ system.")      (expt 2 20))    (if (member system %guix-system-supported-systems) -      `(,(->job 'usb-image +      `(,(->job "usb-image"                  (build-image                   (image                    (inherit efi-disk-image)                    (operating-system installation-os)))) -        ,(->job 'iso9660-image +        ,(->job "iso9660-image"                  (build-image                   (image                    (inherit (image-with-label -                             iso9660-image -                             (string-append "GUIX_" system "_" -                                            (if (> (string-length %guix-version) 7) -                                                (substring %guix-version 0 7) -                                                %guix-version)))) +                            iso9660-image +                            (string-append "GUIX_" system "_" +                                           (if (> (string-length %guix-version) 7) +                                               (substring %guix-version 0 7) +                                               %guix-version))))                    (operating-system installation-os))))          ;; Only cross-compile Guix System images from x86_64-linux for now.          ,@(if (string=? system "x86_64-linux")                (map (lambda (image) -                     (->job (image-name image) (build-image image))) +                     (->job (symbol->string (image-name image)) +                            (build-image image)))                     %guix-system-images)                '()))        '())) @@ -322,112 +321,72 @@ system.")  (define* (system-test-jobs store system                             #:key source commit)    "Return a list of jobs for the system tests." -  (define (test->thunk test) -    (lambda () -      (define drv -        (run-with-store store -          (mbegin %store-monad -            (set-current-system system) -            (set-grafting #f) -            (set-guile-for-build (default-guile)) -            (system-test-value test)))) - -      ;; Those tests are extremely expensive in I/O operations and storage -      ;; size, use the "period" attribute to run them with a period of at -      ;; least 48 hours. -      `((derivation . ,(derivation-file-name drv)) -        (log . ,(log-file store (derivation-file-name drv))) -        (outputs . ,(filter-map (lambda (res) -                                  (match res -                                    ((name . path) -                                     `(,name . ,path)))) -                                (derivation->output-paths drv))) -        (nix-name . ,(derivation-name drv)) -        (system . ,(derivation-system drv)) -        (description . ,(format #f "Guix '~a' system test" -                                (system-test-name test))) -        (long-description . ,(system-test-description test)) -        (license . ,(license-name gpl3+)) -        (period . ,(hours 48)) -        (max-silent-time . 3600) -        (timeout . 3600) -        (home-page . ,%guix-home-page-url) -        (maintainers . ("bug-guix@gnu.org"))))) -    (define (->job test) -    (let ((name (string->symbol -                 (string-append "test." (system-test-name test) -                                "." system)))) -      (cons name (test->thunk test)))) +    (parameterize ((current-guix-package +                    (channel-source->package source #:commit commit))) +      (let ((name (string-append "test." (system-test-name test) +                                 "." system)) +            (drv (run-with-store store +                   (mbegin %store-monad +                     (set-current-system system) +                     (set-grafting #f) +                     (set-guile-for-build (default-guile)) +                     (system-test-value test))))) + +        ;; Those tests are extremely expensive in I/O operations and storage +        ;; size, use the "period" attribute to run them with a period of at +        ;; least 48 hours. +        (derivation->job name drv +                         #:period (hours 24)))))    (if (member system %guix-system-supported-systems)        ;; Override the value of 'current-guix' used by system tests.  Using a        ;; channel instance makes tests that rely on 'current-guix' less        ;; expensive.  It also makes sure we get a valid Guix package when this        ;; code is not running from a checkout. -      (parameterize ((current-guix-package -                      (channel-source->package source #:commit commit))) -        (map ->job (all-system-tests))) +      (map ->job (all-system-tests))        '()))  (define (tarball-jobs store system) -  "Return Hydra jobs to build the self-contained Guix binary tarball." -  (define (->alist drv) -    `((derivation . ,(derivation-file-name drv)) -      (log . ,(log-file store (derivation-file-name drv))) -      (outputs . ,(filter-map (lambda (res) -                                (match res -                                  ((name . path) -                                   `(,name . ,path)))) -                              (derivation->output-paths drv))) -      (nix-name . ,(derivation-name drv)) -      (system . ,(derivation-system drv)) -      (description . "Stand-alone binary Guix tarball") -      (long-description . "This is a tarball containing binaries of Guix and -all its dependencies, and ready to be installed on \"foreign\" distributions.") -      (license . ,(license-name gpl3+)) -      (home-page . ,%guix-home-page-url) -      (maintainers . ("bug-guix@gnu.org")) -      (period . ,(hours 24)))) - +  "Return jobs to build the self-contained Guix binary tarball."    (define (->job name drv) -    (let ((name (symbol-append name (string->symbol ".") -                               (string->symbol system)))) -      `(,name . ,(lambda () -                   (parameterize ((%graft? #f)) -                     (->alist drv)))))) +    (let ((name (string-append name "." system))) +      (parameterize ((%graft? #f)) +        (derivation->job name drv +                         #:period (hours 24)))))    ;; XXX: Add a job for the stable Guix? -  (list (->job 'binary-tarball -               (run-with-store store -                 (mbegin %store-monad -                   (set-guile-for-build (default-guile)) -                   (>>= (profile-derivation (packages->manifest (list guix))) -                        (lambda (profile) -                          (self-contained-tarball "guix-binary" profile -                                                  #:localstatedir? #t -                                                  #:compressor -                                                  (lookup-compressor "xz"))))) -                 #:system system)))) +  (list +   (->job "binary-tarball" +          (run-with-store store +            (mbegin %store-monad +              (set-guile-for-build (default-guile)) +              (>>= (profile-derivation (packages->manifest (list guix))) +                   (lambda (profile) +                     (self-contained-tarball "guix-binary" profile +                                             #:localstatedir? #t +                                             #:compressor +                                             (lookup-compressor "xz"))))) +            #:system system))))  (define job-name    ;; Return the name of a package's job. -  (compose string->symbol package-name)) +  package-name)  (define package->job    (let ((base-packages           (delete-duplicates            (append-map (match-lambda -                       ((_ package _ ...) -                        (match (package-transitive-inputs package) -                          (((_ inputs _ ...) ...) -                           inputs)))) +                        ((_ package _ ...) +                         (match (package-transitive-inputs package) +                           (((_ inputs _ ...) ...) +                            inputs))))                        (%final-inputs)))))      (lambda (store package system)        "Return a job for PACKAGE on SYSTEM, or #f if this combination is not  valid."        (cond ((member package base-packages) -             (package-job store (symbol-append 'base. (job-name package)) +             (package-job store (string-append "base." (job-name package))                            package system))              ((supported-package? package system)               (let ((drv (package-derivation store package system @@ -461,14 +420,19 @@ valid."                            packages)))                   #:select? (const #t)))           ;include hidden packages -(define (arguments->manifests arguments) +(define (arguments->manifests arguments channels)    "Return the list of manifests extracted from ARGUMENTS." +  (define (channel-name->checkout name) +    (let ((channel (find (lambda (channel) +                           (eq? (channel-name channel) name)) +                         channels))) +      (channel-url channel))) +    (map (match-lambda -         ((input-name . relative-path) -          (let* ((checkout (assq-ref arguments (string->symbol input-name))) -                 (base (assq-ref checkout 'file-name))) -            (in-vicinity base relative-path)))) -       (assq-ref arguments 'manifests))) +         ((name . path) +          (let ((checkout (channel-name->checkout name))) +            (in-vicinity checkout path)))) +       arguments))  (define (manifests->packages store manifests)    "Return the list of packages found in MANIFESTS." @@ -484,100 +448,94 @@ valid."                               load-manifest)                      manifests)))) -(define (find-current-checkout arguments) -  "Find the first checkout of ARGUMENTS that provided the current file. -Return #f if no such checkout is found." -  (let ((current-root -         (canonicalize-path -          (string-append (dirname (current-filename)) "/..")))) -    (find (lambda (argument) -            (and=> (assq-ref argument 'file-name) -                   (lambda (name) -                     (string=? name current-root)))) arguments))) -  ;;; -;;; Hydra entry point. +;;; Cuirass entry point.  ;;; -(define (hydra-jobs store arguments) -  "Return Hydra jobs." +(define (cuirass-jobs store arguments) +  "Register Cuirass jobs."    (define subset -    (match (assoc-ref arguments 'subset) -      ("core" 'core)                              ; only build core packages -      ("hello" 'hello)                            ; only build hello -      (((? string?) (? string?) ...) 'list)       ; only build selected list of packages -      ("manifests" 'manifests)                    ; only build packages in the list of manifests -      (_ 'all)))                                  ; build everything +    (assoc-ref arguments 'subset))    (define systems      (match (assoc-ref arguments 'systems) -      (#f              %hydra-supported-systems) +      (#f              %cuirass-supported-systems)        ((lst ...)       lst)        ((? string? str) (call-with-input-string str read)))) -  (define checkout -    (or (find-current-checkout arguments) -        (assq-ref arguments 'superior-guix-checkout))) +  (define channels +    (let ((channels (assq-ref arguments 'channels))) +      (map sexp->channel channels))) + +  (define guix +    (find guix-channel? channels))    (define commit -    (assq-ref checkout 'revision)) +    (channel-commit guix))    (define source -    (assq-ref checkout 'file-name)) +    (channel-url guix))    ;; Turn off grafts.  Grafting is meant to happen on the user's machines.    (parameterize ((%graft? #f))      ;; Return one job for each package, except bootstrap packages. -    (append-map (lambda (system) -                  (format (current-error-port) -                          "evaluating for '~a' (heap size: ~a MiB)...~%" -                          system -                          (round -                           (/ (assoc-ref (gc-stats) 'heap-size) -                              (expt 2. 20)))) -                  (invalidate-derivation-caches!) -                  (case subset -                    ((all) -                     ;; Build everything, including replacements. -                     (let ((all (all-packages)) -                           (job (lambda (package) -                                  (package->job store package -                                                system)))) -                       (append (filter-map job all) -                               (image-jobs store system) -                               (system-test-jobs store system -                                                 #:source source -                                                 #:commit commit) -                               (tarball-jobs store system) -                               (cross-jobs store system)))) -                    ((core) -                     ;; Build core packages only. -                     (append (map (lambda (package) -                                    (package-job store (job-name package) -                                                 package system)) -                                  %core-packages) -                             (cross-jobs store system))) -                    ((hello) -                     ;; Build hello package only. -                     (let ((hello (specification->package "hello"))) -                       (list (package-job store (job-name hello) hello system)))) -                    ((list) -                     ;; Build selected list of packages only. -                     (let* ((names (assoc-ref arguments 'subset)) -                            (packages (map specification->package names))) -                       (map (lambda (package) -                              (package-job store (job-name package) -                                           package system)) -                            packages))) -                    ((manifests) -                     ;; Build packages in the list of manifests. -                     (let* ((manifests (arguments->manifests arguments)) -                            (packages (manifests->packages store manifests))) -                       (map (lambda (package) -                              (package-job store (job-name package) -                                           package system)) -                            packages))) -                    (else -                     (error "unknown subset" subset)))) -                systems))) +    (append-map +     (lambda (system) +       (format (current-error-port) +               "evaluating for '~a' (heap size: ~a MiB)...~%" +               system +               (round +                (/ (assoc-ref (gc-stats) 'heap-size) +                   (expt 2. 20)))) +       (invalidate-derivation-caches!) +       (match subset +         ('all +          ;; Build everything, including replacements. +          (let ((all (all-packages)) +                (job (lambda (package) +                       (package->job store package system)))) +            (append +             (filter-map job all) +             (image-jobs store system) +             (system-test-jobs store system +                               #:source source +                               #:commit commit) +             (tarball-jobs store system) +             (cross-jobs store system)))) +         ('core +          ;; Build core packages only. +          (append +           (map (lambda (package) +                  (package-job store (job-name package) +                               package system)) +                %core-packages) +           (cross-jobs store system))) +         ('guix +          ;; Build Guix modules only. +          (guix-jobs store systems +                     #:source source +                     #:commit commit)) +         ('hello +          ;; Build hello package only. +          (let ((hello (specification->package "hello"))) +            (list (package-job store (job-name hello) +                               hello system)))) +         (('packages . rest) +          ;; Build selected list of packages only. +          (let ((packages (map specification->package rest))) +            (map (lambda (package) +                   (package-job store (job-name package) +                                package system)) +                 packages))) +         (('manifests . rest) +          ;; Build packages in the list of manifests. +          (let* ((manifests (arguments->manifests rest channels)) +                 (packages (manifests->packages store manifests))) +            (map (lambda (package) +                   (package-job store (job-name package) +                                package system)) +                 packages))) +         (else +          (error "unknown subset" subset)))) +     systems))) | 
