Module: Gitlab::Danger::Roulette

Defined in:
lib/gitlab/danger/roulette.rb

Defined Under Namespace

Classes: Spin

Constant Summary collapse

ROULETTE_DATA_URL =
'https://gitlab-org.gitlab.io/gitlab-roulette/roulette.json'
HOURS_WHEN_PERSON_CAN_BE_PICKED =
(6..14).freeze
INCLUDE_TIMEZONE_FOR_CATEGORY =
{
  database: false
}.freeze

Instance Method Summary collapse

Instance Method Details

#project_team(project_name) ⇒ Array<Teammate>

Like team, but only returns teammates in the current project, based on project_name.

Returns:


79
80
81
82
83
84
# File 'lib/gitlab/danger/roulette.rb', line 79

def project_team(project_name)
  team.select { |member| member.in_project?(project_name) }
rescue => err
  warn("Reviewer roulette failed to load team data: #{err.message}")
  []
end

#spin(project, categories, timezone_experiment: false) ⇒ Array<Spin>

Assigns GitLab team members to be reviewer and maintainer for each change category that a Merge Request contains.

Returns:


26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/gitlab/danger/roulette.rb', line 26

def spin(project, categories, timezone_experiment: false)
  spins = categories.map do |category|
    including_timezone = INCLUDE_TIMEZONE_FOR_CATEGORY.fetch(category, timezone_experiment)

    spin_for_category(project, category, timezone_experiment: including_timezone)
  end

  backend_spin = spins.find { |spin| spin.category == :backend }

  spins.each do |spin|
    including_timezone = INCLUDE_TIMEZONE_FOR_CATEGORY.fetch(spin.category, timezone_experiment)
    case spin.category
    when :qa
      # MR includes QA changes, but also other changes, and author isn't an SET
      if categories.size > 1 && !team_mr_author&.reviewer?(project, spin.category, [])
        spin.optional_role = :maintainer
      end
    when :test
      spin.optional_role = :maintainer

      if spin.reviewer.nil?
        # Fetch an already picked backend reviewer, or pick one otherwise
        spin.reviewer = backend_spin&.reviewer || spin_for_category(project, :backend, timezone_experiment: including_timezone).reviewer
      end
    when :engineering_productivity
      if spin.maintainer.nil?
        # Fetch an already picked backend maintainer, or pick one otherwise
        spin.maintainer = backend_spin&.maintainer || spin_for_category(project, :backend, timezone_experiment: including_timezone).maintainer
      end
    end
  end

  spins
end

#spin_for_person(people, random:, timezone_experiment: false) ⇒ Object

Known issue: If someone is rejected due to OOO, and then becomes not OOO, the selection will change on next spin

Parameters:


89
90
91
92
93
94
95
96
97
# File 'lib/gitlab/danger/roulette.rb', line 89

def spin_for_person(people, random:, timezone_experiment: false)
  shuffled_people = people.shuffle(random: random)

  if timezone_experiment
    shuffled_people.find(&method(:valid_person_with_timezone?))
  else
    shuffled_people.find(&method(:valid_person?))
  end
end

#teamArray<Teammate>

Looks up the current list of GitLab team members and parses it into a useful form

Returns:


65
66
67
68
69
70
71
72
73
# File 'lib/gitlab/danger/roulette.rb', line 65

def team
  @team ||=
    begin
      data = Gitlab::Danger::RequestHelper.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

#team_mr_authorObject


18
19
20
# File 'lib/gitlab/danger/roulette.rb', line 18

def team_mr_author
  team.find { |person| person.username == mr_author_username }
end