class Lita::Handlers::GithubPinger
Public Instance Methods
act_on_assign(body, response)
click to toggle source
# File lib/lita/handlers/github_pinger.rb, line 136 def act_on_assign(body, response) type = detect_type(body) if type.nil? puts "Neither pull request or issue detected, exiting..." return end puts "Detected that someone got assigned to a #{type.tr('_', ' ')}." assignee_login = body[type]["assignee"]["login"] assignee = find_engineer(github: assignee_login) puts "Looking up preferences..." should_notify = assignee[:github_preferences][:notify_about_assignment] if !should_notify puts "will not notify, preference for :github_preferences[:notify_about_assignment] is not true" return response end puts "#{assignee} determined as the assignee." url = body[type]["html_url"] message = "*Heads up!* You've been assigned to a #{type.tr('_', ' ')}:\n#{url}" puts "Sending DM to #{assignee}..." send_dm(assignee[:usernames][:slack], message) response end
act_on_build_failure(body, response)
click to toggle source
# File lib/lita/handlers/github_pinger.rb, line 86 def act_on_build_failure(body, response) commit_url = body["commit"]["html_url"] committer = find_engineer(github: body["commit"]["committer"]["login"]) puts "Detected a status failure for commit #{body["sha"]}" message = ":x: Your commit failed CI." message += "\n#{commit_url}" if committer frequency = if committer[:travis_preferences] committer[:travis_preferences][:frequency] else committer[:status_preferences][:frequency] end return if ["off", "only_passes"].include?(frequency) send_dm(committer[:usernames][:slack], message) else puts "Could not find configuration for GitHub username " + body["commit"]["committer"]["login"] end response end
act_on_build_success(body, response)
click to toggle source
# File lib/lita/handlers/github_pinger.rb, line 111 def act_on_build_success(body, response) commit_url = body["commit"]["html_url"] committer = find_engineer(github: body["commit"]["committer"]["login"]) puts "Detected a status success for commit #{body["sha"]}" message = ":white_check_mark: Your commit has passed CI." message += "\n#{commit_url}" if committer frequency = if committer[:travis_preferences] committer[:travis_preferences][:frequency] else committer[:status_preferences][:frequency] end return if ["off", "only_failures"].include?(frequency) send_dm(committer[:usernames][:slack], message) else puts "Could not find configuration for GitHub username " + body["commit"]["committer"]["login"] end response end
act_on_comment(body, response)
click to toggle source
# File lib/lita/handlers/github_pinger.rb, line 275 def act_on_comment(body, response) puts "Detected a comment. Extracting data... " comment_url = body["comment"]["html_url"] comment = body["comment"]["body"] context = body["pull_request"] || body["issue"] commenter = find_engineer(github: body["comment"]["user"]["login"]) pr_owner = find_engineer(github: context["user"]["login"]) lita_commenter = Lita::User.fuzzy_find(commenter[:usernames][:slack]) puts "Reacting to PR comment #{comment_url}" puts "Found commenter #{commenter}" puts "Found pr owner #{pr_owner}" # Sanity Checks - might be a new engineer around that hasn't set up # their config. engineers_to_ping = [] # automatically include the creator of the PR, unless he's # commenting on his own PR if commenter != pr_owner && ["all_discussion", nil].include?(pr_owner[:github_preferences][:frequency]) puts "PR owner was not the commenter, and has a :frequency of 'all_discussion' or nil" puts "Therefore, adding the PR owner to list of engineers to ping." engineers_to_ping << pr_owner end # Is anyone mentioned in this comment? if comment.include?("@") puts "Found @mentions in the body of the comment! Extracting usernames... " # get each @mentioned engineer in the comment mentions = comment .split("@")[1..-1] # "a @b @c d" => ["b ", "c d"] .map { |snip| snip.split(" ").first } # ["b ", "c d"] => ["b", "c"] .map { |name| name.gsub(/[^0-9a-z\-_]/i, '') } puts "Done. Got #{mentions}" puts "Converting usernames to engineers..." mentioned_engineers = mentions.map { |username| find_engineer(github: username) } puts "Done. Got #{mentioned_engineers}" # add them to the list of usernames to ping engineers_to_ping = engineers_to_ping.concat(mentioned_engineers).uniq.compact end puts "New list of engineers to ping: #{engineers_to_ping}." puts "Starting pinging process for each engineer..." engineers_to_ping.each do |engineer| puts "looking at #{engineer}'s preferences..'" next if engineer[:github_preferences][:frequency] == "off" case engineer[:github_preferences][:ping_location] when "dm", nil puts "Preference was either 'dm' or nil, so sending DM." private_message = "New PR comment from <@#{lita_commenter.id}|#{commenter[:usernames][:slack]}>:\n" private_message += "#{comment_url}\n#{comment}" send_dm(engineer[:usernames][:slack], private_message) when "eng-pr", "eng_pr" puts "Preference was either 'eng-pr' or 'eng_pr', so alerting #eng-pr." public_message = "@#{engineer[:usernames][:slack]}, new PR mention: " public_message += "#{comment_url}\n#{comment}" alert_eng_pr(public_message) end end puts "GitHub Hook successfully processed." response end
act_on_pr_labeled(body, response)
click to toggle source
# File lib/lita/handlers/github_pinger.rb, line 224 def act_on_pr_labeled(body, response) type = detect_type(body) puts "Detected that someone labeled a #{type.tr('_', ' ')}." if type.nil? puts "Neither pull request or issue detected, exiting..." return end if body["pull_request"]["labels"].none? { |label| label["name"].downcase.include?('review') } puts "Labels do not include a review label, exiting..." return end if config.enable_round_robin puts "round robin is enabled, selecting the next engineer.." chosen_reviewer = get_next_round_robin_reviewer pr_owner = find_engineer(github: body["pull_request"]["user"]["login"]) pr_owner = pr_owner[:usernames][:slack] unless pr_owner.nil? if chosen_reviewer === pr_owner update_next_round_robin_reviewer chosen_reviewer = get_next_round_robin_reviewer end puts "#{chosen_reviewer} determined as the reviewer." url = body[type]["html_url"] message_for_reviewer = "You're next in line to review a PR! Please review, or assign to an engineer with more context if you think you are unable to give a thorough review. \n#{url}" message_for_owner = "#{chosen_reviewer} has been notified via round-robin to review #{body["pull_request"]["html_url"]}" puts "Sending DM to #{chosen_reviewer}..." send_dm(chosen_reviewer, message_for_reviewer) if pr_owner puts "Notifying #{pr_owner} of assignment." send_dm(pr_owner, message_for_owner) else puts "Couldn't find a config for pr owner #{body["pull_request"]["user"]["login"]}. Make sure they are in the lita config!" puts "Skipping notifying PR owner of RR assignment." end update_next_round_robin_reviewer response end end
act_on_review_requested(body, response)
click to toggle source
# File lib/lita/handlers/github_pinger.rb, line 169 def act_on_review_requested(body, response) puts "Detected a review request." puts "looking at previously notified reviewers for this PR" pr = body["pull_request"] url = pr["html_url"] while redis.locked?("change-reviewers") puts "Redis is locked, waiting..." sleep 1 end redis.lock("change-reviewers") do |lock| puts "Redis lock aquired." notified_engineers = redis.get(REVIEW_REDIS_KEY + ":" + url) notified_engineers = if notified_engineers JSON.parse(notified_engineers) else [] end pr["requested_reviewers"].each do |reviewer| engineer = find_engineer(github: reviewer["login"]) if !engineer puts "Could not find engineer #{reviewer["login"]}" next end if notified_engineers.include?(reviewer["login"]) puts "#{reviewer["login"]} has already been notified to review PR, skipping..." next end puts "#{engineer} determined as a reviewer." puts "Looking up preferences..." should_notify = engineer[:github_preferences][:notify_about_review_requests] if !should_notify puts "will not notify, preference for :github_preferences[:notify_about_review_requests] is not true" else message = "You've been asked to review a pull request:\n#{url}" send_dm(engineer[:usernames][:slack], message) notified_engineers.push(reviewer["login"]) end end redis.set(REVIEW_REDIS_KEY + ":" + url, notified_engineers.to_json) end response end
alert_eng_pr(message)
click to toggle source
# File lib/lita/handlers/github_pinger.rb, line 374 def alert_eng_pr(message) puts "Alerting #eng-pr about content #{message[0..5]}... " room = Lita::Room.fuzzy_find("eng-pr") source = Lita::Source.new(room: room) robot.send_message(source, message) puts "Done." end
detect_type(body)
click to toggle source
# File lib/lita/handlers/github_pinger.rb, line 407 def detect_type(body) if body["pull_request"] "pull_request" elsif body["issue"] "issue" end end
find_engineer(slack: nil, github: nil, name: nil)
click to toggle source
# File lib/lita/handlers/github_pinger.rb, line 382 def find_engineer(slack: nil, github: nil, name: nil) if name return config.engineers[name] end config.engineers.values.select do |eng| if slack eng[:usernames][:slack] == slack elsif github eng[:usernames][:github] == github end end.first end
get_next_round_robin_reviewer()
click to toggle source
# File lib/lita/handlers/github_pinger.rb, line 349 def get_next_round_robin_reviewer engineers_with_rr_enabled = config.engineers.values.select { |eng| eng[:enable_round_robin] } next_reviewer = redis.get(RR_REDIS_KEY) if next_reviewer.nil? next_reviewer = engineers_with_rr_enabled[0][:usernames][:slack] end next_reviewer end
ghping(request, response)
click to toggle source
# File lib/lita/handlers/github_pinger.rb, line 54 def ghping(request, response) puts "########## New GitHub Event! ##########" body = MultiJson.load(request.body) puts body["action"] puts body["state"] if body["comment"] && body["action"] == "created" act_on_comment(body, response) end if body["action"] && body["action"] == "assigned" act_on_assign(body, response) end if body["action"] && body["action"] == "review_requested" act_on_review_requested(body, response) end if body["action"] && body["action"] == "labeled" act_on_pr_labeled(body, response) end if body["state"] && body["state"] == "success" act_on_build_success(body, response) end if body["state"] && body["state"] == "failure" act_on_build_failure(body, response) end end
send_dm(username, content)
click to toggle source
# File lib/lita/handlers/github_pinger.rb, line 396 def send_dm(username, content) puts "Sending DM to #{username} with content #{content[0..5]}... " if user = Lita::User.fuzzy_find(username) source = Lita::Source.new(user: user) robot.send_message(source, content) puts "Done." else alert_eng_pr("Could not find user with name #{username}, please configure everbot.") end end
update_next_round_robin_reviewer()
click to toggle source
# File lib/lita/handlers/github_pinger.rb, line 360 def update_next_round_robin_reviewer engineers_with_rr_enabled = config.engineers.values.select { |eng| eng[:enable_round_robin] } current_reviewer = get_next_round_robin_reviewer current_reviewer_index = engineers_with_rr_enabled.find_index do |eng| eng[:usernames][:slack] == current_reviewer end next_reviewer_index = (current_reviewer_index + 1) % engineers_with_rr_enabled.length next_reviewer = engineers_with_rr_enabled[next_reviewer_index][:usernames][:slack] redis.set(RR_REDIS_KEY, next_reviewer) end