branch: main
commit 9b9a418e464017562bf152cc8aa631c0d6c4dd28
Author: Romain GARBAGE <romain.garb...@inria.fr>
AuthorDate: Fri Apr 4 18:34:39 2025 +0200

    forgejo: Add support for notification to Forgejo through reviews.
    
    * src/cuirass/forges/forgejo.scm (forgejo-notification-create-review): New 
variable.
    (forgejo-handle-notification): Add support for notification to Forgejo 
through reviews.
    
    Signed-off-by: Ludovic Courtès <l...@gnu.org>
---
 src/cuirass/forges/forgejo.scm | 103 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 103 insertions(+)

diff --git a/src/cuirass/forges/forgejo.scm b/src/cuirass/forges/forgejo.scm
index f5e3cdc..9463f83 100644
--- a/src/cuirass/forges/forgejo.scm
+++ b/src/cuirass/forges/forgejo.scm
@@ -456,6 +456,102 @@ BUILD-RESULTS is a list of build records."
     (when message
       (update-forgejo-pull-request-from-spec spec message))))
 
+(define* (forgejo-notification-create-review spec
+                                             #:key
+                                             (jobset-created #f)
+                                             (evaluation-started #f)
+                                             (evaluation-succeeded #f)
+                                             (evaluation-failed #f)
+                                             (build-results #f))
+  "Notify a Forgejo instance of a status change by creating a new review 
message.
+SPEC is a specification record, JOBSET-CREATED is a boolean,
+EVALUATION-STARTED, EVALUATION-SUCCEEDED and EVALUATION-FAILED are numbers and
+BUILD-RESULTS is a list of build records."
+  (log-info "preparing Forgejo notification for spec '~a'"
+            (specification-name spec))
+
+  (define (succeeded-builds build-results)
+    (filter-map (lambda (build)
+                  (and (= (build-status succeeded)
+                          (build-current-status build))
+                       (build-nix-name build)))
+                build-results))
+  (define (failed-builds build-results)
+    (filter-map (lambda (build)
+                  (and (build-failure?
+                        (build-current-status build))
+                       (build-nix-name build)))
+                build-results))
+
+  (let* ((name (specification-name spec))
+         (cuirass-url (%cuirass-url))
+         (message (cond
+                   (jobset-created
+                    (log-debug "forgejo-notification-create-review: ignoring 
jobset-created event")
+                    #f)
+                   (evaluation-started
+                    (log-debug "forgejo-notification-create-review: ignoring 
evaluation-started event")
+                    #f)
+                   (evaluation-succeeded
+                    (log-debug "forgejo-notification-create-review: ignoring 
evaluation-succeeded event")
+                    #f)
+                   (evaluation-failed
+                    (format #f
+                            "> Evaluation [~a](~a/eval/~a) of Cuirass jobset 
[~a](~a/jobset/~a) failed."
+                            evaluation-failed cuirass-url evaluation-failed
+                            name cuirass-url name))
+                   (build-results
+                    (let* ((evaluation-id (apply max
+                                                 (filter-map 
build-evaluation-id
+                                                             build-results)))
+                           (header
+                            (format #f "> Results for evaluation 
[~a](~a/eval/~a) of Cuirass jobset [~a](~a/jobset/~a):~%"
+                                    evaluation-id cuirass-url evaluation-id
+                                    name cuirass-url name))
+                           (succeeded-builds (succeeded-builds build-results))
+                           (successes (if (null? succeeded-builds)
+                                          ""
+                                          (format #f "> Successfully build ~a 
package(s): ~a~%"
+                                                  (length succeeded-builds)
+                                                  (string-join 
succeeded-builds ", "))))
+                           (failed-builds (failed-builds build-results))
+                           (failures (if (null? failed-builds)
+                                         ""
+                                         (format #f "> Failed build ~a 
package(s): ~a~%"
+                                                 (length failed-builds)
+                                                 (string-join failed-builds ", 
")))))
+                      (string-append header successes failures)))
+                   (#t #f)))
+         (review-state (if (or evaluation-failed
+                               (and=> build-results
+                                      (compose not null? failed-builds)))
+                           'REQUEST_CHANGES
+                           'APPROVED)))
+    ;; XXX: Raise an error when no message has been generated?
+    (when message
+      (log-debug "prepared Forgejo notification for spec '~a': ~a (review 
state ~a)"
+                 (specification-name spec) message review-state)
+      (let* ((properties (specification-properties spec))
+             (url (string->uri
+                   (assoc-ref properties
+                              'pull-request-url)))
+             (server (uri-host url))
+             (token (forge-get-token server
+                                     (assoc-ref properties
+                                                
'pull-request-target-namespace)))
+             (owner (assoc-ref properties
+                               'pull-request-target-repository-owner))
+             (repository (assoc-ref properties
+                                    'pull-request-target-repository-name))
+             (pull-request-index (assoc-ref properties
+                                            'pull-request-number)))
+        (forgejo-api-pull-request-create-review server token
+                                                #:owner owner
+                                                #:repository repository
+                                                #:pull-request-index 
pull-request-index
+                                                #:review-message message
+                                                #:review-state 
review-state)))))
+
 (define* (forgejo-handle-notification spec
                                       #:key
                                       (jobset-created #f)
@@ -474,6 +570,13 @@ EVALUATION-FAILED are numbers and BUILD-RESULTS is a list 
of build records."
                                                 #:evaluation-succeeded 
evaluation-succeeded
                                                 #:evaluation-failed 
evaluation-failed
                                                 #:build-results build-results))
+    ('create-review
+     (forgejo-notification-create-review spec
+                                         #:jobset-created jobset-created
+                                         #:evaluation-started 
evaluation-started
+                                         #:evaluation-succeeded 
evaluation-succeeded
+                                         #:evaluation-failed evaluation-failed
+                                         #:build-results build-results))
     (type
      (log-error "forgejo-handle-notification: unsupported notification type ~a"
                 type))))

Reply via email to