Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'tooling/danger/teammate.rb')
-rw-r--r--tooling/danger/teammate.rb121
1 files changed, 121 insertions, 0 deletions
diff --git a/tooling/danger/teammate.rb b/tooling/danger/teammate.rb
new file mode 100644
index 00000000000..bcd33bebdc9
--- /dev/null
+++ b/tooling/danger/teammate.rb
@@ -0,0 +1,121 @@
+# frozen_string_literal: true
+
+module Tooling
+ module Danger
+ class Teammate
+ attr_reader :options, :username, :name, :role, :projects, :available, :hungry, :reduced_capacity, :tz_offset_hours
+
+ # The options data are produced by https://gitlab.com/gitlab-org/gitlab-roulette/-/blob/master/lib/team_member.rb
+ def initialize(options = {})
+ @options = options
+ @username = options['username']
+ @name = options['name']
+ @markdown_name = options['markdown_name']
+ @role = options['role']
+ @projects = options['projects']
+ @available = options['available']
+ @hungry = options['hungry']
+ @reduced_capacity = options['reduced_capacity']
+ @tz_offset_hours = options['tz_offset_hours']
+ end
+
+ def to_h
+ options
+ end
+
+ def ==(other)
+ return false unless other.respond_to?(:username)
+
+ other.username == username
+ end
+
+ def in_project?(name)
+ projects&.has_key?(name)
+ end
+
+ def any_capability?(project, category)
+ capabilities(project).any? { |capability| capability.end_with?(category.to_s) }
+ end
+
+ def reviewer?(project, category, labels)
+ has_capability?(project, category, :reviewer, labels)
+ end
+
+ def traintainer?(project, category, labels)
+ has_capability?(project, category, :trainee_maintainer, labels)
+ end
+
+ def maintainer?(project, category, labels)
+ has_capability?(project, category, :maintainer, labels)
+ end
+
+ def markdown_name(author: nil)
+ "#{@markdown_name} (#{utc_offset_text(author)})"
+ end
+
+ def local_hour
+ (Time.now.utc + tz_offset_hours * 3600).hour
+ end
+
+ protected
+
+ def floored_offset_hours
+ floored_offset = tz_offset_hours.floor(0)
+
+ floored_offset == tz_offset_hours ? floored_offset : tz_offset_hours
+ end
+
+ private
+
+ def utc_offset_text(author = nil)
+ offset_text =
+ if floored_offset_hours >= 0
+ "UTC+#{floored_offset_hours}"
+ else
+ "UTC#{floored_offset_hours}"
+ end
+
+ return offset_text unless author
+
+ "#{offset_text}, #{offset_diff_compared_to_author(author)}"
+ end
+
+ def offset_diff_compared_to_author(author)
+ diff = floored_offset_hours - author.floored_offset_hours
+ return "same timezone as `@#{author.username}`" if diff == 0
+
+ ahead_or_behind = diff < 0 ? 'behind' : 'ahead of'
+ pluralized_hours = pluralize(diff.abs, 'hour', 'hours')
+
+ "#{pluralized_hours} #{ahead_or_behind} `@#{author.username}`"
+ end
+
+ def has_capability?(project, category, kind, labels)
+ case category
+ when :test
+ area = role[/Software Engineer in Test(?:.*?, (\w+))/, 1]
+
+ area && labels.any?("devops::#{area.downcase}") if kind == :reviewer
+ when :engineering_productivity
+ return false unless role[/Engineering Productivity/]
+ return true if kind == :reviewer
+ return true if capabilities(project).include?("#{kind} engineering_productivity")
+
+ capabilities(project).include?("#{kind} backend")
+ else
+ capabilities(project).include?("#{kind} #{category}")
+ end
+ end
+
+ def capabilities(project)
+ Array(projects.fetch(project, []))
+ end
+
+ def pluralize(count, singular, plural)
+ word = count == 1 || count.to_s =~ /^1(\.0+)?$/ ? singular : plural
+
+ "#{count || 0} #{word}"
+ end
+ end
+ end
+end