Created
February 4, 2017 01:05
-
-
Save mjamesruggiero/1731a8f6370ccb107d2761ebf3767edd to your computer and use it in GitHub Desktop.
"Current Pivotal Iteration" Script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env racket | |
#lang racket | |
;;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
;; pivotal | |
;; | |
;; what it does: pulls the current iteration, | |
;; echoes short story summary | |
;; binned by the first owner's name | |
;; | |
;; arguments: API token and team project-id | |
;;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
(require json | |
net/url | |
racket/list | |
racket/format | |
racket/port) | |
(define (usage) | |
(printf "Arguments needed: <token> <project-id>\n")) | |
;;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
;; api | |
;;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
(struct story | |
(name owned-by-id kind current-state owner-name) #:transparent) | |
(define PIVOTAL-URI | |
"https://www.pivotaltracker.com/services/v5/projects") | |
(define ITERATION-PATH | |
"/iterations?scope=current") | |
(define MEMBERSHIPS-PATH | |
"/memberships") | |
(define (pivotal-url project-id) | |
(define url-string | |
(string-append PIVOTAL-URI "/" project-id ITERATION-PATH)) | |
(string->url url-string)) | |
(define (members-url project-id) | |
(define url-string | |
(string-append PIVOTAL-URI "/" project-id MEMBERSHIPS-PATH)) | |
(string->url url-string)) | |
(define (pivotal-header token) | |
(list (string-append "X-TrackerToken:" token))) | |
(define (fetch url header) | |
(define in (get-pure-port url header)) | |
(define out (open-output-string)) | |
(copy-port in out) | |
(get-output-string out)) | |
(define (api-call url header) | |
(fetch url header)) | |
(define (iteration-stories iteration) | |
(hash-ref (car (string->jsexpr iteration)) 'stories)) | |
(define (story-node->story node users) | |
(story | |
(hash-ref node 'name) | |
(hash-ref node 'owned_by_id) | |
(hash-ref node 'kind) | |
(hash-ref node 'current_state) | |
(hash-ref users (hash-ref node 'owned_by_id)))) | |
(define (extract-stories iteration memberships) | |
(let ([users (extract-users (string->jsexpr memberships))]) | |
(map (λ [s] | |
(story-node->story s users)) | |
(iteration-stories iteration)))) | |
(define (extract-users nodes) | |
(let ([m (make-hash)]) | |
(for ([n nodes]) | |
(let* ([person (hash-ref n 'person)] | |
[id (hash-ref person 'id)] | |
[name (hash-ref person 'name)]) | |
(hash-set! m id name))) | |
m)) | |
(define (grouped stories) | |
(group-by (λ (s) | |
(story-owner-name s)) | |
stories)) | |
;;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
;; output | |
;;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
;; TODO allow optional command line arg | |
;; that allows you to write to local file | |
(define (api->file url header filename) | |
(call-with-output-file filename | |
(λ (out) | |
(write (api-call url header) out)) | |
#:mode 'text | |
#:exists 'replace)) | |
(define (print-grouped grouped) | |
(let ([formatter | |
(λ (story) | |
(~a (story-current-state story) | |
" - " (story-owner-name story) | |
" - " (story-name story) | |
#:max-width 90 #:limit-marker "..."))]) | |
(for ([g grouped]) | |
(for ([s g]) | |
(printf "~a\n" (formatter s)))))) | |
;;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
;; command-line | |
;;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
(define (runner args) | |
(let* ([token | |
(vector-ref args 0)] | |
[project-id | |
(vector-ref args 1)] | |
[header | |
(pivotal-header token)] | |
[iteration | |
(api-call (pivotal-url project-id) header)] | |
[users | |
(api-call (members-url project-id) header)] | |
[stories | |
(grouped (extract-stories iteration users))]) | |
(print-grouped stories))) | |
(define (main) | |
(let ([cli-args | |
(current-command-line-arguments)]) | |
(if (> 2 (vector-length cli-args)) | |
(usage) | |
(runner cli-args)))) | |
(main) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment