code_ownership 1.34.2 → 1.36.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
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e34134e28ee70e58344ea6d3f90be157bbdd6945888eee07d73abf3db3ed873b
|
4
|
+
data.tar.gz: 1875f6d3131505551c163aa03413edefa86c6f279d2c3189d9663a74a9603758
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: de217fe525521395f2b6ad647257aecd69c9e8f8895fa0d466051cf4d365c3fce2dcf08ea9c9bfbeeef0c75116f3188d6f350c72becb965f7f3d49a992a0b6fa
|
7
|
+
data.tar.gz: abf92fcca79c8311cfa9d82fabcb0b129fdd076c9cb7a3db31c0db983dabf1e6cb5810b501e38cdab9fbf028dc3a43ed6105928469015b6bf30a33e774b5a6b6
|
data/README.md
CHANGED
@@ -73,6 +73,12 @@ js_package_paths:
|
|
73
73
|
|
74
74
|
This defaults `**/`, which makes it look for `package.json` files across your application.
|
75
75
|
|
76
|
+
> [!NOTE]
|
77
|
+
> Javscript package ownership does not respect `unowned_globs`. If you wish to disable usage of this feature you can set `js_package_paths` to an empty list.
|
78
|
+
```yml
|
79
|
+
js_package_paths: []
|
80
|
+
```
|
81
|
+
|
76
82
|
### Custom Ownership
|
77
83
|
To enable custom ownership, you can inject your own custom classes into `code_ownership`.
|
78
84
|
To do this, first create a class that adheres to the `CodeOwnership::Mapper` and/or `CodeOwnership::Validator` interface.
|
@@ -155,7 +161,7 @@ unowned_globs:
|
|
155
161
|
- app/services/some_file2.rb
|
156
162
|
- frontend/javascripts/**/__generated__/**/*
|
157
163
|
```
|
158
|
-
You can call the validation function with the Ruby API
|
164
|
+
You can call the validation function with the Ruby API
|
159
165
|
```ruby
|
160
166
|
CodeOwnership.validate!
|
161
167
|
```
|
@@ -11,6 +11,7 @@ module CodeOwnership
|
|
11
11
|
const :unbuilt_gems_path, T.nilable(String)
|
12
12
|
const :skip_codeowners_validation, T::Boolean
|
13
13
|
const :raw_hash, T::Hash[T.untyped, T.untyped]
|
14
|
+
const :require_github_teams, T::Boolean
|
14
15
|
|
15
16
|
sig { returns(Configuration) }
|
16
17
|
def self.fetch
|
@@ -27,7 +28,8 @@ module CodeOwnership
|
|
27
28
|
unowned_globs: config_hash.fetch('unowned_globs', []),
|
28
29
|
js_package_paths: js_package_paths(config_hash),
|
29
30
|
skip_codeowners_validation: config_hash.fetch('skip_codeowners_validation', false),
|
30
|
-
raw_hash: config_hash
|
31
|
+
raw_hash: config_hash,
|
32
|
+
require_github_teams: config_hash.fetch('require_github_teams', false)
|
31
33
|
)
|
32
34
|
end
|
33
35
|
|
@@ -10,6 +10,8 @@ module CodeOwnership
|
|
10
10
|
include Mapper
|
11
11
|
|
12
12
|
CODEOWNERS_DIRECTORY_FILE_NAME = '.codeowner'
|
13
|
+
RELATIVE_ROOT = Pathname('.').freeze
|
14
|
+
ABSOLUTE_ROOT = Pathname('/').freeze
|
13
15
|
|
14
16
|
@@directory_cache = T.let({}, T::Hash[String, T.nilable(CodeTeams::Team)]) # rubocop:disable Style/ClassVars
|
15
17
|
|
@@ -74,36 +76,46 @@ module CodeOwnership
|
|
74
76
|
)
|
75
77
|
end
|
76
78
|
|
77
|
-
#
|
79
|
+
# Takes a file and finds the relevant `.codeowner` file by walking up the directory
|
78
80
|
# structure. Example, given `a/b/c.rb`, this looks for `a/b/.codeowner`, `a/.codeowner`,
|
79
81
|
# and `.codeowner` in that order, stopping at the first file to actually exist.
|
80
|
-
#
|
82
|
+
# If the parovided file is a directory, it will look for `.codeowner` in that directory and then upwards.
|
83
|
+
# We do additional caching so that we don't have to check for file existence every time.
|
81
84
|
sig { params(file: String).returns(T.nilable(CodeTeams::Team)) }
|
82
85
|
def map_file_to_relevant_owner(file)
|
83
86
|
file_path = Pathname.new(file)
|
84
|
-
|
87
|
+
team = T.let(nil, T.nilable(CodeTeams::Team))
|
85
88
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
+
if File.directory?(file)
|
90
|
+
team = get_team_from_codeowners_file_within_directory(file_path)
|
91
|
+
end
|
92
|
+
|
93
|
+
while team.nil? && file_path != RELATIVE_ROOT && file_path != ABSOLUTE_ROOT
|
94
|
+
file_path = file_path.parent
|
95
|
+
team = get_team_from_codeowners_file_within_directory(file_path)
|
96
|
+
end
|
97
|
+
|
98
|
+
team
|
99
|
+
end
|
89
100
|
|
90
|
-
|
101
|
+
sig { params(directory: Pathname).returns(T.nilable(CodeTeams::Team)) }
|
102
|
+
def get_team_from_codeowners_file_within_directory(directory)
|
103
|
+
potential_codeowners_file = directory.join(CODEOWNERS_DIRECTORY_FILE_NAME)
|
91
104
|
|
92
|
-
|
93
|
-
if @@directory_cache.key?(potential_codeowners_file_name)
|
94
|
-
team = @@directory_cache[potential_codeowners_file_name]
|
95
|
-
elsif potential_codeowners_file.exist?
|
96
|
-
team = owner_for_codeowners_file(potential_codeowners_file)
|
105
|
+
potential_codeowners_file_name = potential_codeowners_file.to_s
|
97
106
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
107
|
+
team = nil
|
108
|
+
if @@directory_cache.key?(potential_codeowners_file_name)
|
109
|
+
team = @@directory_cache[potential_codeowners_file_name]
|
110
|
+
elsif potential_codeowners_file.exist?
|
111
|
+
team = owner_for_codeowners_file(potential_codeowners_file)
|
102
112
|
|
103
|
-
|
113
|
+
@@directory_cache[potential_codeowners_file_name] = team
|
114
|
+
else
|
115
|
+
@@directory_cache[potential_codeowners_file_name] = nil
|
104
116
|
end
|
105
117
|
|
106
|
-
|
118
|
+
return team
|
107
119
|
end
|
108
120
|
end
|
109
121
|
end
|
@@ -21,7 +21,7 @@ module CodeOwnership
|
|
21
21
|
|
22
22
|
sig { override.params(teams: T::Array[CodeTeams::Team]).returns(T::Array[String]) }
|
23
23
|
def self.validation_errors(teams)
|
24
|
-
all_github_teams = teams.flat_map { |team| self.for(team).github.team }
|
24
|
+
all_github_teams = teams.flat_map { |team| self.for(team).github.team }.compact
|
25
25
|
|
26
26
|
teams_used_more_than_once = all_github_teams.tally.select do |_team, count|
|
27
27
|
count > 1
|
@@ -29,6 +29,18 @@ module CodeOwnership
|
|
29
29
|
|
30
30
|
errors = T.let([], T::Array[String])
|
31
31
|
|
32
|
+
if require_github_teams?
|
33
|
+
missing_github_teams = teams.select { |team| self.for(team).github.team.nil? }
|
34
|
+
|
35
|
+
if missing_github_teams.any?
|
36
|
+
errors << <<~ERROR
|
37
|
+
The following teams are missing `github.team` entries:
|
38
|
+
|
39
|
+
#{missing_github_teams.map(&:config_yml).join("\n")}
|
40
|
+
ERROR
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
32
44
|
if teams_used_more_than_once.any?
|
33
45
|
errors << <<~ERROR
|
34
46
|
The following teams are specified multiple times:
|
@@ -40,6 +52,11 @@ module CodeOwnership
|
|
40
52
|
|
41
53
|
errors
|
42
54
|
end
|
55
|
+
|
56
|
+
sig { returns(T::Boolean) }
|
57
|
+
def self.require_github_teams?
|
58
|
+
CodeOwnership.configuration.require_github_teams
|
59
|
+
end
|
43
60
|
end
|
44
61
|
end
|
45
62
|
end
|
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.36.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-
|
11
|
+
date: 2023-12-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: code_teams
|