git.fiddlerwoaroof.com
jira-api.lisp
f9607eae
 ;;;; jira-api.lisp
 (in-package #:jira-api)
 
9cc3714b
 (defun get-filter (auth filter &rest r &key (expand "subscriptions[:-5]"))
   (declare (ignore expand))
   (apply 'api-get-call auth (format nil "filter/~d" filter) r))
 
 (defun get-issues (auth &key jql)
   (if jql
       (api-get-call auth "search" "jql" jql)
       (api-get-call auth "search")))
 
 (defmacro jql (auth &body jql)
   `(api-get-call ,auth "search" "jql"
                  ,(apply #'serapeum:concat jql)))
 
 (defun run-filter (auth filter)
   (let ((jql (gethash "jql" (yason:parse (get-filter auth filter)))))
     (get-issues auth :jql jql)))
f9607eae
 
 (defun get-issue (auth key &rest params &key expand)
   (declare (ignore expand))
   (apply 'api-get-call auth (format nil "issue/~a" key) params))
 
9cc3714b
 (defun get-board-issues (auth key &rest params &key expand)
   (declare (ignore expand))
   (apply 'api-get-call auth (format nil "board/~a/issue" key) params))
 
f9607eae
 (defun get-projects (auth)
   (api-get-call auth "issue/createmeta"))
 
 (defun make-issue (project-key summary &key (description nil description-p) (issue-type "Bug"))
   (let* ((issue (make-hash-table :test 'equal))
          (project (alist-string-hash-table `(("key" . ,project-key))))
          (issue-type (alist-string-hash-table `(("name" . ,issue-type)))))
     (setf (gethash "fields" issue)
           (alist-string-hash-table
             `(("project" . ,project)
               ("summary" . ,summary)
               ,@(when description-p
                   (list
                     (cons "description" description)))
               ("issuetype" . ,issue-type))))
     issue))
 
 (defun post-issue (auth issue)
   (let-each (:be *)
     issue
     (with-output-to-string (s)
       (yason:encode * s))
     (api-post-call auth "issue" *)))
 
 (defun post-issue-from-fields (auth project-key summary &key
                         (description nil description-p)
                         (issue-type nil issue-type-p))
   (let ((optional-arguments '()))
     (when issue-type-p
       (push issue-type optional-arguments))
     (when description-p
       (push description optional-arguments))
 
     (let-each (:be *)
       (apply #'make-issue project-key summary optional-arguments)
       (post-issue auth *))))
 
 (defun read-issue (&optional (iostream *query-io*))
   (let ((project-key (prompt :project-key iostream))
         (summary (prompt :summary iostream))
         (description (optional-prompt iostream :description "Add a description? ")))
     (apply #'make-issue project-key summary
            (list*
              (when description
                (list description))))))
 
 (defun show-person (person title)
0db897a4
   (format t "~&~4t~a: ~a~%" title (show person)))
f9607eae
 
 (defun show-labels (labels)
   (format t "~&~4tLabels: ~{~a~}~%" (coerce labels 'list)))
 
 (defun classify-issues (sheeple-issues &optional (classify-by '(status name)))
   (sheeple:with-properties (issues) sheeple-issues
0db897a4
     (loop with classes = (make-hash-table :test 'equalp)
           for issue across issues
9fbca987
           do (ensure-parent issue =issue=)
0db897a4
           do (loop for classification in classify-by
                    for thing = (sheeple:property-value (fields issue) classification)
                        then (sheeple:property-value thing classification)
                    finally (push issue (gethash thing classes)))
           finally (return classes))))
f9607eae
 
9cc3714b
 (defun status-to-num (status)
   (string-case (string-downcase status)
     ("open" 0)
     ("in progress" 1)
     ("needs qr" 2)
     ("needs demo" 3)
     ("closed" 4)
     (t 5)))
 
 (defun sort-issues-by-status (sheeple-issues)
   (prog1 sheeple-issues
     (sheeple:with-properties (issues) sheeple-issues
       (setf issues
             (sort issues #'< :key (op (status-to-num (name (status (fields _))))))))))
 
 (defun show-issue-short (issue &optional (stream t))
0db897a4
   (sheeple:with-properties (key self) issue
     (let* ((fields (fields issue))
            (status (name (status fields)))
            (summary (summary fields)))
9fbca987
 
9cc3714b
       (format stream "~&~a (~a) <~a>~%"
9fbca987
               key
               status 
               (puri:merge-uris (format nil "/browse/~a" (key issue))
                                *hostname*))
 
9cc3714b
       (show-summary summary stream)
       (fresh-line stream))))
 
 (defun map-issues (fun sheeple-issues)
   (sheeple:with-properties (issues) sheeple-issues
     (loop for issue across issues
           do (ensure-parent issue =issue=)
           collect (funcall fun issue))))
f9607eae
 
0db897a4
 (defun show-issues (sheeple-issues)
   (sheeple:with-properties (issues) sheeple-issues
     (loop for issue across issues
           do (ensure-parent issue =issue=)
           do (show-issue-short issue))))
f9607eae
 
0db897a4
 (defun print-on-own-line (str)
   (format t "~&~a~&" str))
f9607eae
 
 (defun show-projects (projects)
   (sheeple:with-properties (projects) projects
     (loop for project across projects
0db897a4
           do (ensure-parent project =project=)
           do (print-on-own-line (show project)))))
9cc3714b
 
 (defun get-points-for-issues (count start)
   (loop with end = (+ count start)
      for batch-start from start to end by 50
      for batch-count = (min (- end batch-start)
                             50)
      append (map 'list #'points
                  (issues
                   (json2sheeple
                    (get-issues *auth* :jql
                                (format nil "issueKey in (~{CJPM-~a~^, ~})"
                                        (alexandria:iota batch-count
                                                         :start batch-start)))
                    =issues=)))))