diff options
author | Lin Jen-Shin <godfat@godfat.org> | 2019-05-29 22:38:26 +0800 |
---|---|---|
committer | Lin Jen-Shin <godfat@godfat.org> | 2019-05-30 19:24:28 +0800 |
commit | c90ba127bf8cdd4ccac9692b6c96fa746314cd55 (patch) | |
tree | 480c8fe6e25d71625c3d8c7376851c3a91e572f2 /lib | |
parent | c8b4edf651009c4603802bf22a66a04d395b4f00 (diff) | |
download | gitlab-ce-c90ba127bf8cdd4ccac9692b6c96fa746314cd55.tar.gz |
Extract roulette to its own module
So it's more modular and extensible
Diffstat (limited to 'lib')
-rw-r--r-- | lib/gitlab/danger/helper.rb | 29 | ||||
-rw-r--r-- | lib/gitlab/danger/roulette.rb | 84 |
2 files changed, 84 insertions, 29 deletions
diff --git a/lib/gitlab/danger/helper.rb b/lib/gitlab/danger/helper.rb index f0ca397609d..7effb802678 100644 --- a/lib/gitlab/danger/helper.rb +++ b/lib/gitlab/danger/helper.rb @@ -1,6 +1,4 @@ # frozen_string_literal: true -require 'net/http' -require 'json' require_relative 'teammate' @@ -8,7 +6,6 @@ module Gitlab module Danger module Helper RELEASE_TOOLS_BOT = 'gitlab-release-tools-bot' - ROULETTE_DATA_URL = URI.parse('https://about.gitlab.com/roulette.json').freeze # Returns a list of all files that have been added, modified or renamed. # `git.modified_files` might contain paths that already have been renamed, @@ -49,32 +46,6 @@ module Gitlab ee? ? 'gitlab-ee' : 'gitlab-ce' end - # Looks up the current list of GitLab team members and parses it into a - # useful form - # - # @return [Array<Teammate>] - def team - @team ||= - begin - rsp = Net::HTTP.get_response(ROULETTE_DATA_URL) - raise "Failed to read #{ROULETTE_DATA_URL}: #{rsp.code} #{rsp.message}" unless - rsp.is_a?(Net::HTTPSuccess) - - data = JSON.parse(rsp.body) - data.map { |hash| ::Gitlab::Danger::Teammate.new(hash) } - rescue JSON::ParserError - raise "Failed to parse JSON response from #{ROULETTE_DATA_URL}" - end - end - - # Like +team+, but only returns teammates in the current project, based on - # project_name. - # - # @return [Array<Teammate>] - def project_team - team.select { |member| member.in_project?(project_name) } - end - # @return [Hash<String,Array<String>>] def changes_by_category all_changed_files.each_with_object(Hash.new { |h, k| h[k] = [] }) do |file, hash| diff --git a/lib/gitlab/danger/roulette.rb b/lib/gitlab/danger/roulette.rb new file mode 100644 index 00000000000..062eda38ee4 --- /dev/null +++ b/lib/gitlab/danger/roulette.rb @@ -0,0 +1,84 @@ +# frozen_string_literal: true + +require 'net/http' +require 'json' +require 'cgi' + +require_relative 'teammate' + +module Gitlab + module Danger + module Roulette + ROULETTE_DATA_URL = 'https://about.gitlab.com/roulette.json' + HTTPError = Class.new(RuntimeError) + + # Looks up the current list of GitLab team members and parses it into a + # useful form + # + # @return [Array<Teammate>] + def team + @team ||= + begin + data = http_get_json(ROULETTE_DATA_URL) + data.map { |hash| ::Gitlab::Danger::Teammate.new(hash) } + rescue JSON::ParserError + raise "Failed to parse JSON response from #{ROULETTE_DATA_URL}" + end + end + + # Like +team+, but only returns teammates in the current project, based on + # project_name. + # + # @return [Array<Teammate>] + def project_team(project_name) + team.select { |member| member.in_project?(project_name) } + end + + def canonical_branch_name(branch_name) + branch_name.gsub(/^[ce]e-|-[ce]e$/, '') + end + + def new_random(seed) + Random.new(Digest::MD5.hexdigest(seed).to_i(16)) + end + + # Known issue: If someone is rejected due to OOO, and then becomes not OOO, the + # selection will change on next spin + def spin_for_person(people, random:) + person = nil + people = people.dup + + people.size.times do + person = people.sample(random: random) + + break person unless out_of_office?(person) + + people -= [person] + end + + person + end + + private + + def out_of_office?(person) + username = CGI.escape(person.username) + api_endpoint = "https://gitlab.com/api/v4/users/#{username}/status" + response = http_get_json(api_endpoint) + response["message"]&.match?(/OOO/i) + rescue HTTPError, JSON::ParserError + false # this is no worse than not checking for OOO + end + + def http_get_json(url) + rsp = Net::HTTP.get_response(URI.parse(url)) + + unless rsp.is_a?(Net::HTTPSuccess) + raise HTTPError, "Failed to read #{url}: #{rsp.code} #{rsp.message}" + end + + JSON.parse(rsp.body) + end + end + end +end |