branch: main
commit de86524ddb4cef451fee81f680b53f719ea8e47a
Author: Ludovic Courtès <l...@gnu.org>
AuthorDate: Mon Sep 9 11:23:25 2024 +0200

    remote-worker: Send ‘build-dependency-failed’ when appropriate.
    
    Previously, builds with a failing dependency that does not have a
    corresponding entry in the ‘Builds’ table would be marked as “failed”.
    Now they’re marked as “dependency-failed”.
    
    * src/cuirass/remote.scm (build-dependency-failed-message): New
    procedure.
    * src/cuirass/scripts/remote-server.scm (serve-build-requests): Handle
    ‘build-dependency-failed’ messages.
    * src/cuirass/scripts/remote-worker.scm (run-build): Move
    ‘perform-build’ calls to ‘run-build-plan’; iterate over the BUILD list
    and send ‘build-dependency-failed’ message when appropriate.
    * tests/remote.scm ("build with failing dependency"): Adjust
    accordingly.
---
 src/cuirass/remote.scm                |  6 ++++
 src/cuirass/scripts/remote-server.scm |  5 ++++
 src/cuirass/scripts/remote-worker.scm | 56 ++++++++++++++++++++++++-----------
 tests/remote.scm                      |  4 +--
 4 files changed, 52 insertions(+), 19 deletions(-)

diff --git a/src/cuirass/remote.scm b/src/cuirass/remote.scm
index cd0a063..d268e4b 100644
--- a/src/cuirass/remote.scm
+++ b/src/cuirass/remote.scm
@@ -82,6 +82,7 @@
             build-started-message
             build-rejected-message
             build-failed-message
+            build-dependency-failed-message
             build-succeeded-message
             worker-ping
             worker-ready-message
@@ -573,6 +574,11 @@ within TIMEOUT seconds."
   "Return a message that indicates that the build of DRV has failed."
   `(build-failed (drv ,drv) (url ,url) (log ,log)))
 
+(define (build-dependency-failed-message drv url dependency)
+  "Return a message indicating that DEPENDENCY, a derivation of DRV, fails to
+build."
+  `(build-dependency-failed (drv ,drv) (url ,url) (dependency ,dependency)))
+
 (define* (build-succeeded-message drv url #:optional log)
   "Return a message that indicates that the build of DRV is done."
   `(build-succeeded (drv ,drv) (url ,url) (log ,log)))
diff --git a/src/cuirass/scripts/remote-server.scm 
b/src/cuirass/scripts/remote-server.scm
index 88f168d..99c2052 100644
--- a/src/cuirass/scripts/remote-server.scm
+++ b/src/cuirass/scripts/remote-server.scm
@@ -508,6 +508,11 @@ Use WORKER-DIRECTORY to maintain the list of active 
workers."
              (log-debug "fetching required for ~a (fail)" drv)
              (put-message fetch-worker command)
              #t)
+            (('build-dependency-failed ('drv drv) ('url url)
+                                       ('dependency dependency) _ ...)
+             (log-info "build failed: dependency '~a' of '~a'"
+                       dependency drv)
+             (db-update-build-status! drv (build-status failed-dependency)))
             (('worker-ready worker properties ...)
              (update-worker worker properties))
             (`(worker-request-info)
diff --git a/src/cuirass/scripts/remote-worker.scm 
b/src/cuirass/scripts/remote-worker.scm
index 9f8b15e..9c0c971 100644
--- a/src/cuirass/scripts/remote-worker.scm
+++ b/src/cuirass/scripts/remote-worker.scm
@@ -271,6 +271,44 @@ process may use up to PARALLELISM cores.
 The publish server of the build server is added to the list of the store
 substitutes-urls.  This way derivations that are not present on the worker can
 still be substituted."
+  (define (run-build-plan store drv build)
+    ;; Build DRV and its dependencies, sending a "build failed" message as
+    ;; soon as one of them fails.
+    ;; XXX: Assuming BUILD is in topological order.
+    (log-info "~a: build plan of '~a' includes ~a derivations"
+              (worker-name worker) drv (length build))
+
+    (let loop ((build build))
+      (match build
+        (()
+         (log-info "~a: done building '~a' and its dependencies"
+                   (worker-name worker) drv))
+        ((head tail ...)
+         (and (guard (c (#t                       ;catch all
+                         (if (string=? drv (derivation-file-name head))
+                             (begin
+                               (log-info "~a: '~a' failed to build"
+                                         (worker-name worker) drv)
+                               (reply (build-failed-message
+                                       drv
+                                       (worker-publish-url worker))))
+                             (begin
+                               (log-info "~a: '~a' failed to build\
+ (dependency of ~a)"
+                                         (worker-name worker)
+                                         (derivation-file-name head)
+                                         drv)
+                               (reply
+                                (build-dependency-failed-message
+                                 drv
+                                 (worker-publish-url worker)
+                                 (derivation-file-name head)))))
+                         #f))
+                (perform-build store (derivation-file-name head)
+                               worker server reply)
+                #t)
+              (loop tail))))))
+
   (with-store/non-blocking store
     (let ((publish-url (server-publish-url server)))
       ;; TODO: Choose PARALLELISM dynamically based on the number of currently
@@ -308,23 +346,7 @@ still be substituted."
                    (build-succeeded-message drv
                                             (worker-publish-url worker))))
                 (let ((build (if (null? build) (list drv) build)))
-                  ;; Build DRV and its dependencies, sending a "build failed"
-                  ;; message as soon as one of them fails.
-                  ;; XXX: Assuming BUILD is in topological order.
-                  (log-info "~a: build plan of '~a' includes ~a derivations"
-                            (worker-name worker) drv (length build))
-                  (guard (c (#t                   ;catch all
-                             ;; TODO: Distinguish between 'failed' and
-                             ;; 'failed-dependency'.
-                             (log-info "~a: '~a' or one of its dependencies \
-failed to build"
-                                       (worker-name worker) drv)
-                             (reply (build-failed-message
-                                     drv (worker-publish-url worker)))))
-                    (for-each (lambda (drv)
-                                (perform-build store (derivation-file-name drv)
-                                               worker server reply))
-                              build)))))
+                  (run-build-plan store drv build))))
           (begin
             (log-error "~a cannot be fetched; not building it" drv)
             (reply (build-rejected-message drv (worker-name worker))))))))
diff --git a/tests/remote.scm b/tests/remote.scm
index bea6f01..712ea52 100644
--- a/tests/remote.scm
+++ b/tests/remote.scm
@@ -298,7 +298,7 @@ Completing build process.\n"))
 
   (test-assert "build with failing dependency"
     ;; When a build depends on a failing derivation with no corresponding
-    ;; build entry, that build must be marked as failing.
+    ;; build entry, that build must be marked as 'failed-dependency'.
     (let* ((dependency (with-store store
                          (derivation-file-name
                           (run-with-store store
@@ -314,7 +314,7 @@ Failing dependency ~s.\n"
       (retry
        (lambda ()
          (and (= (build-current-status (db-get-build drv))
-                 (build-status failed))
+                 (build-status failed-dependency))
               (not (stat (build-log-file drv) #f))))
        #:times 10
        #:delay 1)))

Reply via email to