Generalize the GitLab API client.

This commit is contained in:
Ray Miller 2025-06-18 09:56:14 +01:00
parent c3e133073a
commit a2e936e608

View file

@ -2,9 +2,9 @@
--no-auto-compile -e main -s --no-auto-compile -e main -s
!# !#
(use-modules (ice-9 exceptions) (use-modules (ice-9 binary-ports)
(ice-9 exceptions)
(ice-9 match) (ice-9 match)
(ice-9 textual-ports)
(json) (json)
(srfi srfi-1) (srfi srfi-1)
(srfi srfi-26) (srfi srfi-26)
@ -13,10 +13,12 @@
(web response) (web response)
(web uri)) (web uri))
(define gitlab-token (string-trim-right (getenv "GITLAB_TOKEN"))) (define gitlab-token (string-trim (getenv "GITLAB_TOKEN")))
(define base-url "https://gitlab.com/api/v4") (define base-url "https://gitlab.com/api/v4")
(define (encode-query alist) (define (encode-query alist)
"Encode an association list as a query string. The keys should be symbols and the
values strings or #f, in which case the parameter is skipped."
(fold (match-lambda* (fold (match-lambda*
(((k . v) s) (((k . v) s)
(if v (if v
@ -32,10 +34,6 @@
(define (json-response? res) (define (json-response? res)
(eq? 'application/json (car (response-content-type res)))) (eq? 'application/json (car (response-content-type res))))
(define (text-response? res)
(string-prefix? "text/"
(symbol->string (car (response-content-type res)))))
(define (json-ok? res) (define (json-ok? res)
(and (= 200 (response-code res)) (and (= 200 (response-code res))
(json-response? res))) (json-response? res)))
@ -47,28 +45,20 @@
(status-code api-error-status-code) (status-code api-error-status-code)
(body api-error-body)) (body api-error-body))
(define-syntax check-api-response (define* (api-call method endpoint #:key query payload (ok? json-ok?) (post-proc identity))
(syntax-rules () (let* ((res body (method (if query
((check-api-response endpoint res body-port) (string-append base-url endpoint "?" (encode-query query))
(check-api-response endpoint res body-port (<= 100 (response-code res) 399))) (string-append base-url endpoint))
((check-api-response endpoint res body-port ok?) #:headers `((private-token . ,gitlab-token)
(unless ok? (content-type . (application/json (charset . "utf-8"))))
(let ((body (cond #:body (if payload (scm->json payload) #f)))
((json-response? res) (json->scm body-port)) (body (if (json-response? res) (call-with-input-bytevector body json->scm) body)))
((text-response? res) (get-string-all body-port)) (if (ok? res)
(else "<binary response body>")))) (post-proc body)
(close-port body-port) (raise-exception (make-api-error endpoint (response-code res) body)))))
(raise-exception (make-api-error endpoint (response-code res) body)))))))
(define (list-merge-requests params) (define (list-merge-requests params)
(let ((res body-port (http-get (string-append base-url "/merge_requests?" (encode-query params)) (api-call http-get "/merge_requests" #:query params #:post-proc vector->list))
#:headers `((private-token . ,gitlab-token))
#:streaming? #t)))
(check-api-response "list-merge-requests" res body-port json-ok?)
(let ((body (json->scm body-port)))
(close-port body-port)
(vector->list body))))
(define (field-equal? field-name value) (define (field-equal? field-name value)
(lambda (alist) (lambda (alist)