code_ownership 1.32.7 → 1.32.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 76d700471a2e895926f184939c856b08ac75d5240a0d924a8e4474ac733a7204
4
- data.tar.gz: 3b62947009df98089b522614022643762c4c51d82af4f90f957606bcedfe60bc
3
+ metadata.gz: 18e702e6635a7d3d264eaae41f61fb6f83e423e8021ca76e92a6972fe5444848
4
+ data.tar.gz: 90f34b5a02b21a1f78ff781f7ef3e8220a45549e77c4b93b829381a57f37ba7c
5
5
  SHA512:
6
- metadata.gz: df833467c3721e6b7d67aebd0732d59c46073589210251bd0859cb05979103741876264dd336df10401005360bca7a2937c65e861044b22abd698a2b8b65a20d
7
- data.tar.gz: 1b8f489aa18295cd8c534f3d5bcb3e2ab569553f26ec7e5a9445faff90da3aee3860bd3d7a02d6e91b80815d65b96680b0f54b085770ba85a54efa13aa0109b1
6
+ metadata.gz: f1deba0493c9ebbff4e39b81c0a282ffd634cef6db756f3f4be2b3b91f8c43e0d0f6d9362e03f2779ac5fe302101ae19fa8bf90022c55f24afbd9cd7c3b1fb13
7
+ data.tar.gz: 0a1a3da4c7c758b0b64b7d9f817a92924c7a5e54fb4918655af2208a5ba8c65f12d41b37f0f568f443a817dd5893d16e351de745be641b3a56d3479e257add45
@@ -40,15 +40,18 @@ module CodeOwnership
40
40
  #
41
41
  sig do
42
42
  abstract.params(files: T::Array[String]).
43
- returns(T::Hash[String, T.nilable(::CodeTeams::Team)])
43
+ returns(T::Hash[String, ::CodeTeams::Team])
44
44
  end
45
- def map_files_to_owners(files)
45
+ def globs_to_owner(files)
46
46
  end
47
47
 
48
+ #
49
+ # This should be fast when run with MANY files
50
+ #
48
51
  sig do
49
- abstract.returns(T::Hash[String, T.nilable(::CodeTeams::Team)])
52
+ abstract.params(cache: GlobsToOwningTeamMap, files: T::Array[String]).returns(GlobsToOwningTeamMap)
50
53
  end
51
- def codeowners_lines_to_owners
54
+ def update_cache(cache, files)
52
55
  end
53
56
 
54
57
  sig { abstract.returns(String) }
@@ -64,7 +67,7 @@ module CodeOwnership
64
67
  glob_to_owner_map_by_mapper_description = {}
65
68
 
66
69
  Mapper.all.each do |mapper|
67
- mapped_files = mapper.codeowners_lines_to_owners
70
+ mapped_files = mapper.globs_to_owner(Private.tracked_files)
68
71
  mapped_files.each do |glob, owner|
69
72
  next if owner.nil?
70
73
  glob_to_owner_map_by_mapper_description[mapper.description] ||= {}
@@ -90,6 +90,58 @@ module CodeOwnership
90
90
  def self.path
91
91
  Pathname.pwd.join('.github/CODEOWNERS')
92
92
  end
93
+
94
+ sig { params(files: T::Array[String]).void }
95
+ def self.update_cache!(files)
96
+ cache = Private.glob_cache
97
+ # Each mapper returns a new copy of the cache subset related to that mapper,
98
+ # which is then stored back into the cache.
99
+ Mapper.all.each do |mapper|
100
+ existing_cache = cache.raw_cache_contents.fetch(mapper.description, {})
101
+ updated_cache = mapper.update_cache(existing_cache, files)
102
+ cache.raw_cache_contents[mapper.description] = updated_cache
103
+ end
104
+ end
105
+
106
+ sig { returns(T::Boolean) }
107
+ def self.use_codeowners_cache?
108
+ CodeownersFile.path.exist? && !Private.configuration.skip_codeowners_validation
109
+ end
110
+
111
+ sig { returns(GlobCache) }
112
+ def self.to_glob_cache
113
+ github_team_to_code_team_map = T.let({}, T::Hash[String, CodeTeams::Team])
114
+ CodeTeams.all.each do |team|
115
+ github_team = TeamPlugins::Github.for(team).github.team
116
+ github_team_to_code_team_map[github_team] = team
117
+ end
118
+ raw_cache_contents = T.let({}, GlobCache::CacheShape)
119
+ current_mapper = T.let(nil, T.nilable(String))
120
+ mapper_descriptions = Set.new(Mapper.all.map(&:description))
121
+
122
+ path.readlines.each do |line|
123
+ line_with_no_comment = line.chomp.gsub("# ", "")
124
+ if mapper_descriptions.include?(line_with_no_comment)
125
+ current_mapper = line_with_no_comment
126
+ else
127
+ next if current_mapper.nil?
128
+ next if line.chomp == ""
129
+ # The codeowners file stores paths relative to the root of directory
130
+ # Since a `/` means root of the file system from the perspective of ruby,
131
+ # we remove that beginning slash so we can correctly glob the files out.
132
+ normalized_line = line.gsub(/^# /, '').gsub(/^\//, '')
133
+ split_line = normalized_line.split
134
+ # Most lines will be in the format: /path/to/file my-github-team
135
+ # This will skip over lines that are not of the correct form
136
+ next if split_line.count > 2
137
+ entry, github_team = split_line
138
+ raw_cache_contents[current_mapper] ||= {}
139
+ raw_cache_contents.fetch(current_mapper)[T.must(entry)] = github_team_to_code_team_map.fetch(T.must(github_team))
140
+ end
141
+ end
142
+
143
+ GlobCache.new(raw_cache_contents)
144
+ end
93
145
  end
94
146
  end
95
147
  end
@@ -7,12 +7,11 @@ module CodeOwnership
7
7
  extend T::Sig
8
8
 
9
9
  MapperDescription = T.type_alias { String }
10
- GlobsByMapper = T.type_alias { T::Hash[String, CodeTeams::Team] }
11
10
 
12
11
  CacheShape = T.type_alias do
13
12
  T::Hash[
14
13
  MapperDescription,
15
- GlobsByMapper
14
+ GlobsToOwningTeamMap
16
15
  ]
17
16
  end
18
17
 
@@ -18,7 +18,7 @@ module CodeOwnership
18
18
  extend T::Sig
19
19
  include Mapper
20
20
 
21
- @@map_files_to_owners = T.let({}, T.nilable(T::Hash[String, T.nilable(::CodeTeams::Team)])) # rubocop:disable Style/ClassVars
21
+ @@map_files_to_owners = T.let({}, T.nilable(T::Hash[String, ::CodeTeams::Team])) # rubocop:disable Style/ClassVars
22
22
 
23
23
  TEAM_PATTERN = T.let(/\A(?:#|\/\/) @team (?<team>.*)\Z/.freeze, Regexp)
24
24
 
@@ -33,9 +33,9 @@ module CodeOwnership
33
33
  sig do
34
34
  override.
35
35
  params(files: T::Array[String]).
36
- returns(T::Hash[String, T.nilable(::CodeTeams::Team)])
36
+ returns(T::Hash[String, ::CodeTeams::Team])
37
37
  end
38
- def map_files_to_owners(files)
38
+ def globs_to_owner(files)
39
39
  return @@map_files_to_owners if @@map_files_to_owners&.keys && @@map_files_to_owners.keys.count > 0
40
40
 
41
41
  @@map_files_to_owners = files.each_with_object({}) do |filename_relative_to_root, mapping| # rubocop:disable Style/ClassVars
@@ -46,6 +46,24 @@ module CodeOwnership
46
46
  end
47
47
  end
48
48
 
49
+ sig do
50
+ override.params(cache: GlobsToOwningTeamMap, files: T::Array[String]).returns(GlobsToOwningTeamMap)
51
+ end
52
+ def update_cache(cache, files)
53
+ cache.merge!(globs_to_owner(files))
54
+
55
+ # TODO: Make `tracked_files` return a set
56
+ fileset = Set.new(Private.tracked_files)
57
+ invalid_files = cache.keys.select do |file|
58
+ !fileset.include?(file)
59
+ end
60
+ invalid_files.each do |invalid_file|
61
+ cache.delete(invalid_file)
62
+ end
63
+
64
+ cache
65
+ end
66
+
49
67
  sig { params(filename: String).returns(T.nilable(CodeTeams::Team)) }
50
68
  def file_annotation_based_owner(filename)
51
69
  # If for a directory is named with an ownable extension, we need to skip
@@ -96,14 +114,6 @@ module CodeOwnership
96
114
  end
97
115
  end
98
116
 
99
- sig do
100
- override.returns(T::Hash[String, T.nilable(::CodeTeams::Team)])
101
- end
102
- def codeowners_lines_to_owners
103
- @@map_files_to_owners = nil # rubocop:disable Style/ClassVars
104
- map_files_to_owners(Private.tracked_files)
105
- end
106
-
107
117
  sig { override.returns(String) }
108
118
  def description
109
119
  'Annotations at the top of file'
@@ -24,20 +24,10 @@ module CodeOwnership
24
24
  end
25
25
 
26
26
  sig do
27
- override.
28
- params(files: T::Array[String]).
29
- returns(T::Hash[String, T.nilable(::CodeTeams::Team)])
27
+ override.params(cache: GlobsToOwningTeamMap, files: T::Array[String]).returns(GlobsToOwningTeamMap)
30
28
  end
31
- def map_files_to_owners(files) # rubocop:disable Lint/UnusedMethodArgument
32
- ParseJsPackages.all.each_with_object({}) do |package, res|
33
- owner = owner_for_package(package)
34
- next if owner.nil?
35
-
36
- glob = package.directory.join('**/**').to_s
37
- Dir.glob(glob).each do |path|
38
- res[path] = owner
39
- end
40
- end
29
+ def update_cache(cache, files)
30
+ globs_to_owner(files)
41
31
  end
42
32
 
43
33
  #
@@ -49,9 +39,10 @@ module CodeOwnership
49
39
  # subset of files, but rather we want code ownership for all files.
50
40
  #
51
41
  sig do
52
- override.returns(T::Hash[String, T.nilable(::CodeTeams::Team)])
42
+ override.params(files: T::Array[String]).
43
+ returns(T::Hash[String, ::CodeTeams::Team])
53
44
  end
54
- def codeowners_lines_to_owners
45
+ def globs_to_owner(files)
55
46
  ParseJsPackages.all.each_with_object({}) do |package, res|
56
47
  owner = owner_for_package(package)
57
48
  next if owner.nil?
@@ -23,23 +23,6 @@ module CodeOwnership
23
23
  owner_for_package(package)
24
24
  end
25
25
 
26
- sig do
27
- override.
28
- params(files: T::Array[String]).
29
- returns(T::Hash[String, T.nilable(::CodeTeams::Team)])
30
- end
31
- def map_files_to_owners(files) # rubocop:disable Lint/UnusedMethodArgument
32
- Packs.all.each_with_object({}) do |package, res|
33
- owner = owner_for_package(package)
34
- next if owner.nil?
35
-
36
- glob = package.relative_path.join('**/**').to_s
37
- Dir.glob(glob).each do |path|
38
- res[path] = owner
39
- end
40
- end
41
- end
42
-
43
26
  #
44
27
  # Package ownership ignores the passed in files when generating code owners lines.
45
28
  # This is because Package ownership knows that the fastest way to find code owners for package based ownership
@@ -49,9 +32,10 @@ module CodeOwnership
49
32
  # subset of files, but rather we want code ownership for all files.
50
33
  #
51
34
  sig do
52
- override.returns(T::Hash[String, T.nilable(::CodeTeams::Team)])
35
+ override.params(files: T::Array[String]).
36
+ returns(T::Hash[String, ::CodeTeams::Team])
53
37
  end
54
- def codeowners_lines_to_owners
38
+ def globs_to_owner(files)
55
39
  Packs.all.each_with_object({}) do |package, res|
56
40
  owner = owner_for_package(package)
57
41
  next if owner.nil?
@@ -65,6 +49,13 @@ module CodeOwnership
65
49
  'Owner metadata key in package.yml'
66
50
  end
67
51
 
52
+ sig do
53
+ override.params(cache: GlobsToOwningTeamMap, files: T::Array[String]).returns(GlobsToOwningTeamMap)
54
+ end
55
+ def update_cache(cache, files)
56
+ globs_to_owner(files)
57
+ end
58
+
68
59
  sig { params(package: Packs::Pack).returns(T.nilable(CodeTeams::Team)) }
69
60
  def owner_for_package(package)
70
61
  raw_owner_value = package.metadata['owner']
@@ -10,15 +10,14 @@ module CodeOwnership
10
10
  include Mapper
11
11
  include Validator
12
12
 
13
- @@map_files_to_owners = T.let(@map_files_to_owners, T.nilable(T::Hash[String, T.nilable(::CodeTeams::Team)])) # rubocop:disable Style/ClassVars
13
+ @@map_files_to_owners = T.let(@map_files_to_owners, T.nilable(T::Hash[String, ::CodeTeams::Team])) # rubocop:disable Style/ClassVars
14
14
  @@map_files_to_owners = {} # rubocop:disable Style/ClassVars
15
- @@codeowners_lines_to_owners = T.let(@codeowners_lines_to_owners, T.nilable(T::Hash[String, T.nilable(::CodeTeams::Team)])) # rubocop:disable Style/ClassVars
15
+ @@codeowners_lines_to_owners = T.let(@codeowners_lines_to_owners, T.nilable(T::Hash[String, ::CodeTeams::Team])) # rubocop:disable Style/ClassVars
16
16
  @@codeowners_lines_to_owners = {} # rubocop:disable Style/ClassVars
17
17
 
18
18
  sig do
19
- override.
20
- params(files: T::Array[String]).
21
- returns(T::Hash[String, T.nilable(::CodeTeams::Team)])
19
+ params(files: T::Array[String]).
20
+ returns(T::Hash[String, ::CodeTeams::Team])
22
21
  end
23
22
  def map_files_to_owners(files) # rubocop:disable Lint/UnusedMethodArgument
24
23
  return @@map_files_to_owners if @@map_files_to_owners&.keys && @@map_files_to_owners.keys.count > 0
@@ -93,9 +92,17 @@ module CodeOwnership
93
92
  end
94
93
 
95
94
  sig do
96
- override.returns(T::Hash[String, T.nilable(::CodeTeams::Team)])
95
+ override.params(cache: GlobsToOwningTeamMap, files: T::Array[String]).returns(GlobsToOwningTeamMap)
97
96
  end
98
- def codeowners_lines_to_owners
97
+ def update_cache(cache, files)
98
+ globs_to_owner(files)
99
+ end
100
+
101
+ sig do
102
+ override.params(files: T::Array[String]).
103
+ returns(T::Hash[String, ::CodeTeams::Team])
104
+ end
105
+ def globs_to_owner(files)
99
106
  return @@codeowners_lines_to_owners if @@codeowners_lines_to_owners&.keys && @@codeowners_lines_to_owners.keys.count > 0
100
107
 
101
108
  @@codeowners_lines_to_owners = CodeTeams.all.each_with_object({}) do |team, map| # rubocop:disable Style/ClassVars
@@ -9,15 +9,14 @@ module CodeOwnership
9
9
  extend T::Sig
10
10
  include Mapper
11
11
 
12
- @@map_files_to_owners = T.let(@map_files_to_owners, T.nilable(T::Hash[String, T.nilable(::CodeTeams::Team)])) # rubocop:disable Style/ClassVars
12
+ @@map_files_to_owners = T.let(@map_files_to_owners, T.nilable(T::Hash[String, ::CodeTeams::Team])) # rubocop:disable Style/ClassVars
13
13
  @@map_files_to_owners = {} # rubocop:disable Style/ClassVars
14
- @@codeowners_lines_to_owners = T.let(@codeowners_lines_to_owners, T.nilable(T::Hash[String, T.nilable(::CodeTeams::Team)])) # rubocop:disable Style/ClassVars
14
+ @@codeowners_lines_to_owners = T.let(@codeowners_lines_to_owners, T.nilable(T::Hash[String, ::CodeTeams::Team])) # rubocop:disable Style/ClassVars
15
15
  @@codeowners_lines_to_owners = {} # rubocop:disable Style/ClassVars
16
16
 
17
17
  sig do
18
- override.
19
- params(files: T::Array[String]).
20
- returns(T::Hash[String, T.nilable(::CodeTeams::Team)])
18
+ params(files: T::Array[String]).
19
+ returns(T::Hash[String, ::CodeTeams::Team])
21
20
  end
22
21
  def map_files_to_owners(files) # rubocop:disable Lint/UnusedMethodArgument
23
22
  return @@map_files_to_owners if @@map_files_to_owners&.keys && @@map_files_to_owners.keys.count > 0
@@ -36,9 +35,10 @@ module CodeOwnership
36
35
  end
37
36
 
38
37
  sig do
39
- override.returns(T::Hash[String, T.nilable(::CodeTeams::Team)])
38
+ override.params(files: T::Array[String]).
39
+ returns(T::Hash[String, ::CodeTeams::Team])
40
40
  end
41
- def codeowners_lines_to_owners
41
+ def globs_to_owner(files)
42
42
  return @@codeowners_lines_to_owners if @@codeowners_lines_to_owners&.keys && @@codeowners_lines_to_owners.keys.count > 0
43
43
 
44
44
  @@codeowners_lines_to_owners = CodeTeams.all.each_with_object({}) do |team, map| # rubocop:disable Style/ClassVars
@@ -52,6 +52,13 @@ module CodeOwnership
52
52
  @@map_files_to_owners = {} # rubocop:disable Style/ClassVars
53
53
  end
54
54
 
55
+ sig do
56
+ override.params(cache: GlobsToOwningTeamMap, files: T::Array[String]).returns(GlobsToOwningTeamMap)
57
+ end
58
+ def update_cache(cache, files)
59
+ globs_to_owner(files)
60
+ end
61
+
55
62
  sig { override.returns(String) }
56
63
  def description
57
64
  'Team YML ownership'
@@ -44,6 +44,8 @@ module CodeOwnership
44
44
 
45
45
  sig { params(files: T::Array[String], autocorrect: T::Boolean, stage_changes: T::Boolean).void }
46
46
  def self.validate!(files:, autocorrect: true, stage_changes: true)
47
+ CodeownersFile.update_cache!(files) if CodeownersFile.use_codeowners_cache?
48
+
47
49
  errors = Validator.all.flat_map do |validator|
48
50
  validator.validation_errors(
49
51
  files: files,
@@ -92,7 +94,13 @@ module CodeOwnership
92
94
  sig { returns(GlobCache) }
93
95
  def self.glob_cache
94
96
  @glob_cache ||= T.let(@glob_cache, T.nilable(GlobCache))
95
- @glob_cache ||= Mapper.to_glob_cache
97
+ @glob_cache ||= begin
98
+ if CodeownersFile.use_codeowners_cache?
99
+ CodeownersFile.to_glob_cache
100
+ else
101
+ Mapper.to_glob_cache
102
+ end
103
+ end
96
104
  end
97
105
  end
98
106
 
@@ -19,6 +19,7 @@ module CodeOwnership
19
19
  extend T::Helpers
20
20
 
21
21
  requires_ancestor { Kernel }
22
+ GlobsToOwningTeamMap = T.type_alias { T::Hash[String, CodeTeams::Team] }
22
23
 
23
24
  sig { params(file: String).returns(T.nilable(CodeTeams::Team)) }
24
25
  def for_file(file)
@@ -50,7 +51,7 @@ module CodeOwnership
50
51
  ownership_information << "# Code Ownership Report for `#{team.name}` Team"
51
52
  Mapper.all.each do |mapper|
52
53
  ownership_information << "## #{mapper.description}"
53
- codeowners_lines = mapper.codeowners_lines_to_owners
54
+ codeowners_lines = mapper.globs_to_owner(Private.tracked_files)
54
55
  ownership_for_mapper = []
55
56
  codeowners_lines.each do |line, team_for_line|
56
57
  next if team_for_line.nil?
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: code_ownership
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.32.7
4
+ version: 1.32.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gusto Engineers
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-04-11 00:00:00.000000000 Z
11
+ date: 2023-04-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: code_teams