code_ownership 1.29.3 → 1.31.0
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 +4 -4
- data/lib/code_ownership/private/ownership_mappers/team_globs.rb +52 -0
- data/lib/code_ownership/private/ownership_mappers/team_yml_ownership.rb +62 -0
- data/lib/code_ownership/private/validations/no_overlapping_globs.rb +30 -0
- data/lib/code_ownership/private.rb +4 -0
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 292664613750d5a5413984bac92ade17caa9a7f1796123455d16dd6f76ae6410
|
|
4
|
+
data.tar.gz: 306f65f710f7462acc3b001232e73e3561a63faa260153b7f759adc3dbf0a28e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 196be6927310bda4e577f94ea9553d832abf85f2dbc65e2d2efc0c55016001a9d8b6d6c64674aeb846ae41f1500bd0f5254c6e486017653cb03c620be9be0865
|
|
7
|
+
data.tar.gz: bdf65c513ab30773eed96cb934d1212d4599e0f54f0f0fcc1729b54bd6a007aefc6edc7dd647c2348c3020c2afe04d79017b84013d51cb1b6fb3284577653a5f
|
|
@@ -31,6 +31,58 @@ module CodeOwnership
|
|
|
31
31
|
end
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
+
class MappingContext < T::Struct
|
|
35
|
+
const :glob, String
|
|
36
|
+
const :team, CodeTeams::Team
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
class GlobOverlap < T::Struct
|
|
40
|
+
extend T::Sig
|
|
41
|
+
|
|
42
|
+
const :mapping_contexts, T::Array[MappingContext]
|
|
43
|
+
|
|
44
|
+
sig { returns(String) }
|
|
45
|
+
def description
|
|
46
|
+
# These are sorted only to prevent non-determinism in output between local and CI environments.
|
|
47
|
+
sorted_contexts = mapping_contexts.sort_by{|context| context.team.config_yml.to_s }
|
|
48
|
+
description_args = sorted_contexts.map do |context|
|
|
49
|
+
"`#{context.glob}` (from `#{context.team.config_yml}`)"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
description_args.join(', ')
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
sig do
|
|
57
|
+
returns(T::Array[GlobOverlap])
|
|
58
|
+
end
|
|
59
|
+
def find_overlapping_globs
|
|
60
|
+
mapped_files = T.let({}, T::Hash[String, T::Array[MappingContext]])
|
|
61
|
+
CodeTeams.all.each_with_object({}) do |team, map| # rubocop:disable Style/ClassVars
|
|
62
|
+
TeamPlugins::Ownership.for(team).owned_globs.each do |glob|
|
|
63
|
+
Dir.glob(glob).each do |filename|
|
|
64
|
+
mapped_files[filename] ||= []
|
|
65
|
+
T.must(mapped_files[filename]) << MappingContext.new(glob: glob, team: team)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
overlaps = T.let([], T::Array[GlobOverlap])
|
|
71
|
+
mapped_files.each do |filename, mapping_contexts|
|
|
72
|
+
if mapping_contexts.count > 1
|
|
73
|
+
overlaps << GlobOverlap.new(mapping_contexts: mapping_contexts)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
deduplicated_overlaps = overlaps.uniq do |glob_overlap|
|
|
78
|
+
glob_overlap.mapping_contexts.map do |context|
|
|
79
|
+
[context.glob, context.team.name]
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
deduplicated_overlaps
|
|
84
|
+
end
|
|
85
|
+
|
|
34
86
|
sig do
|
|
35
87
|
override.params(file: String).
|
|
36
88
|
returns(T.nilable(::CodeTeams::Team))
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# typed: true
|
|
4
|
+
|
|
5
|
+
module CodeOwnership
|
|
6
|
+
module Private
|
|
7
|
+
module OwnershipMappers
|
|
8
|
+
class TeamYmlOwnership
|
|
9
|
+
extend T::Sig
|
|
10
|
+
include Interface
|
|
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
|
|
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
|
|
15
|
+
@@codeowners_lines_to_owners = {} # rubocop:disable Style/ClassVars
|
|
16
|
+
|
|
17
|
+
sig do
|
|
18
|
+
override.
|
|
19
|
+
params(files: T::Array[String]).
|
|
20
|
+
returns(T::Hash[String, T.nilable(::CodeTeams::Team)])
|
|
21
|
+
end
|
|
22
|
+
def map_files_to_owners(files) # rubocop:disable Lint/UnusedMethodArgument
|
|
23
|
+
return @@map_files_to_owners if @@map_files_to_owners&.keys && @@map_files_to_owners.keys.count > 0
|
|
24
|
+
|
|
25
|
+
@@map_files_to_owners = CodeTeams.all.each_with_object({}) do |team, map| # rubocop:disable Style/ClassVars
|
|
26
|
+
map[team.config_yml] = team
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
sig do
|
|
31
|
+
override.params(file: String).
|
|
32
|
+
returns(T.nilable(::CodeTeams::Team))
|
|
33
|
+
end
|
|
34
|
+
def map_file_to_owner(file)
|
|
35
|
+
map_files_to_owners([file])[file]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
sig do
|
|
39
|
+
override.returns(T::Hash[String, T.nilable(::CodeTeams::Team)])
|
|
40
|
+
end
|
|
41
|
+
def codeowners_lines_to_owners
|
|
42
|
+
return @@codeowners_lines_to_owners if @@codeowners_lines_to_owners&.keys && @@codeowners_lines_to_owners.keys.count > 0
|
|
43
|
+
|
|
44
|
+
@@codeowners_lines_to_owners = CodeTeams.all.each_with_object({}) do |team, map| # rubocop:disable Style/ClassVars
|
|
45
|
+
map[team.config_yml] = team
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
sig { override.void }
|
|
50
|
+
def bust_caches!
|
|
51
|
+
@@codeowners_lines_to_owners = {} # rubocop:disable Style/ClassVars
|
|
52
|
+
@@map_files_to_owners = {} # rubocop:disable Style/ClassVars
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
sig { override.returns(String) }
|
|
56
|
+
def description
|
|
57
|
+
'Team YML ownership'
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
|
|
3
|
+
module CodeOwnership
|
|
4
|
+
module Private
|
|
5
|
+
module Validations
|
|
6
|
+
class NoOverlappingGlobs
|
|
7
|
+
extend T::Sig
|
|
8
|
+
extend T::Helpers
|
|
9
|
+
include Interface
|
|
10
|
+
|
|
11
|
+
sig { override.params(files: T::Array[String], autocorrect: T::Boolean, stage_changes: T::Boolean).returns(T::Array[String]) }
|
|
12
|
+
def validation_errors(files:, autocorrect: true, stage_changes: true)
|
|
13
|
+
overlapping_globs = OwnershipMappers::TeamGlobs.new.find_overlapping_globs
|
|
14
|
+
|
|
15
|
+
errors = T.let([], T::Array[String])
|
|
16
|
+
|
|
17
|
+
if overlapping_globs.any?
|
|
18
|
+
errors << <<~MSG
|
|
19
|
+
`owned_globs` cannot overlap between teams. The following globs overlap:
|
|
20
|
+
|
|
21
|
+
#{overlapping_globs.map { |overlap| "- #{overlap.description}"}.join("\n")}
|
|
22
|
+
MSG
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
errors
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -10,11 +10,13 @@ require 'code_ownership/private/validations/interface'
|
|
|
10
10
|
require 'code_ownership/private/validations/files_have_owners'
|
|
11
11
|
require 'code_ownership/private/validations/github_codeowners_up_to_date'
|
|
12
12
|
require 'code_ownership/private/validations/files_have_unique_owners'
|
|
13
|
+
require 'code_ownership/private/validations/no_overlapping_globs'
|
|
13
14
|
require 'code_ownership/private/ownership_mappers/interface'
|
|
14
15
|
require 'code_ownership/private/ownership_mappers/file_annotations'
|
|
15
16
|
require 'code_ownership/private/ownership_mappers/team_globs'
|
|
16
17
|
require 'code_ownership/private/ownership_mappers/package_ownership'
|
|
17
18
|
require 'code_ownership/private/ownership_mappers/js_package_ownership'
|
|
19
|
+
require 'code_ownership/private/ownership_mappers/team_yml_ownership'
|
|
18
20
|
|
|
19
21
|
module CodeOwnership
|
|
20
22
|
module Private
|
|
@@ -39,6 +41,7 @@ module CodeOwnership
|
|
|
39
41
|
Validations::FilesHaveOwners.new,
|
|
40
42
|
Validations::FilesHaveUniqueOwners.new,
|
|
41
43
|
Validations::GithubCodeownersUpToDate.new,
|
|
44
|
+
Validations::NoOverlappingGlobs.new,
|
|
42
45
|
]
|
|
43
46
|
|
|
44
47
|
errors = validators.flat_map do |validator|
|
|
@@ -62,6 +65,7 @@ module CodeOwnership
|
|
|
62
65
|
Private::OwnershipMappers::TeamGlobs.new,
|
|
63
66
|
Private::OwnershipMappers::PackageOwnership.new,
|
|
64
67
|
Private::OwnershipMappers::JsPackageOwnership.new,
|
|
68
|
+
Private::OwnershipMappers::TeamYmlOwnership.new,
|
|
65
69
|
]
|
|
66
70
|
end
|
|
67
71
|
|
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.
|
|
4
|
+
version: 1.31.0
|
|
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-02-
|
|
11
|
+
date: 2023-02-22 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: code_teams
|
|
@@ -141,6 +141,7 @@ files:
|
|
|
141
141
|
- lib/code_ownership/private/ownership_mappers/js_package_ownership.rb
|
|
142
142
|
- lib/code_ownership/private/ownership_mappers/package_ownership.rb
|
|
143
143
|
- lib/code_ownership/private/ownership_mappers/team_globs.rb
|
|
144
|
+
- lib/code_ownership/private/ownership_mappers/team_yml_ownership.rb
|
|
144
145
|
- lib/code_ownership/private/parse_js_packages.rb
|
|
145
146
|
- lib/code_ownership/private/team_plugins/github.rb
|
|
146
147
|
- lib/code_ownership/private/team_plugins/ownership.rb
|
|
@@ -148,6 +149,7 @@ files:
|
|
|
148
149
|
- lib/code_ownership/private/validations/files_have_unique_owners.rb
|
|
149
150
|
- lib/code_ownership/private/validations/github_codeowners_up_to_date.rb
|
|
150
151
|
- lib/code_ownership/private/validations/interface.rb
|
|
152
|
+
- lib/code_ownership/private/validations/no_overlapping_globs.rb
|
|
151
153
|
- sorbet/config
|
|
152
154
|
- sorbet/rbi/gems/code_teams@1.0.0.rbi
|
|
153
155
|
- sorbet/rbi/gems/packs@0.0.2.rbi
|