aboutsummaryrefslogtreecommitdiff
path: root/guix-qa-frontpage/guix-data-service.scm
diff options
context:
space:
mode:
Diffstat (limited to 'guix-qa-frontpage/guix-data-service.scm')
-rw-r--r--guix-qa-frontpage/guix-data-service.scm286
1 files changed, 180 insertions, 106 deletions
diff --git a/guix-qa-frontpage/guix-data-service.scm b/guix-qa-frontpage/guix-data-service.scm
index 9bf7997..8540524 100644
--- a/guix-qa-frontpage/guix-data-service.scm
+++ b/guix-qa-frontpage/guix-data-service.scm
@@ -4,22 +4,33 @@
#:use-module (srfi srfi-71)
#:use-module (ice-9 match)
#:use-module (ice-9 exceptions)
+ #:use-module (ice-9 binary-ports)
#:use-module (web uri)
#:use-module (web client)
#:use-module (web response)
#:use-module (rnrs bytevectors)
#:use-module (zlib)
#:use-module (json)
+ #:use-module (fibers)
+ #:use-module (knots timeout)
+ #:use-module (knots non-blocking)
#:use-module ((guix-build-coordinator utils fibers) #:select (retry-on-error))
#:use-module (guix-qa-frontpage utils)
#:use-module (guix-qa-frontpage patchwork)
#:use-module (guix-qa-frontpage manage-patch-branches)
- #:export (&guix-data-service-error
+ #:export (%data-service-url-base
+ %data-service-guix-repository-id
+
+ &guix-data-service-error
guix-data-service-error?
guix-data-service-error-response-body
guix-data-service-error-response-code
+ guix-data-service-error-url
guix-data-service-error->sexp
+ guix-data-service-error-summary
+ guix-data-service-error-sexp->error
+ guix-data-service-error-invalid-query?
guix-data-service-request
@@ -51,84 +62,122 @@
package-reproducibility-url))
+(define %data-service-url-base
+ "https://data.qa.guix.gnu.org")
+
+(define %data-service-guix-repository-id 1)
+
(define-exception-type &guix-data-service-error &error
make-guix-data-service-error
guix-data-service-error?
(response-body guix-data-service-error-response-body)
- (response-code guix-data-service-error-response-code))
+ (response-code guix-data-service-error-response-code)
+ (url guix-data-service-error-url))
(define (guix-data-service-error->sexp 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)
- ((string=? message "unknown commit")
- 'unknown-commit)
- (else
- 'unknown-error))))))))))
- (assoc-ref
- (guix-data-service-error-response-body exn)
- "query_parameters")))))
-
-;; Returns the port as well as the raw socket
-(define* (open-socket-for-uri* uri
- #:key (verify-certificate? #t))
- (define tls-wrap
- (@@ (web client) tls-wrap))
-
- (define https?
- (eq? 'https (uri-scheme uri)))
-
- (define plain-uri
- (if https?
- (build-uri
- 'http
- #:userinfo (uri-userinfo uri)
- #:host (uri-host uri)
- #:port (or (uri-port uri) 443)
- #:path (uri-path uri)
- #:query (uri-query uri)
- #:fragment (uri-fragment uri))
- uri))
-
- (let ((s (open-socket-for-uri plain-uri)))
- (values
- (if https?
- (tls-wrap s (uri-host uri)
- #:verify-certificate? verify-certificate?)
- s)
- s)))
+ (cond
+ ((string=? (or (assoc-ref (guix-data-service-error-response-body exn)
+ "error")
+ "")
+ "invalid query")
+ `((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)
+ ((string=? message "unknown commit")
+ 'unknown-commit)
+ (else
+ 'unknown-error))))))))))
+ (assoc-ref
+ (guix-data-service-error-response-body exn)
+ "query_parameters")))))
+ (else
+ `((exception . guix-data-service-exception)
+ (body . ,(guix-data-service-error-response-body exn))
+ (url . ,(guix-data-service-error-url exn))))))
+
+(define (guix-data-service-error-summary exn)
+ (cond
+ ((string=? (or (assoc-ref (guix-data-service-error-response-body exn)
+ "error")
+ "")
+ "invalid query")
+ (string-join
+ (filter-map
+ (match-lambda
+ ((param . val)
+ (and=>
+ (assoc-ref val "invalid_value")
+ (lambda (value)
+ (let ((message
+ (assoc-ref val "message")))
+ (simple-format
+ #f
+ "~A: ~A"
+ param
+ ;; 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)
+ ((string=? message "unknown commit")
+ 'unknown-commit)
+ (else
+ 'unknown-error))))))))
+ (assoc-ref
+ (guix-data-service-error-response-body exn)
+ "query_parameters"))
+ ", "))
+ (else
+ (simple-format #f "~A" (guix-data-service-error-response-body exn)))))
+
+(define (guix-data-service-error-sexp->error sexp)
+ (make-guix-data-service-error
+ (if (eq? (assq-ref sexp 'exception)
+ 'guix-data-service-invalid-parameters)
+ `(("error" . "invalid-query")
+ ,@sexp)
+ sexp)
+ #f
+ #f))
+
+(define (guix-data-service-error-invalid-query? exn)
+ (and
+ (guix-data-service-error? exn)
+ (string=?
+ (or (assoc-ref (guix-data-service-error-response-body exn)
+ "error")
+ "")
+ "invalid-query")))
(define* (guix-data-service-request url #:key (retry-times 0) (retry-delay 5))
(define (make-request)
(let ((port
- socket
- (open-socket-for-uri* (string->uri url))))
-
- ;; This can't be done earlier as tls-wrap/guile-gnutls doesn't support
- ;; handshake on a non blocking socket
- (let ((flags (fcntl socket F_GETFL)))
- (fcntl socket F_SETFL (logior O_NONBLOCK flags)))
+ (non-blocking-open-socket-for-uri (string->uri url))))
(let ((response
body
@@ -137,35 +186,49 @@
'((accept-encoding . ((1 . "gzip"))))
#:streaming? #t
#:port port)))
- (if (eq? (response-code response)
- 404)
- #f
- (let ((json-body
- (match (response-content-encoding response)
- (('gzip)
- ;; Stop fibers from triggering dynamic-wind in (zlib)
- (call-with-blocked-asyncs
- (lambda ()
- (call-with-zlib-input-port
- body
- json->scm
- #:format 'gzip))))
- (_
- (json->scm body)))))
- (if (or (> (response-code response)
- 400)
- (assoc-ref json-body "error"))
- (raise-exception
- (make-guix-data-service-error json-body
- (response-code response)))
- (values json-body
- response)))))))
+ (cond
+ ((eq? (response-code response) 404)
+ #f)
+ ((not (eq? (first (response-content-type response))
+ 'application/json))
+ (raise-exception
+ (make-guix-data-service-error
+ (utf8->string
+ (match (response-content-encoding response)
+ (('gzip)
+ (call-with-zlib-input-port*
+ body
+ get-bytevector-all
+ #:format 'gzip))
+ (_
+ (get-bytevector-all body))))
+ (response-code response)
+ url)))
+ (else
+ (let ((json-body
+ (match (response-content-encoding response)
+ (('gzip)
+ (call-with-zlib-input-port*
+ body
+ json->scm
+ #:format 'gzip))
+ (_
+ (json->scm body)))))
+ (if (or (> (response-code response)
+ 400)
+ (assoc-ref json-body "error"))
+ (raise-exception
+ (make-guix-data-service-error json-body
+ (response-code response)
+ url))
+ (values json-body
+ response))))))))
(if (= 0 retry-times)
(make-request)
(retry-on-error
(lambda ()
- (with-fibers-port-timeouts
+ (with-port-timeouts
make-request
#:timeout 120))
#:times retry-times
@@ -179,12 +242,13 @@
#:key system target
no-build-from-build-server)
(string-append
- "https://data.qa.guix.gnu.org/revision/"
+ %data-service-url-base
+ "/revision/"
commit
"/package-derivations.json?"
"system=" system
"&target=" target
- "&field=" "(no-additional-fields)"
+ "&field=" "no-additional-fields"
"&all_results=" "on"
(if no-build-from-build-server
(string-append
@@ -193,7 +257,8 @@
(define* (compare-package-derivations-url base-and-target-refs #:key systems)
(string-append
- "https://data.qa.guix.gnu.org/compare/package-derivations.json?"
+ %data-service-url-base
+ "/compare/package-derivations.json?"
"base_commit=" (assq-ref base-and-target-refs 'base)
"&target_commit=" (assq-ref base-and-target-refs 'target)
(string-join
@@ -206,7 +271,8 @@
(define* (compare-package-cross-derivations-url base-and-target-refs #:key systems)
(string-append
- "https://data.qa.guix.gnu.org/compare/package-derivations.json?"
+ %data-service-url-base
+ "/compare/package-derivations.json?"
"base_commit=" (assq-ref base-and-target-refs 'base)
"&target_commit=" (assq-ref base-and-target-refs 'target)
(string-join
@@ -225,7 +291,8 @@
(define* (revision-comparison-url base-and-target-refs #:key (json? #t))
(string-append
- "https://data.qa.guix.gnu.org/compare"
+ %data-service-url-base
+ "/compare"
(if json? ".json" "")
"?"
"base_commit=" (assq-ref base-and-target-refs 'base)
@@ -235,7 +302,8 @@
(guix-data-service-request url))
(define (list-branches-url repository-id)
- (simple-format #f "https://data.qa.guix.gnu.org/repository/~A.json"
+ (simple-format #f "~A/repository/~A.json"
+ %data-service-url-base
repository-id))
(define (list-branches url)
@@ -248,8 +316,9 @@
(let ((json-body
(guix-data-service-request
(string-append
- "https://data.qa.guix.gnu.org"
- "/repository/2"
+ %data-service-url-base
+ "/repository/"
+ (number->string %data-service-guix-repository-id)
"/branch/" branch
"/latest-processed-revision.json"))))
(assoc-ref
@@ -259,7 +328,8 @@
(define (branch-revisions-url repository-id branch-name)
(simple-format
#f
- "https://data.qa.guix.gnu.org/repository/~A/branch/~A.json"
+ "~A/repository/~A/branch/~A.json"
+ %data-service-url-base
repository-id
branch-name))
@@ -272,7 +342,8 @@
(define* (revision-details-url commit)
(simple-format
#f
- "https://data.qa.guix.gnu.org/revision/~A.json"
+ "~A/revision/~A.json"
+ %data-service-url-base
commit))
(define (revision-details url)
@@ -281,7 +352,8 @@
(define* (revision-system-tests-url commit #:key (system "x86_64-linux"))
(simple-format
#f
- "https://data.qa.guix.gnu.org/revision/~A/system-tests.json?system=~A"
+ "~A/revision/~A/system-tests.json?system=~A"
+ %data-service-url-base
commit
system))
@@ -294,7 +366,8 @@
(define* (package-substitute-availability-url commit)
(simple-format
#f
- "https://data.qa.guix.gnu.org/revision/~A/package-substitute-availability.json"
+ "~A/revision/~A/package-substitute-availability.json"
+ %data-service-url-base
commit))
(define (package-substitute-availability url)
@@ -307,5 +380,6 @@
(define* (package-reproducibility-url commit)
(simple-format
#f
- "https://data.qa.guix.gnu.org/revision/~A/package-reproducibility.json"
+ "~A/revision/~A/package-reproducibility.json"
+ %data-service-url-base
commit))