hubot-scripts
Version:
Allows you to opt in to a variety of scripts
131 lines (121 loc) • 5.43 kB
text/coffeescript
# Description:
# Rally information for bugs, stories, and users
#
# Dependencies:
# None
#
# Configuration:
# HUBOT_RALLY_USERNAME
# HUBOT_RALLY_PASSWORD
#
# Commands:
# hubot rally me <defect id | task id | story id> - Lookup a task, story or defect from Rally
#
# Notes:
# Since Rally supports rich text for description fields, it will come back as HTML
# to pretty print this we can run it through lynx. Make sure you have lynx installed
# and PATH accessible, otherwise we will degrade to just showing the html description.
# ENV Variables Required:
#
# Author:
# brianmichel
exec = require('child_process').exec
user = process.env.HUBOT_RALLY_USERNAME
pass = process.env.HUBOT_RALLY_PASSWORD
api_version = 1.29
module.exports = (robot) ->
robot.respond /(rally)( me)? (.*)/i, (msg) ->
if user && pass
switch msg.match[3].toUpperCase().substring(0,2)
when "DE" then bugRequest msg, msg.match[3], (string) ->
msg.send string
when "TA" then taskRequest msg, msg.match[3], (string) ->
msg.send string
when "US" then storyRequest msg, msg.match[3], (string) ->
msg.send string
else msg.send "Uhh, that doesn't work"
else
msg.send "You need to set HUBOT_RALLY_USERNAME & HUBOT_RALLY_PASSWORD before making requests!"
bugRequest = (msg, defectId, cb) ->
query_string = '/defect.js?query=(FormattedId%20=%20'+defectId+')' + '&fetch=true'
rallyRequest msg, query_string, (json) ->
if json && json.QueryResult.TotalResultCount > 0
getLinkToItem msg, json.QueryResult.Results[0], "defect"
description = "No Description"
if json.QueryResult.Results[0].Description
prettifyDescription json.QueryResult.Results[0].Description, (output) ->
description = output
return_array = [
"#{json.QueryResult.Results[0].FormattedID} - #{json.QueryResult.Results[0]._refObjectName}"
"Owner - #{ if json.QueryResult.Results[0].Owner then json.QueryResult.Results[0].Owner._refObjectName else "No Owner" }"
"Project - #{ if json.QueryResult.Results[0].Project then json.QueryResult.Results[0].Project._refObjectName else "No Project" }"
"Severity - #{json.QueryResult.Results[0].Severity}"
"State - #{json.QueryResult.Results[0].State}"
"#{description}"
]
cb return_array.join("\n")
else
cb "Aww snap, I couldn't find that bug!"
taskRequest = (msg, taskId, cb) ->
query_string = '/task.js?query=(FormattedId%20=%20'+taskId+')' + '&fetch=true'
rallyRequest msg, query_string, (json) ->
if json && json.QueryResult.TotalResultCount > 0
getLinkToItem msg, json.QueryResult.Results[0], "task"
return_array = [
"#{json.QueryResult.Results[0].FormattedID} - #{json.QueryResult.Results[0].Name}"
"Owner - #{ if json.QueryResult.Results[0].Owner then json.QueryResult.Results[0].Owner._refObjectName else "No Owner" }"
"Project - #{ if json.QueryResult.Results[0].Project then json.QueryResult.Results[0].Project._refObjectName else "No Project" }"
"State - #{json.QueryResult.Results[0].State}"
"Feature - #{if json.QueryResult.Results[0].WorkProduct ? json.QueryResult.Results[0].WorkProduct._refObjectName else "Not associated with any feature"}"
]
cb return_array.join("\n")
else
cb "Aww snap, I couldn't find that task!"
storyRequest = (msg, storyId, cb) ->
query_string = '/hierarchicalrequirement.js?query=(FormattedId%20=%20'+storyId+')' + '&fetch=true'
rallyRequest msg, query_string, (json) ->
if json && json.QueryResult.TotalResultCount > 0
getLinkToItem msg, json.QueryResult.Results[0], "userstory"
description = "No Description"
prettifyDescription json.QueryResult.Results[0].Description, (output) ->
description = output || description
return_array = [
"#{json.QueryResult.Results[0].FormattedID} - #{json.QueryResult.Results[0].Name}"
"Owner - #{ if json.QueryResult.Results[0].Owner then json.QueryResult.Results[0].Owner._refObjectName else "No Owner" }"
"Project - #{ if json.QueryResult.Results[0].Project then json.QueryResult.Results[0].Project._refObjectName else "No Project" }"
"ScheduleState - #{json.QueryResult.Results[0].ScheduleState}"
"#{description}"
]
cb return_array.join("\n")
else
cb "Aww snap, I couldn't find that story!"
rallyRequest = (msg, query, cb) ->
rally_url = 'https://rally1.rallydev.com/slm/webservice/' + api_version + query
basicAuthRequest msg, rally_url, (json) ->
cb json
basicAuthRequest = (msg, url, cb) ->
auth = 'Basic ' + new Buffer(user + ':' + pass).toString('base64');
msg.http(url)
.headers(Authorization: auth, Accept: 'application/json')
.get() (err, res, body) ->
json_body = null
switch res.statusCode
when 200 then json_body = JSON.parse(body)
else json_body = null
cb json_body
getLinkToItem = (msg, object, type) ->
project = if object && object.Project then object.Project else null
if project
objectId = object.ObjectID
jsPos = project._ref.lastIndexOf ".js"
lastSlashPos = project._ref.lastIndexOf "/"
projectId = project._ref[(lastSlashPos+1)..(jsPos-1)]
msg.send "https://rally1.rallydev.com/slm/rally.sp#/#{projectId}/detail/#{type}/#{objectId}"
else
#do nothing
prettifyDescription = (html_description, cb) ->
child = exec "echo \"#{html_description}\" | lynx -dump -stdin", (error, stdout, stderr) ->
return_text = html_description
if !error
return_text = stdout
cb return_text