# frozen_string_literal: true module Gitlab module Dangerfiles CategoryStruct = Struct.new(:name, :project, :kind, :labels, keyword_init: true) class Category < CategoryStruct def self.for(name, **arguments) (name_to_class[name] || self).new(name: name, **arguments) end def self.name_to_class @name_to_class ||= { none: None, test: Test, tooling: Tooling, import_integrate_be: ImportIntegrateBE, import_integrate_fe: ImportIntegrateFE, ux: UX, }.freeze end private_class_method :name_to_class def has_capability?(teammate) teammate.capabilities(project).include?(capability) end private def capability @capability ||= "#{kind} #{name}" end class None < Category def capability @capability ||= kind.to_s end end class Test < Category def has_capability?(teammate) return false if kind != :reviewer area = teammate.role[/Software Engineer in Test(?:.*?, (\w+))/, 1] !!area && labels.any?("devops::#{area.downcase}") end end class Tooling < Category def has_capability?(teammate) if super true elsif %i[trainee_maintainer maintainer].include?(kind) false else # fallback to backend reviewer teammate.capabilities(project).include?("#{kind} backend") end end end class ImportIntegrateBE < Category def has_capability?(teammate) kind == :reviewer && teammate.role.match?(/Backend Engineer.+Manage:Import and Integrate/) end end class ImportIntegrateFE < Category def has_capability?(teammate) kind == :reviewer && teammate.role.match?(/Frontend Engineer.+Manage:Import and Integrate/) end end class UX < Category def has_capability?(teammate) super && if labels.any?("Community contribution") can_review_wider_community_contribution?(teammate) else can_review_team_memeber_contribution?(teammate) end end private def can_review_wider_community_contribution?(teammate) # We want the designer for the team to review the wider community # contribution because they're more familiar with that area. the_designer_for_the_team?(teammate) end def can_review_team_memeber_contribution?(teammate) # We don't want the designer for the team to review merge # requests for the same team which is designed by themselves. # So they can only review if they're not the designer for the team. !the_designer_for_the_team?(teammate) end def the_designer_for_the_team?(teammate) # Pick corresponding group for community contribution # Specialty can be: # Source Code # [Growth: Activation, Growth: Expansion] # Runner group_labels = Array(teammate.specialty).map do |field| group = field.strip.sub(/^.+: ?/, "").downcase "group::#{group}" end (group_labels & labels).any? end end end end end