Class: Archsight::Import::TeamMatcher

Inherits:
Object
  • Object
show all
Defined in:
lib/archsight/import/team_matcher.rb

Overview

Matches git contributors to BusinessActor teams

Uses team member email and name patterns from BusinessActor annotations to match top contributors from git history to teams.

Examples:

matcher = Archsight::Import::TeamMatcher.new(database)
result = matcher.analyze(top_contributors)
# => { maintainer: "Team:Engineering", contributors: ["Team:QA", "Team:Ops"] }

Constant Summary collapse

IGNORED_TEAMS =

Teams to ignore when matching (bots, unknown, etc.)

%w[Bot:Team No:Team Team:Unknown Team:Bot].freeze
TEAM_ANNOTATION_KEYS =

Team annotation keys that contain member/lead information

%w[team/members team/lead].freeze

Instance Method Summary collapse

Constructor Details

#initialize(database, corporate_affixes: []) ⇒ TeamMatcher

Returns a new instance of TeamMatcher.



21
22
23
24
25
26
27
28
# File 'lib/archsight/import/team_matcher.rb', line 21

def initialize(database, corporate_affixes: [])
  @database = database
  @corporate_affixes = corporate_affixes
  @teams = load_teams
  @email_to_team = build_email_index
  @name_to_team = build_name_index
  @member_identities = build_member_identities
end

Instance Method Details

#analyze(top_contributors) ⇒ Hash

Analyze top contributors and return team assignments

Parameters:

  • top_contributors (Array<Hash>)

    List of contributors with “name”, “email”, “commits” keys

Returns:

  • (Hash)

    { maintainer: String?, contributors: [String] }



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/archsight/import/team_matcher.rb', line 34

def analyze(top_contributors)
  return { maintainer: nil, contributors: [] } if top_contributors.nil? || top_contributors.empty?

  team_commits = Hash.new(0)

  top_contributors.each do |contributor|
    team = match_contributor(contributor["name"], contributor["email"])
    next unless team
    next if IGNORED_TEAMS.include?(team)

    team_commits[team] += contributor["commits"]
  end

  return { maintainer: nil, contributors: [] } if team_commits.empty?

  # Sort by commits descending
  sorted = team_commits.sort_by { |_, commits| -commits }

  {
    maintainer: sorted.first&.first,
    contributors: sorted.drop(1).map(&:first)
  }
end

#match_contributor(name, email) ⇒ String?

Match a single contributor to a team

Parameters:

  • name (String)

    Contributor name

  • email (String)

    Contributor email

Returns:

  • (String, nil)

    Team name or nil if no match



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/archsight/import/team_matcher.rb', line 63

def match_contributor(name, email)
  return nil if name.nil? && email.nil?

  # Try exact email match first (most reliable)
  if email
    normalized_email = email.to_s.downcase.strip
    team = @email_to_team[normalized_email]
    return team if team
  end

  # Try name match (less reliable, but useful for LDAP-style names)
  if name
    normalized_name = normalize_name(name)
    team = @name_to_team[normalized_name]
    return team if team
  end

  # Try corporate username pattern match (e.g. jsmith-ionos -> John Smith)
  if name
    team = pattern_match_username(name)
    return team if team
  end

  nil
end