Skip to content

Instantly share code, notes, and snippets.

@dalehamel
Last active August 29, 2015 14:13
Show Gist options
  • Save dalehamel/ce9bfe7c8a2f4addb03a to your computer and use it in GitHub Desktop.
Save dalehamel/ce9bfe7c8a2f4addb03a to your computer and use it in GitHub Desktop.
Victorops coffeescript WIP
# Description:
# This script can be used to interact with VictorOps schedules, and page VictorOps teams
#
# Configuration:
# HUBOT_VICTOROPS_USER - The username of the hubot user in the VictorOps org
# HUBOT_VICTOROPS_PASS - The password of the hubot user in the VictorOps org
# HUBOT_VICTOROPS_REST - The API token to use
# Commands:
# hubot oncall - Lists the teams you can check (working)
# hubot oncall <team> - Shows who is on-call right now for a team (working but only for the first rotation in a schedule due to victorops API bug)
# hubot page - Lists the teams you can page (working)
# hubot page <team> [message] - Pages the team specified
moment = require 'moment'
module.exports = (robot) ->
# maybe move this out into a config variable but whatever good enough for now
aliases =
"operations" : [ "op","ops","operation"]
class VictorOps
constructor: ->
@hubot_user = process.env.HUBOT_VICTOROPS_USER
@hubot_pass = process.env.HUBOT_VICTOROPS_PASS
@vo_rest = process.env.HUBOT_VICTOROPS_REST
@sched_api = "https://#{@hubot_user}:#{@hubot_pass}@portal.victorops.com/api/v1/org/shopify-inc/teams?days_forward=1"
@pager_api = "https://alert.victorops.com/integrations/generic/20131114/alert/#{@vo_rest}"
# Queries VictorOps for the oncall schedule
get_schedule: (callback) ->
robot.http(@sched_api).get() (err,res,body) ->
callback? JSON.parse(body)
# Get an object containing the current oncall data for each team
parse_schedule: (schedule) ->
oncall = {}
# At the minimum, add all teams to the oncall object
oncall[team["slug"]] = {} for team in schedule
for team in schedule
# A shift that has an on
current_shift = shift for shift in team["oncall"] when "oncall" of shift
# Add the information for the current shift to the oncall object
if current_shift?
user = current_shift["oncall"]
name = current_shift["shift_name"]
end_stamp = roll["until"] for roll in current_shift["rolls"] when roll["change"] == current_shift["shift_roll"]
end = moment.unix(end_stamp / 1000).format('YYYY-MM-DD HH:mm:ss')
oncall[team["slug"]]["primary"] = { user : user, shift : name, end: end} # FIXME VictorOps isn't returning all rotations for a schedule
current_shift = null
return oncall
page_team: (team, message, user, cb) ->
response = "Paged!"
robot.victorops.get_schedule (schedule) ->
oncall = robot.victorops.parse_schedule schedule
# If the team requested to be paged doesn't exist, abort
response = "I'm sorry #{user}, I don't know about the #{team} team" unless team of oncall
cb? response unless team of oncall
return unless team of oncall
# Build the webook payload
payload =
entity_id: 'hubot_page'
paged_by: user
message_type: 'CRITICAL'
state_message: message
entity_display_name: "#{user} manually paged via hubot: #{message}"
endpoint = "#{robot.victorops.pager_api}/#{team}"
# Send the payload
robot.http(endpoint)
.post(JSON.stringify(payload)) (err, res, body) ->
result = JSON.parse(body)
# Notify of any errors
response = "Sorry #{user}, I failed to page #{team} because: #{result["message"]}" unless result["result"] == "success"
cb? response
# Add the victorops object to the robot, so other scripts can page if needed
robot.victorops = new VictorOps
# A bit of a hack, allows for dereferencing aliase to a team
dealias = (alias) ->
return alias if alias of aliases
teams = ( team for team,teams_aliases of aliases when alias in teams_aliases)
return teams[0] if teams.length > 0
return alias if teams.length == 0
# Page a team, optionally supply a message
robot.respond /page\s+(\S+)(\s+)?(.+)?/, (msg) ->
alias = msg.match[1]
message = msg.match[3] or "No message provided"
team = dealias alias
robot.victorops.page_team team, message, msg.message.user.name, (response) ->
msg.send response
# Notify of who is on call
robot.respond /on(\s*)call\s+(\S+)/, (msg) ->
alias = msg.match[2]
team = dealias alias
robot.victorops.get_schedule (schedule) ->
oncall = robot.victorops.parse_schedule schedule
return msg.send "I'm sorry #{msg.message.user.name}, I don't know about the #{team} team" unless team of oncall
return msg.send "Uh oh #{msg.message.user.name}, it looks like no on is oncall for #{team} team" if Object.keys(oncall[team]).length == 0
msg.send """Hi #{msg.message.user.name}, the following users are oncall for the #{team} team:
#{( "#{rotation}: #{shift['user']} is on call for the #{shift['shift']} shift until #{shift['end']}" for rotation,shift of oncall[team]).join("\n")}
IMPORTANT: #{robot.name} did not page #{team}. Use #{robot.name} page #{team} [message]
"""
# Provide a list of teams with oncall schedules
robot.respond /(oncall|page)$/i, (msg) ->
action = msg.match[1]
robot.victorops.get_schedule (schedule) ->
oncall = robot.victorops.parse_schedule schedule
teams= "#{("#{team}#{if team of aliases then " (#{aliases[team].join("|")})" else ""}" for team,rotations of oncall).join(', ')}"
msg.send """
Hi #{msg.message.user.name}, which oncall team did you need?
I know about these teams: #{teams}
Usage: #{robot.name} #{action} <team>
"""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment