aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Baines <mail@cbaines.net>2023-10-14 21:14:28 +0100
committerChristopher Baines <mail@cbaines.net>2023-10-15 12:13:09 +0100
commit801e6d12a2e4175ed5dacd3b812d66623ce0d66e (patch)
tree051552022e4fd56adc7e00dad3c26564d3b42c61
parent00808356f65a4bc40aaa66d335a71f6fca9c1f7d (diff)
downloadqa-frontpage-801e6d12a2e4175ed5dacd3b812d66623ce0d66e.tar
qa-frontpage-801e6d12a2e4175ed5dacd3b812d66623ce0d66e.tar.gz
Show the changes to cross derivations on issue pages
-rw-r--r--guix-qa-frontpage/derivation-changes.scm30
-rw-r--r--guix-qa-frontpage/guix-data-service.scm13
-rw-r--r--guix-qa-frontpage/issue.scm118
-rw-r--r--guix-qa-frontpage/server.scm35
-rw-r--r--guix-qa-frontpage/view/issue.scm35
-rw-r--r--guix-qa-frontpage/view/shared.scm726
6 files changed, 733 insertions, 224 deletions
diff --git a/guix-qa-frontpage/derivation-changes.scm b/guix-qa-frontpage/derivation-changes.scm
index 6953603..cda0084 100644
--- a/guix-qa-frontpage/derivation-changes.scm
+++ b/guix-qa-frontpage/derivation-changes.scm
@@ -128,16 +128,26 @@
(cons system '())))
all-systems))
(lambda (a b)
- (< (or (list-index
- (lambda (s)
- (string=? (car a) s))
- all-systems)
- 10)
- (or (list-index
- (lambda (s)
- (string=? (car b) s))
- all-systems)
- 10)))))))
+ (let ((a-key (car a))
+ (b-key (car b)))
+ (cond
+ ((and (string? a-key)
+ (string? b-key))
+ (< (or (list-index
+ (lambda (s)
+ (string=? (car a) s))
+ all-systems)
+ 10)
+ (or (list-index
+ (lambda (s)
+ (string=? (car b) s))
+ all-systems)
+ 10)))
+ ((and (pair? a-key)
+ (pair? b-key))
+ (string<? (cdr a-key)
+ (cdr b-key)))
+ (else #f))))))))
`(,@derivation-changes
(counts . ,counts)))
diff --git a/guix-qa-frontpage/guix-data-service.scm b/guix-qa-frontpage/guix-data-service.scm
index 8de4e21..03bb39d 100644
--- a/guix-qa-frontpage/guix-data-service.scm
+++ b/guix-qa-frontpage/guix-data-service.scm
@@ -22,6 +22,7 @@
guix-data-service-error->sexp
compare-package-derivations-url
+ compare-package-cross-derivations-url
compare-package-derivations
revision-comparison-url
@@ -178,6 +179,18 @@
"&target=none"
"&field=builds&limit_results=&all_results=on"))
+(define* (compare-package-cross-derivations-url base-and-target-refs #:key systems)
+ (string-append
+ "https://data.qa.guix.gnu.org/compare/package-derivations.json?"
+ "base_commit=" (assq-ref base-and-target-refs 'base)
+ "&target_commit=" (assq-ref base-and-target-refs 'target)
+ (string-join
+ (map (lambda (system)
+ (simple-format #f "&system=~A" system))
+ (or systems '()))
+ "")
+ "&field=builds&limit_results=&all_results=on"))
+
(define (compare-package-derivations url)
(let ((json-body
(guix-data-service-request url)))
diff --git a/guix-qa-frontpage/issue.scm b/guix-qa-frontpage/issue.scm
index 345aafe..87d7a64 100644
--- a/guix-qa-frontpage/issue.scm
+++ b/guix-qa-frontpage/issue.scm
@@ -151,62 +151,82 @@
tags-status))))))
(define (issue-data number)
+ (define (call-with-data-service-error-handling thunk)
+ (with-exception-handler
+ (lambda (exn)
+ (if (guix-data-service-error? exn)
+ `((exception . guix-data-service-invalid-parameters)
+ (invalid_query_parameters
+ .
+ ,(filter-map
+ (match-lambda
+ ((param . val)
+ (and=>
+ (assoc-ref val "invalid_value")
+ (lambda (value)
+ (let ((message
+ (assoc-ref val "message")))
+ (cons
+ param
+ `((value . ,value)
+ (error
+ ;; Convert the HTML error messages
+ ;; to something easier to handle
+ . ,(cond
+ ((string-contains message
+ "failed to process revision")
+ 'failed-to-process-revision)
+ ((string-contains message
+ "yet to process revision")
+ 'yet-to-process-revision)
+ (else
+ 'unknown))))))))))
+ (assoc-ref
+ (guix-data-service-error-response-body exn)
+ "query_parameters"))))
+ `((exception . ,(simple-format #f "~A" exn)))))
+ thunk
+ #:unwind? #t))
+
(let* ((base-and-target-refs
(get-issue-branch-base-and-target-refs
number))
+ (derivation-changes-raw-data
+ (if base-and-target-refs
+ (call-with-data-service-error-handling
+ (lambda ()
+ (compare-package-derivations
+ (compare-package-derivations-url
+ base-and-target-refs
+ #:systems %systems-to-submit-builds-for))))
+ #f))
(derivation-changes-data
+ (if (and derivation-changes-raw-data
+ (not (assq-ref derivation-changes-raw-data 'exception)))
+ (derivation-changes
+ derivation-changes-raw-data
+ %systems-to-submit-builds-for)
+ #f))
+ (cross-derivation-changes-raw-data
(if base-and-target-refs
- (with-exception-handler
- (lambda (exn)
- (if (guix-data-service-error? exn)
- `((exception . guix-data-service-invalid-parameters)
- (invalid_query_parameters
- .
- ,(filter-map
- (match-lambda
- ((param . val)
- (and=>
- (assoc-ref val "invalid_value")
- (lambda (value)
- (let ((message
- (assoc-ref val "message")))
- (cons
- param
- `((value . ,value)
- (error
- ;; Convert the HTML error messages
- ;; to something easier to handle
- . ,(cond
- ((string-contains message
- "failed to process revision")
- 'failed-to-process-revision)
- ((string-contains message
- "yet to process revision")
- 'yet-to-process-revision)
- (else
- 'unknown))))))))))
- (assoc-ref
- (guix-data-service-error-response-body exn)
- "query_parameters"))))
- `((exception . ,(simple-format #f "~A" exn)))))
- (lambda ()
- (compare-package-derivations
- (compare-package-derivations-url
- base-and-target-refs
- #:systems %systems-to-submit-builds-for)))
- #:unwind? #t)
+ (call-with-data-service-error-handling
+ (lambda ()
+ (compare-package-derivations
+ (compare-package-cross-derivations-url
+ base-and-target-refs
+ #:systems %systems-to-submit-builds-for))))
#f))
- (derivation-changes
- (if (and derivation-changes-data
- (not (assq-ref derivation-changes-data 'exception)))
+ (cross-derivation-changes-data
+ (if (and cross-derivation-changes-raw-data
+ (not (assq-ref cross-derivation-changes-raw-data 'exception)))
(derivation-changes
- derivation-changes-data
+ cross-derivation-changes-raw-data
%systems-to-submit-builds-for)
#f))
(builds-missing?
- (if derivation-changes
+ (if derivation-changes-data
(builds-missing-for-derivation-changes?
- (assoc-ref derivation-changes-data
+ (assoc-ref derivation-changes-raw-data
"derivation_changes"))
#t))
(comparison-details
@@ -253,8 +273,9 @@
(values
base-and-target-refs
- derivation-changes
- (and=> derivation-changes-data
+ derivation-changes-data
+ cross-derivation-changes-data
+ (and=> derivation-changes-raw-data
(lambda (changes)
(alist-delete "derivation_changes" changes)))
builds-missing?
@@ -300,6 +321,7 @@
(lambda ()
(let ((base-and-target-refs
derivation-changes
+ cross-derivation-changes
change-details
builds-missing?
comparison-details
@@ -309,7 +331,7 @@
issue-data
#:args
(list issue-number)
- #:version 2
+ #:version 3
#:ttl (/ frequency 2))))
(with-sqlite-cache
diff --git a/guix-qa-frontpage/server.scm b/guix-qa-frontpage/server.scm
index 4a45720..f397011 100644
--- a/guix-qa-frontpage/server.scm
+++ b/guix-qa-frontpage/server.scm
@@ -509,6 +509,7 @@
(if series
(let* ((base-and-target-refs
derivation-changes
+ cross-derivation-changes
change-details
builds-missing?
comparison-details
@@ -518,7 +519,7 @@
issue-data
#:args
(list (string->number number))
- #:version 2
+ #:version 3
#:ttl 6000))
(create-branch-for-issue-log
(select-create-branch-for-issue-log
@@ -549,6 +550,7 @@
base-and-target-refs
#:json? #f))
derivation-changes
+ cross-derivation-changes
builds-missing?
change-details
comparison-details
@@ -575,6 +577,7 @@ has no patches or has been closed.")
(('GET "issue" number "package-changes")
(let ((revisions
derivation-changes
+ cross-derivation-changes
substitute-availability
up-to-date-with-master
master-branch-systems-with-low-substitute-availability
@@ -584,7 +587,7 @@ has no patches or has been closed.")
issue-data
#:args
(list (string->number number))
- #:version 2
+ #:version 3
#:ttl 6000)))
(render-html
#:sxml
@@ -595,9 +598,35 @@ has no patches or has been closed.")
(uri-query (request-uri request))
parse-query-string)
'())))))
+ (('GET "issue" number "package-cross-changes")
+ (let ((revisions
+ derivation-changes
+ cross-derivation-changes
+ substitute-availability
+ up-to-date-with-master
+ master-branch-systems-with-low-substitute-availability
+ (with-sqlite-cache
+ database
+ 'issue-data
+ issue-data
+ #:args
+ (list (string->number number))
+ #:version 3
+ #:ttl 6000)))
+ (render-html
+ #:sxml
+ (issue-package-cross-changes-view number
+ "x86_64-linux"
+ cross-derivation-changes
+ (or
+ (and=>
+ (uri-query (request-uri request))
+ parse-query-string)
+ '())))))
(('GET "issue" number "prepare-review")
(let ((revisions
derivation-changes
+ cross-derivation-changes
substitute-availability
up-to-date-with-master
master-branch-systems-with-low-substitute-availability
@@ -607,7 +636,7 @@ has no patches or has been closed.")
issue-data
#:args
(list (string->number number))
- #:version 2
+ #:version 3
#:ttl 6000)))
(render-html
#:sxml
diff --git a/guix-qa-frontpage/view/issue.scm b/guix-qa-frontpage/view/issue.scm
index f7e83f9..e149cc4 100644
--- a/guix-qa-frontpage/view/issue.scm
+++ b/guix-qa-frontpage/view/issue.scm
@@ -11,6 +11,7 @@
#:use-module (guix-qa-frontpage view shared)
#:export (issue-view
issue-package-changes-view
+ issue-package-cross-changes-view
issue-prepare-review-view))
@@ -19,6 +20,7 @@
create-branch-for-issue-log
comparison-link
derivation-changes
+ cross-derivation-changes
builds-missing?
change-details comparison-details
systems-with-low-substitute-availability)
@@ -32,6 +34,14 @@
(define derivation-changes-counts
(assq-ref derivation-changes 'counts))
+ (define cross-derivation-changes-counts
+ (and cross-derivation-changes
+ (filter
+ (match-lambda
+ (((system . target) . derivations) #t)
+ (_ #f))
+ (assq-ref cross-derivation-changes 'counts))))
+
(define links-div
`(div
(@ (class "large-screen-float-right"))
@@ -189,7 +199,8 @@
(null? systems-with-low-substitute-availability)
(not comparison-details)
(assq-ref comparison-details 'exception)
- (null? derivation-changes-counts))
+ (and (null? derivation-changes-counts)
+ (null? cross-derivation-changes-counts)))
'()
;; TODO: Only show (and apply) this if it relates to these
;; changes. So just look at the systems relevant to the changes.
@@ -219,6 +230,18 @@
(target . ,(assoc-ref (assoc-ref revisions "target")
"commit"))))
derivation-changes-counts
+ (string-append "/issue/" issue-number))
+
+ (h4 "Cross builds from "
+ (code "x86_64-linux"))
+
+ ,(package-cross-changes-summary-table
+ (let ((revisions (assoc-ref change-details "revisions")))
+ `((base . ,(assoc-ref (assoc-ref revisions "base")
+ "commit"))
+ (target . ,(assoc-ref (assoc-ref revisions "target")
+ "commit"))))
+ cross-derivation-changes-counts
(string-append "/issue/" issue-number))))
(define prepare-review-section
@@ -363,6 +386,16 @@ div.bad {
derivation-changes
query-parameters))
+(define (issue-package-cross-changes-view issue-number
+ system
+ cross-derivation-changes
+ query-parameters)
+ (package-cross-changes-view
+ (simple-format #f "Issue ~A" issue-number)
+ system
+ cross-derivation-changes
+ query-parameters))
+
(define (issue-prepare-review-view issue-number query-parameters)
(define (escape str)
(call-with-output-string
diff --git a/guix-qa-frontpage/view/shared.scm b/guix-qa-frontpage/view/shared.scm
index 3411224..3cf92b8 100644
--- a/guix-qa-frontpage/view/shared.scm
+++ b/guix-qa-frontpage/view/shared.scm
@@ -27,19 +27,177 @@
#:use-module (guix-qa-frontpage manage-builds)
#:use-module (guix-qa-frontpage view util)
#:export (package-changes-view
- package-changes-summary-table))
+ package-cross-changes-view
+ package-changes-summary-table
+ package-cross-changes-summary-table))
+
+(define (builds->overall-status builds)
+ (if (eq? #f builds)
+ 'not-present
+ (let ((build-statuses
+ (map
+ (lambda (build)
+ (let ((status
+ (assoc-ref build "status")))
+ (if (and (string=? status "scheduled")
+ (assoc-ref build "potentially_blocked"))
+ "blocked"
+ status)))
+ builds)))
+ (cond
+ ((member "succeeded" build-statuses)
+ 'succeeding)
+ ((and (not (member "succeeded" build-statuses))
+ (member "failed" build-statuses))
+ 'failing)
+ ((member "blocked" build-statuses)
+ 'blocked)
+ (else
+ 'unknown)))))
+
+(define %changes
+ '(broken
+ fixed
+ blocked
+ still-working
+ still-failing
+ still-blocked
+ new-working
+ new-failing
+ new-blocked
+ removed-working
+ removed-failing
+ removed-blocked
+ unknown-to-working
+ unknown-to-failing
+ unknown-to-blocked
+ unknown))
+
+(define (builds->change-by-system builds-by-system)
+ (map
+ (match-lambda
+ ((system . builds)
+ (let ((base-status (builds->overall-status
+ (assoc-ref builds "base")))
+ (target-status (builds->overall-status
+ (assoc-ref builds "target"))))
+ (cons
+ system
+ (cond
+ ((and (eq? base-status 'succeeding)
+ (eq? target-status 'failing))
+ 'broken)
+ ((and (eq? base-status 'succeeding)
+ (eq? target-status 'blocked))
+ 'blocked)
+ ((and (or (eq? base-status 'failing)
+ (eq? base-status 'blocked))
+ (eq? target-status 'succeeding))
+ 'fixed)
+ ((and (eq? 'not-present base-status)
+ (eq? 'succeeding target-status))
+ 'new-working)
+ ((and (eq? 'not-present base-status)
+ (eq? 'failing target-status))
+ 'new-failing)
+ ((and (eq? 'not-present base-status)
+ (eq? 'blocked target-status))
+ 'new-blocked)
+ ((and (eq? 'succeeding base-status)
+ (eq? 'not-present target-status))
+ 'removed-working)
+ ((and (eq? 'failing base-status)
+ (eq? 'not-present target-status))
+ 'removed-failing)
+ ((and (eq? 'blocked base-status)
+ (eq? 'not-present target-status))
+ 'removed-blocked)
+ ((and (eq? base-status target-status 'succeeding))
+ 'still-working)
+ ((and (eq? base-status target-status 'failing))
+ 'still-failing)
+ ((and (eq? base-status target-status 'blocked))
+ 'still-blocked)
+ ((and (or (eq? 'unknown base-status)
+ (eq? 'blocked base-status))
+ (eq? 'succeeding target-status))
+ 'unknown-to-working)
+ ((and (or (eq? 'unknown base-status)
+ (eq? 'blocked base-status))
+ (eq? 'failing target-status))
+ 'unknown-to-failing)
+ ((and (eq? 'unknown base-status)
+ (eq? 'blocked target-status))
+ 'unknown-to-blocked)
+ (else 'unknown))))))
+ builds-by-system))
+
+(define (display-builds builds derivations change)
+ (define %color-for-change
+ '((fixed . "green")
+ (broken . "red")
+ (blocked . "yellow")
+ (still-working . "lightgreen")
+ (still-failing . "#FFCCCB")
+ (still-blocked . "lightyellow")
+ (new-working . "lightgreen")
+ (new-failing . "red")
+ (new-blocked . "lightyellow")
+ (removed-working . "")
+ (removed-failing . "")
+ (removed-blocked . "")
+ (unknown-to-working . "lightgreen")
+ (unknown-to-failing . "#FFCCCB")
+ (unknown-to-blocked . "lightyellow")
+ (unknown . "lightgrey")))
+
+ (if builds
+ (let ((base-status
+ (builds->overall-status
+ (assoc-ref builds "base")))
+ (target-status
+ (builds->overall-status
+ (assoc-ref builds "target"))))
+ (if (and
+ (eq? base-status 'not-present)
+ (eq? target-status 'not-present))
+ '(td)
+ `(td
+ (@ (style ,(simple-format
+ #f
+ "background-color: ~A;"
+ (assq-ref
+ %color-for-change
+ change))))
+ ,(if (eq? base-status 'not-present)
+ `(div "was not present")
+ `(div
+ (a (@ (href ,(string-append
+ "https://data.qa.guix.gnu.org"
+ (uri-encode-filename
+ (assoc-ref derivations "base")))))
+ "was " ,base-status)))
+ ,(if (eq? target-status 'not-present)
+ `(div "now not present")
+ `(div
+ (a (@ (href ,(string-append
+ "https://data.qa.guix.gnu.org"
+ (uri-encode-filename
+ (assoc-ref derivations "target")))))
+ "now " ,target-status))))))
+ '(td)))
(define (package-changes-view title
derivation-changes
query-parameters)
- (define (derivation-for-system side system)
+ (define (derivation-for-system derivations system)
(vector-any
(lambda (derivation)
(if (string=? (assoc-ref derivation "system")
system)
derivation
#f))
- side))
+ derivations))
(define (builds-by-system base target)
(map
@@ -73,162 +231,6 @@
(assoc-ref derivation "derivation-file-name")))))))
%systems-to-submit-builds-for))
- (define (builds->overall-status side-builds)
- (if (eq? #f side-builds)
- 'not-present
- (let ((build-statuses
- (map
- (lambda (build)
- (let ((status
- (assoc-ref build "status")))
- (if (and (string=? status "scheduled")
- (assoc-ref build "potentially_blocked"))
- "blocked"
- status)))
- side-builds)))
- (cond
- ((member "succeeded" build-statuses)
- 'succeeding)
- ((and (not (member "succeeded" build-statuses))
- (member "failed" build-statuses))
- 'failing)
- ((member "blocked" build-statuses)
- 'blocked)
- (else
- 'unknown)))))
-
- (define %changes
- '(broken
- fixed
- blocked
- still-working
- still-failing
- still-blocked
- new-working
- new-failing
- new-blocked
- removed-working
- removed-failing
- removed-blocked
- unknown-to-working
- unknown-to-failing
- unknown-to-blocked
- unknown))
-
- (define (builds->change-by-system builds-by-system)
- (map
- (match-lambda
- ((system . builds)
- (let ((base-status (builds->overall-status
- (assoc-ref builds "base")))
- (target-status (builds->overall-status
- (assoc-ref builds "target"))))
- (cons
- system
- (cond
- ((and (eq? base-status 'succeeding)
- (eq? target-status 'failing))
- 'broken)
- ((and (eq? base-status 'succeeding)
- (eq? target-status 'blocked))
- 'blocked)
- ((and (or (eq? base-status 'failing)
- (eq? base-status 'blocked))
- (eq? target-status 'succeeding))
- 'fixed)
- ((and (eq? 'not-present base-status)
- (eq? 'succeeding target-status))
- 'new-working)
- ((and (eq? 'not-present base-status)
- (eq? 'failing target-status))
- 'new-failing)
- ((and (eq? 'not-present base-status)
- (eq? 'blocked target-status))
- 'new-blocked)
- ((and (eq? 'succeeding base-status)
- (eq? 'not-present target-status))
- 'removed-working)
- ((and (eq? 'failing base-status)
- (eq? 'not-present target-status))
- 'removed-failing)
- ((and (eq? 'blocked base-status)
- (eq? 'not-present target-status))
- 'removed-blocked)
- ((and (eq? base-status target-status 'succeeding))
- 'still-working)
- ((and (eq? base-status target-status 'failing))
- 'still-failing)
- ((and (eq? base-status target-status 'blocked))
- 'still-blocked)
- ((and (or (eq? 'unknown base-status)
- (eq? 'blocked base-status))
- (eq? 'succeeding target-status))
- 'unknown-to-working)
- ((and (or (eq? 'unknown base-status)
- (eq? 'blocked base-status))
- (eq? 'failing target-status))
- 'unknown-to-failing)
- ((and (eq? 'unknown base-status)
- (eq? 'blocked target-status))
- 'unknown-to-blocked)
- (else 'unknown))))))
- builds-by-system))
-
- (define (display-builds builds derivations change)
- (define %color-for-change
- '((fixed . "green")
- (broken . "red")
- (blocked . "yellow")
- (still-working . "lightgreen")
- (still-failing . "#FFCCCB")
- (still-blocked . "lightyellow")
- (new-working . "lightgreen")
- (new-failing . "red")
- (new-blocked . "lightyellow")
- (removed-working . "")
- (removed-failing . "")
- (removed-blocked . "")
- (unknown-to-working . "lightgreen")
- (unknown-to-failing . "#FFCCCB")
- (unknown-to-blocked . "lightyellow")
- (unknown . "lightgrey")))
-
- (if builds
- (let ((base-status
- (builds->overall-status
- (assoc-ref builds "base")))
- (target-status
- (builds->overall-status
- (assoc-ref builds "target"))))
- (if (and
- (eq? base-status 'not-present)
- (eq? target-status 'not-present))
- '(td)
- `(td
- (@ (style ,(simple-format
- #f
- "background-color: ~A;"
- (assq-ref
- %color-for-change
- change))))
- ,(if (eq? base-status 'not-present)
- `(div "was not present")
- `(div
- (a (@ (href ,(string-append
- "https://data.qa.guix.gnu.org"
- (uri-encode-filename
- (assoc-ref derivations "base")))))
- "was " ,base-status)))
- ,(if (eq? target-status 'not-present)
- `(div "now not present")
- `(div
- (a (@ (href ,(string-append
- "https://data.qa.guix.gnu.org"
- (uri-encode-filename
- (assoc-ref derivations "target")))))
- "now " ,target-status))))))
- '(td)))
-
(define grouped-query-parameters
(group-to-alist
identity
@@ -365,6 +367,214 @@
'()
(assoc-ref derivation-changes "derivation_changes"))))))))
+(define (package-cross-changes-view title
+ system
+ derivation-changes
+ query-parameters)
+ (define (derivation-for-target derivations target)
+ (vector-any
+ (lambda (derivation)
+ (if (string=? (assoc-ref derivation "target")
+ target)
+ derivation
+ #f))
+ derivations))
+
+ ;; TODO This probably performs poorly when there are lots of changes
+ (define all-targets
+ (delete-duplicates!
+ (vector-fold-right
+ (lambda (_ result package-and-version)
+ (vector-fold-right
+ (lambda (_ result derivation)
+ (let ((target
+ (assoc-ref derivation "target")))
+ (if (string-null? target)
+ result
+ (cons target result))))
+ (vector-fold-right
+ (lambda (_ result derivation)
+ (let ((target
+ (assoc-ref derivation "target")))
+ (if (string-null? target)
+ result
+ (cons target result))))
+ result
+ (assoc-ref package-and-version "target"))
+ (assoc-ref package-and-version "base")))
+ '()
+ (assoc-ref derivation-changes "derivation_changes"))))
+
+ (define (builds-by-target base-data target-data)
+ (map
+ (lambda (target)
+ (cons
+ target
+ `(("base" . ,(and=>
+ (derivation-for-target base-data target)
+ (lambda (derivation)
+ (vector->list
+ (assoc-ref derivation "builds")))))
+ ("target" . ,(and=>
+ (derivation-for-target target-data target)
+ (lambda (derivation)
+ (vector->list
+ (assoc-ref derivation "builds"))))))))
+ all-targets))
+
+ (define (derivations-by-target base-data target-data)
+ (map
+ (lambda (target)
+ (cons
+ target
+ `(("base" . ,(and=>
+ (derivation-for-target base-data target)
+ (lambda (derivation)
+ (assoc-ref derivation "derivation-file-name"))))
+ ("target" . ,(and=>
+ (derivation-for-target target-data target)
+ (lambda (derivation)
+ (assoc-ref derivation "derivation-file-name")))))))
+ all-targets))
+
+ (define grouped-query-parameters
+ (group-to-alist
+ identity
+ query-parameters))
+
+ (define target-change
+ (map
+ (lambda (target)
+ (cons (string-append target "-change")
+ target))
+ all-targets))
+
+ (define (display? package-and-version change-by-target)
+ (every
+ (match-lambda
+ ((key . vals)
+ (cond
+ ((assoc-ref target-change key)
+ (let ((system (assoc-ref target-change key)))
+ (->bool
+ (member (assoc-ref change-by-target system)
+ (map string->symbol vals)))))
+ (else #t))))
+ grouped-query-parameters))
+
+ (layout
+ #:title title
+ #:body
+ `((main
+ (@ (style "max-width: 98%;"))
+ (table
+ (form
+ (@ (id "filter-form")
+ (method "get"))
+ (thead
+ (tr
+ (td "Name")
+ (td "Version")
+ ,@(map
+ (lambda (target)
+ `(td (span (@ (style "font-size: 1.5em; font-family: monospace;"))
+ ,target)
+ (select
+ (@ (name
+ ,(simple-format #f "~A-change"
+ target))
+ (style "margin-bottom: 0;")
+ (multiple #t))
+ ,@(let ((target-change-selected-options
+ (or (assoc-ref
+ grouped-query-parameters
+ (string-append target "-change"))
+ '())))
+ (map
+ (match-lambda
+ ((value . label)
+ `(option
+ (@ (value ,value)
+ ,@(if (member (symbol->string value)
+ target-change-selected-options)
+ '((selected ""))
+ '()))
+ ,label)))
+ (map
+ (lambda (change)
+ (cons change change))
+ %changes))))
+ (button
+ (@ (type "submit")
+ (style "padding: 0; width: 100%;"))
+ "Update")))
+ all-targets))
+ (tr
+ (td)
+ (td)
+ ,@(map
+ (lambda (target)
+ (let* ((target-change-selected-options
+ (or (assoc-ref
+ grouped-query-parameters
+ (string-append target "-change"))
+ '()))
+ (selected-labels
+ (filter-map
+ (match-lambda
+ ((value . label)
+ (if (member (symbol->string value)
+ target-change-selected-options)
+ label
+ #f)))
+ (map
+ (lambda (change)
+ (cons change change))
+ %changes))))
+ (if (null? selected-labels)
+ '(td)
+ `(td
+ "Filtering for:"
+ (ul
+ (@ (style "margin: 0;"))
+ ,@(map (lambda (label)
+ `(li ,label))
+ selected-labels))))))
+ all-targets))))
+ (tbody
+ (@ (style "overflow: auto; max-height: 40em;"))
+ ,@(vector-fold-right
+ (lambda (_ result package-and-version)
+ (let* ((builds
+ (builds-by-target
+ (assoc-ref package-and-version "base")
+ (assoc-ref package-and-version "target")))
+ (derivations
+ (derivations-by-target
+ (assoc-ref package-and-version "base")
+ (assoc-ref package-and-version "target")))
+ (change-by-target
+ ;; This works, even though the naming is wrong as it's
+ ;; being used to group builds by target
+ (builds->change-by-system builds)))
+ (cons
+ `(tr
+ (@ ,@(if (display? package-and-version
+ change-by-target)
+ '()
+ '((style "display: none;"))))
+ (td ,(assoc-ref package-and-version "name"))
+ (td ,(assoc-ref package-and-version "version"))
+ ,@(map
+ (lambda (target)
+ (display-builds (assoc-ref builds target)
+ (assoc-ref derivations target)
+ (assoc-ref change-by-target target)))
+ all-targets))
+ result)))
+ '()
+ (assoc-ref derivation-changes "derivation_changes"))))))))
+
(define (package-changes-summary-table revisions
derivation-changes-counts
package-changes-url-prefix)
@@ -372,10 +582,17 @@
(define* (package-derivations-comparison-link system
#:key build-change)
(string-append
- (simple-format #f "https://data.qa.guix.gnu.org/compare/package-derivations?base_commit=~A&target_commit=~A&system=~A&target=none"
+ (simple-format #f "https://data.qa.guix.gnu.org/compare/package-derivations?base_commit=~A&target_commit=~A"
(assq-ref revisions 'base)
- (assq-ref revisions 'target)
- system)
+ (assq-ref revisions 'target))
+ (match system
+ ((system . target)
+ (simple-format #f "&system=~A&target=~A"
+ system
+ target))
+ (system
+ (simple-format #f "&system=~A&target=none"
+ system)))
(if build-change
(simple-format #f "&build_change=~A" build-change)
"")))
@@ -545,3 +762,188 @@
"target revision.")))))))))))
params)))
'()))))))))
+
+(define (package-cross-changes-summary-table revisions
+ cross-derivation-changes-counts
+ package-changes-url-prefix)
+
+ (define* (package-derivations-comparison-link system target
+ #:key build-change)
+ (string-append
+ (simple-format #f "https://data.qa.guix.gnu.org/compare/package-derivations?base_commit=~A&target_commit=~A"
+ (assq-ref revisions 'base)
+ (assq-ref revisions 'target))
+ (simple-format #f "&system=~A&target=~A"
+ system
+ target)
+ (if build-change
+ (simple-format #f "&build_change=~A" build-change)
+ "")))
+
+ `(table
+ (@ (style "border-collapse: collapse;"))
+ (thead
+ (tr
+ (th (@ (rowspan 3)) "Target")
+ (th (@ (colspan 8)) "Package build status")
+ (th))
+ (tr
+ (th (@ (colspan 4)) "Base")
+ (th (@ (colspan 4)
+ (style "border-left-width: 0.1em; border-left-style: solid; border-left-color: black"))
+ "With branch changes")
+ (th))
+ (tr
+ ,@(let ((header-style
+ "font-size: 80%; min-width: 3.5rem;"))
+ `((th (@ (style ,header-style))
+ "Succeeding")
+ (th (@ (style ,header-style))
+ "Failing")
+ (th (@ (style ,header-style))
+ "Blocked")
+ (th (@ (style ,header-style))
+ "Unknown")
+ (th (@ (style
+ ,(string-append
+ header-style
+ " border-left-width: 0.125em; border-left-style: solid; border-left-color: black;")))
+ "Succeeding")
+ (th (@ (style ,header-style))
+ "Failing")
+ (th (@ (style ,header-style))
+ "Blocked")
+ (th (@ (style ,header-style))
+ "Unknown")
+ (th)))))
+ (tbody
+ ,@(if (and cross-derivation-changes-counts
+ (not (assq-ref cross-derivation-changes-counts 'exception)))
+ (if (null? cross-derivation-changes-counts)
+ `((tr
+ (td (@ (colspan 7))
+ "No package derivation changes")))
+ (map
+ (match-lambda
+ (((system . target) . derivations)
+
+ (define (count side status)
+ (assoc-ref (assoc-ref
+ derivations
+ side)
+ status))
+
+ `(tr
+ (td (@ (class "monospace")) ,target)
+ ,@(map (lambda (status)
+ `(td ,(count 'base status)))
+ '(succeeding failing blocked unknown))
+ (td ,@(if (and (>= (count 'target 'succeeding)
+ (count 'base 'succeeding))
+ (> (count 'target 'succeeding)
+ 0))
+ `((@ (class "good")))
+ '())
+ (a (@ (href
+ ,(string-append
+ package-changes-url-prefix
+ "/package-cross-changes?"
+ target "-change=fixed&"
+ target "-change=still-working&"
+ target "-change=unknown-to-working&"
+ target "-change=new-working")))
+ ,(count 'target 'succeeding)))
+ (td ,@(if (> (count 'target 'failing)
+ (count 'base 'failing))
+ '((@ (class "bad")))
+ '())
+ (a (@ (href
+ ,(string-append
+ package-changes-url-prefix
+ "/package-cross-changes?"
+ target "-change=broken&"
+ target "-change=still-failing&"
+ target "-change=unknown-to-failing&"
+ target "-change=new-failing")))
+ ,(count 'target 'failing)))
+ (td ,@(if (> (count 'target 'blocked)
+ (count 'base 'blocked))
+ '((@ (class "bad")))
+ '())
+ (a (@ (href
+ ,(string-append
+ package-changes-url-prefix
+ "/package-cross-changes?"
+ target "-change=blocked&"
+ target "-change=still-blocked&"
+ target "-change=unknown-to-blocked&"
+ target "-change=new-blocked")))
+ ,(count 'target 'blocked)))
+ (td (@ ,@(if (> (count 'target 'unknown)
+ (count 'base 'unknown))
+ '((class "bad"))
+ '()))
+ (a (@ (href
+ ,(string-append
+ package-changes-url-prefix
+ "/package-cross-changes?"
+ target "-change=unknown")))
+ ,(count 'target 'unknown)))
+ (td (a (@ (href
+ ,(package-derivations-comparison-link system
+ target)))
+ "View comparison")))))
+ cross-derivation-changes-counts))
+ `((tr
+ (td (@ (colspan 10)
+ (class "bad"))
+ "Comparison unavailable"
+ ,@(or (and=>
+ (assq-ref cross-derivation-changes-counts
+ 'invalid_query_parameters)
+ (lambda (params)
+ (append-map
+ (match-lambda
+ ((param . details)
+ (let ((error
+ (assq-ref details 'error)))
+ (cond
+ ((member param '("base_commit"
+ "target_commit"))
+ `((br)
+ (a
+ (@ (href
+ ,(string-append
+ "https://data.qa.guix.gnu.org"
+ "/revision/"
+ (assq-ref
+ revisions
+ (if (string=? param "base_commit")
+ 'base
+ 'target)))))
+ ,(cond
+ ((eq? error 'unknown-commit)
+ (string-append
+ (if (string=? param "base_commit")
+ "Base revision "
+ "Target revision ")
+ "unknown to the data service."))
+ ((member error
+ '(yet-to-process-revision
+ failed-to-process-revision))
+ (simple-format
+ #f "~A to process ~A"
+ (if (eq? error 'yet-to-process-revision)
+ "Yet"
+ "Failed")
+ (if (string=? param "base_commit")
+ "base revision (from master branch)"
+ "target revision")))
+ (else
+ (string-append
+ "Error with "
+ (if (string=? param "base_commit")
+ "base revision."
+ "target revision.")))))))))))
+ params)))
+ '()))))))))