Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
"Current Pivotal Iteration" Script
#! /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