Skip to content

Instantly share code, notes, and snippets.

@lightstrike
Created February 28, 2015 22:42
Show Gist options
  • Select an option

  • Save lightstrike/6036d676e344a6be4b7b to your computer and use it in GitHub Desktop.

Select an option

Save lightstrike/6036d676e344a6be4b7b to your computer and use it in GitHub Desktop.
Pivotal Tracker Developer Focus Metric
# -*- coding: utf-8 -*-
"""
Calculates the following 'Developer Focus' metric using
data from the Pivotal Tracker API:
# unique developers actively working on active projects /
Open stories ("started" state) from active projects
For this first pass, the IDs of active projects and
developers are set as environment variables.
In the future, it may be possible to determine these
values dynamically using the Pivotal Tracker API,
though it doesn't appear to be possible as of 3.2015.
"""
from os import environ
import requests
import json
def get_env_setting(setting, default=None):
"""
Get the environment setting or return exception
"""
try:
var = environ.get(setting, default) if default else environ[setting]
return var
except KeyError:
error_msg = "Set the %s env variable" % setting
raise KeyError(error_msg)
def get_env_list(setting, structure=int, delimiter=','):
"""
converts delimited string variable into a Python list
"""
env_variable = get_env_setting(setting).replace(" ", "")
return map(structure, env_variable.split(delimiter))
# Get API token for Pivotal Tracker
# Found at https://www.pivotaltracker.com/profile
PIVOTAL_TOKEN = get_env_setting('PIVOTAL_API_TOKEN')
TRACKER_HEADERS = {'X-TrackerToken': PIVOTAL_TOKEN}
# Get active project and developer IDs for API lookups
ACTIVE_PROJECTS = get_env_list('ACTIVE_PIVOTAL_PROJECTS')
ACTIVE_DEVELOPERS = get_env_list('ACTIVE_PIVOTAL_DEVELOPERS')
# Set Pivotal Tracker Endpoints
# https://www.pivotaltracker.com/help/api/rest/v5#Stories
OPEN_STORIES_URL = "https://www.pivotaltracker.com/services/v5/projects/{project_id}/stories?with_state=started"
PROJECTS_URL = "https://www.pivotaltracker.com/services/v5/projects"
# Set Slack endpoint for posting metric (optional)
SLACK_METRICS_URL = get_env_setting('SLACK_METRICS_URL', 'console')
SLACK_METRICS_CHANNEL = get_env_setting('SLACK_METRICS_CHANNEL')
# Set metric inputs
active_developers = len(ACTIVE_DEVELOPERS)
total_open_stories = 0
def get_open_stories(project_id):
"""
return number of open stories given a
Pivotal Tracker project ID
"""
request_url = OPEN_STORIES_URL.format(project_id=project_id)
# https://www.pivotaltracker.com/help/api#Request_Authentication_and_CORS
stories_request = requests.get(request_url, headers=TRACKER_HEADERS)
return json.loads(stories_request.content)
for project in ACTIVE_PROJECTS:
"""
get open stories for all active projects and add to tally
If successful response, json.loads will return a list object,
if failed response, json.loads will return a dict object.
"""
open_stories = get_open_stories(project)
if type(open_stories) == list:
total_open_stories += len(open_stories)
else:
raise Exception("This request was not successful. Please try again later.")
# Calculate active project string for display
projects_request = requests.get(PROJECTS_URL, headers=TRACKER_HEADERS)
projects_json = json.loads(projects_request.content)
active_projects = [p['name'] for p in projects_json if p['id'] in ACTIVE_PROJECTS]
# calculate metric and
developer_focus = (float(active_developers)/float(total_open_stories))*100
metrics_text = ("Developer Focus: {focus_metric}% ({developers} "
"Developers / {stories} Open Stories) in {projects} "
"active projects ({active_projects}).").format(
focus_metric=developer_focus,
developers=active_developers,
stories=total_open_stories,
projects=len(active_projects),
active_projects=', '.join(active_projects)
)
# if SLACK_URL, post to SLACK room, otherwise just print to console
if not SLACK_METRICS_URL == 'console':
slack_payload = {
"channel": SLACK_METRICS_CHANNEL,
"username": "metricsbot",
"text": metrics_text,
"icon_emoji": ":chart:"
}
requests.post(SLACK_METRICS_URL, data=json.dumps(slack_payload), headers=TRACKER_HEADERS)
else:
print(metrics_text)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment