code_ownership 1.32.7 → 1.32.8

Sign up to get free protection for your applications and to get access to all the features.
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