code_ownership 1.26.0 → 1.28.2

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: 988c067afbabcc65d5b697aea162ba1c288787e4d7d9a84a261b00f76859aa6b
4
- data.tar.gz: 6a504214d4470cfd2d1ab103f201069367e39962a390d34382410587a6067e40
3
+ metadata.gz: bf48240fd31979132287823a3f9d40d6b03776df405583c31a56cb87e6dfbe40
4
+ data.tar.gz: 1cbd9b0fee826c7a23dd71335043eab358f99157bb7f677a94b8d4abc1782f4e
5
5
  SHA512:
6
- metadata.gz: 16b3e48c3cb734857dd66cf03f9d43d89bb92ee3ab92abfc0550004274531e03eef4abc9157fab33e25d815dd5b5c6f055d65987e7526dcb4952212930935678
7
- data.tar.gz: 0f0cc9f4a1b8938e088bc258d5b247d633beaac3c68ddf37ea269fa3740d27d796b9773354e47855e79ecd5e958b49d97fd9f231f42502e62eab508d1d8ea9a1
6
+ metadata.gz: 68721e648bcd3e8888f3f94d33baf0d38b642c3d6104db0964e6aff3194860407e72c9ad88ffec357285006bff87490b49b92a238fbbf83d37509d34868ea0fe
7
+ data.tar.gz: 0d878620986f0fe3e6168fa8ea0db1a1a530d27c0f35410f70b3f876146df2b184f9db3486ef9e4e74c0583a067b48ad4462af6877d7452e5d1574bec61ebd8f
data/README.md CHANGED
@@ -1,14 +1,17 @@
1
1
  # CodeOwnership
2
- This gem helps engineering teams declare ownership of code.
3
2
 
4
- Check out `lib/code_ownership.rb` to see the public API.
3
+ This gem helps engineering teams declare ownership of code. This gem works best in large, usually monolithic code bases where many teams work together.
5
4
 
6
- Check out `code_ownership_spec.rb` to see examples of how code ownership is used.
5
+ Check out [`lib/code_ownership.rb`](https://github.com/rubyatscale/code_ownership/blob/main/lib/code_ownership.rb) to see the public API.
7
6
 
8
- There is also a [companion VSCode Extension]([url](https://github.com/bigrails/code-ownership-vscode)) for this gem. Just search `Gusto.code-ownership-vscode` in the VSCode Extension Marketplace.
7
+ Check out [`code_ownership_spec.rb`](https://github.com/rubyatscale/code_ownership/blob/main/spec/lib/code_ownership_spec.rb) to see examples of how code ownership is used.
8
+
9
+ There is also a [companion VSCode Extension]([url](https://github.com/rubyatscale/code-ownership-vscode)) for this gem. Just search `Gusto.code-ownership-vscode` in the VSCode Extension Marketplace.
9
10
 
10
11
  ## Usage: Declaring Ownership
12
+
11
13
  There are three ways to declare code ownership using this gem.
14
+
12
15
  ### Package-Based Ownership
13
16
  Package based ownership integrates [`packwerk`](https://github.com/Shopify/packwerk) and has ownership defined per package. To define that all files within a package are owned by one team, configure your `package.yml` like this:
14
17
  ```yml
@@ -19,7 +22,7 @@ metadata:
19
22
  ```
20
23
 
21
24
  ### Glob-Based Ownership
22
- In your team's configured YML (see [`bigrails-teams`](https://github.com/bigrails/bigrails-teams)), you can set `owned_globs` to be a glob of files your team owns. For example, in `my_team.yml`:
25
+ In your team's configured YML (see [`code_teams`](https://github.com/rubyatscale/code_teams)), you can set `owned_globs` to be a glob of files your team owns. For example, in `my_team.yml`:
23
26
  ```yml
24
27
  name: My Team
25
28
  owned_globs:
@@ -31,9 +34,32 @@ File annotations are a last resort if there is no clear home for your code. File
31
34
  ```ruby
32
35
  # @team MyTeam
33
36
  ```
37
+
38
+ ### Javascript Package Ownership
39
+ Javascript package based ownership allows you to specify an owenrship key in a `package.json`. To use this, configure your `package.json` like this:
40
+
41
+ ```json
42
+ {
43
+ // other keys
44
+ "metadata": {
45
+ "owner": "My Team"
46
+ }
47
+ // other keys
48
+ }
49
+ ```
50
+
51
+ You can also tell `code_ownership` where to find JS packages in the configuration, like this:
52
+ ```yml
53
+ js_package_paths:
54
+ - frontend/javascripts/packages/*
55
+ - frontend/other_location_for_packages/*
56
+ ```
57
+
58
+ This defaults `**/`, which makes it look for `package.json` files across your application.
59
+
34
60
  ## Usage: Reading CodeOwnership
35
61
  ### `for_file`
36
- `CodeOwnership.for_file`, given a relative path to a file returns a `Teams::Team` if there is a team that owns the file, `nil` otherwise.
62
+ `CodeOwnership.for_file`, given a relative path to a file returns a `CodeTeams::Team` if there is a team that owns the file, `nil` otherwise.
37
63
 
38
64
  ```ruby
39
65
  CodeOwnership.for_file('path/to/file/relative/to/application/root.rb')
@@ -44,7 +70,7 @@ Contributor note: If you are making updates to this method or the methods gettin
44
70
  See `code_ownership_spec.rb` for examples.
45
71
 
46
72
  ### `for_backtrace`
47
- `CodeOwnership.for_backtrace` can be given a backtrace and will either return `nil`, or a `Teams::Team`.
73
+ `CodeOwnership.for_backtrace` can be given a backtrace and will either return `nil`, or a `CodeTeams::Team`.
48
74
 
49
75
  ```ruby
50
76
  CodeOwnership.for_backtrace(exception.backtrace)
@@ -56,7 +82,7 @@ See `code_ownership_spec.rb` for an example.
56
82
 
57
83
  ### `for_class`
58
84
 
59
- `CodeOwnership.for_class` can be given a class and will either return `nil`, or a `Teams::Team`.
85
+ `CodeOwnership.for_class` can be given a class and will either return `nil`, or a `CodeTeams::Team`.
60
86
 
61
87
  ```ruby
62
88
  CodeOwnership.for_class(MyClass.name)
@@ -71,9 +97,11 @@ See `code_ownership_spec.rb` for an example.
71
97
  A `CODEOWNERS` file defines who owns specific files or paths in a repository. When you run `bin/codeownership validate`, a `.github/CODEOWNERS` file will automatically be generated and updated.
72
98
 
73
99
  ## Proper Configuration & Validation
100
+
74
101
  CodeOwnership comes with a validation function to ensure the following things are true:
102
+
75
103
  1) Only one mechanism is defining file ownership. That is -- you can't have a file annotation on a file owned via package-based or glob-based ownership. This helps make ownership behavior more clear by avoiding concerns about precedence.
76
- 2) All teams referenced as an owner for any file or package is a valid team (i.e. it's in the list of `Teams.all`).
104
+ 2) All teams referenced as an owner for any file or package is a valid team (i.e. it's in the list of `CodeTeams.all`).
77
105
  3) All files have ownership. You can specify in `unowned_globs` to represent a TODO list of files to add ownership to.
78
106
  3) The `.github/CODEOWNERS` file is up to date. This is automatically corrected and staged unless specified otherwise with `bin/codeownership validate --skip-autocorrect --skip-stage`. You can turn this validation off by setting `skip_codeowners_validation: true` in `code_ownership.yml`.
79
107
 
@@ -18,13 +18,13 @@ module CodeOwnership
18
18
  extend T::Sig
19
19
  include Interface
20
20
 
21
- @@map_files_to_owners = T.let({}, T.nilable(T::Hash[String, T.nilable(::Teams::Team)])) # rubocop:disable Style/ClassVars
21
+ @@map_files_to_owners = T.let({}, T.nilable(T::Hash[String, T.nilable(::CodeTeams::Team)])) # rubocop:disable Style/ClassVars
22
22
 
23
23
  TEAM_PATTERN = T.let(/\A(?:#|\/\/) @team (?<team>.*)\Z/.freeze, Regexp)
24
24
 
25
25
  sig do
26
26
  override.params(file: String).
27
- returns(T.nilable(::Teams::Team))
27
+ returns(T.nilable(::CodeTeams::Team))
28
28
  end
29
29
  def map_file_to_owner(file)
30
30
  file_annotation_based_owner(file)
@@ -33,7 +33,7 @@ module CodeOwnership
33
33
  sig do
34
34
  override.
35
35
  params(files: T::Array[String]).
36
- returns(T::Hash[String, T.nilable(::Teams::Team)])
36
+ returns(T::Hash[String, T.nilable(::CodeTeams::Team)])
37
37
  end
38
38
  def map_files_to_owners(files)
39
39
  return @@map_files_to_owners if @@map_files_to_owners&.keys && @@map_files_to_owners.keys.count > 0
@@ -46,7 +46,7 @@ module CodeOwnership
46
46
  end
47
47
  end
48
48
 
49
- sig { params(filename: String).returns(T.nilable(Teams::Team)) }
49
+ sig { params(filename: String).returns(T.nilable(CodeTeams::Team)) }
50
50
  def file_annotation_based_owner(filename)
51
51
  # If for a directory is named with an ownable extension, we need to skip
52
52
  # so File.foreach doesn't blow up below. This was needed because Cypress
@@ -97,7 +97,7 @@ module CodeOwnership
97
97
  end
98
98
 
99
99
  sig do
100
- override.returns(T::Hash[String, T.nilable(::Teams::Team)])
100
+ override.returns(T::Hash[String, T.nilable(::CodeTeams::Team)])
101
101
  end
102
102
  def codeowners_lines_to_owners
103
103
  @@map_files_to_owners = nil # rubocop:disable Style/ClassVars
@@ -16,7 +16,7 @@ module CodeOwnership
16
16
  #
17
17
  sig do
18
18
  abstract.params(file: String).
19
- returns(T.nilable(::Teams::Team))
19
+ returns(T.nilable(::CodeTeams::Team))
20
20
  end
21
21
  def map_file_to_owner(file)
22
22
  end
@@ -26,13 +26,13 @@ module CodeOwnership
26
26
  #
27
27
  sig do
28
28
  abstract.params(files: T::Array[String]).
29
- returns(T::Hash[String, T.nilable(::Teams::Team)])
29
+ returns(T::Hash[String, T.nilable(::CodeTeams::Team)])
30
30
  end
31
31
  def map_files_to_owners(files)
32
32
  end
33
33
 
34
34
  sig do
35
- abstract.returns(T::Hash[String, T.nilable(::Teams::Team)])
35
+ abstract.returns(T::Hash[String, T.nilable(::CodeTeams::Team)])
36
36
  end
37
37
  def codeowners_lines_to_owners
38
38
  end
@@ -13,7 +13,7 @@ module CodeOwnership
13
13
 
14
14
  sig do
15
15
  override.params(file: String).
16
- returns(T.nilable(::Teams::Team))
16
+ returns(T.nilable(::CodeTeams::Team))
17
17
  end
18
18
  def map_file_to_owner(file)
19
19
  package = map_file_to_relevant_package(file)
@@ -26,7 +26,7 @@ module CodeOwnership
26
26
  sig do
27
27
  override.
28
28
  params(files: T::Array[String]).
29
- returns(T::Hash[String, T.nilable(::Teams::Team)])
29
+ returns(T::Hash[String, T.nilable(::CodeTeams::Team)])
30
30
  end
31
31
  def map_files_to_owners(files) # rubocop:disable Lint/UnusedMethodArgument
32
32
  ParseJsPackages.all.each_with_object({}) do |package, res|
@@ -49,7 +49,7 @@ module CodeOwnership
49
49
  # subset of files, but rather we want code ownership for all files.
50
50
  #
51
51
  sig do
52
- override.returns(T::Hash[String, T.nilable(::Teams::Team)])
52
+ override.returns(T::Hash[String, T.nilable(::CodeTeams::Team)])
53
53
  end
54
54
  def codeowners_lines_to_owners
55
55
  ParseJsPackages.all.each_with_object({}) do |package, res|
@@ -65,7 +65,7 @@ module CodeOwnership
65
65
  'Owner metadata key in package.json'
66
66
  end
67
67
 
68
- sig { params(package: ParseJsPackages::Package).returns(T.nilable(Teams::Team)) }
68
+ sig { params(package: ParseJsPackages::Package).returns(T.nilable(CodeTeams::Team)) }
69
69
  def owner_for_package(package)
70
70
  raw_owner_value = package.metadata['owner']
71
71
  return nil if !raw_owner_value
@@ -13,10 +13,10 @@ module CodeOwnership
13
13
 
14
14
  sig do
15
15
  override.params(file: String).
16
- returns(T.nilable(::Teams::Team))
16
+ returns(T.nilable(::CodeTeams::Team))
17
17
  end
18
18
  def map_file_to_owner(file)
19
- package = map_file_to_relevant_package(file)
19
+ package = ParsePackwerk.package_from_path(file)
20
20
 
21
21
  return nil if package.nil?
22
22
 
@@ -26,7 +26,7 @@ module CodeOwnership
26
26
  sig do
27
27
  override.
28
28
  params(files: T::Array[String]).
29
- returns(T::Hash[String, T.nilable(::Teams::Team)])
29
+ returns(T::Hash[String, T.nilable(::CodeTeams::Team)])
30
30
  end
31
31
  def map_files_to_owners(files) # rubocop:disable Lint/UnusedMethodArgument
32
32
  ParsePackwerk.all.each_with_object({}) do |package, res|
@@ -49,7 +49,7 @@ module CodeOwnership
49
49
  # subset of files, but rather we want code ownership for all files.
50
50
  #
51
51
  sig do
52
- override.returns(T::Hash[String, T.nilable(::Teams::Team)])
52
+ override.returns(T::Hash[String, T.nilable(::CodeTeams::Team)])
53
53
  end
54
54
  def codeowners_lines_to_owners
55
55
  ParsePackwerk.all.each_with_object({}) do |package, res|
@@ -65,7 +65,7 @@ module CodeOwnership
65
65
  'Owner metadata key in package.yml'
66
66
  end
67
67
 
68
- sig { params(package: ParsePackwerk::Package).returns(T.nilable(Teams::Team)) }
68
+ sig { params(package: ParsePackwerk::Package).returns(T.nilable(CodeTeams::Team)) }
69
69
  def owner_for_package(package)
70
70
  raw_owner_value = package.metadata['owner']
71
71
  return nil if !raw_owner_value
@@ -80,41 +80,6 @@ module CodeOwnership
80
80
  def bust_caches!
81
81
  @@package_yml_cache = {} # rubocop:disable Style/ClassVars
82
82
  end
83
-
84
- private
85
-
86
- # takes a file and finds the relevant `package.yml` file by walking up the directory
87
- # structure. Example, given `packs/a/b/c.rb`, this looks for `packs/a/b/package.yml`, `packs/a/package.yml`,
88
- # `packs/package.yml`, and `package.yml` in that order, stopping at the first file to actually exist.
89
- # We do additional caching so that we don't have to check for file existence every time
90
- sig { params(file: String).returns(T.nilable(ParsePackwerk::Package)) }
91
- def map_file_to_relevant_package(file)
92
- file_path = Pathname.new(file)
93
- path_components = file_path.each_filename.to_a.map { |path| Pathname.new(path) }
94
-
95
- (path_components.length - 1).downto(0).each do |i|
96
- potential_relative_path_name = T.must(path_components[0...i]).reduce(Pathname.new('')) { |built_path, path| built_path.join(path) }
97
- potential_package_yml_path = potential_relative_path_name.
98
- join(ParsePackwerk::PACKAGE_YML_NAME)
99
-
100
- potential_package_yml_string = potential_package_yml_path.to_s
101
-
102
- package = nil
103
- if @@package_yml_cache.key?(potential_package_yml_string)
104
- package = @@package_yml_cache[potential_package_yml_string]
105
- elsif potential_package_yml_path.exist?
106
- package = ParsePackwerk::Package.from(potential_package_yml_path)
107
-
108
- @@package_yml_cache[potential_package_yml_string] = package
109
- else
110
- @@package_yml_cache[potential_package_yml_string] = nil
111
- end
112
-
113
- return package unless package.nil?
114
- end
115
-
116
- nil
117
- end
118
83
  end
119
84
  end
120
85
  end
@@ -9,20 +9,20 @@ module CodeOwnership
9
9
  extend T::Sig
10
10
  include Interface
11
11
 
12
- @@map_files_to_owners = T.let(@map_files_to_owners, T.nilable(T::Hash[String, T.nilable(::Teams::Team)])) # rubocop:disable Style/ClassVars
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
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(::Teams::Team)])) # 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
15
  @@codeowners_lines_to_owners = {} # rubocop:disable Style/ClassVars
16
16
 
17
17
  sig do
18
18
  override.
19
19
  params(files: T::Array[String]).
20
- returns(T::Hash[String, T.nilable(::Teams::Team)])
20
+ returns(T::Hash[String, T.nilable(::CodeTeams::Team)])
21
21
  end
22
22
  def map_files_to_owners(files) # rubocop:disable Lint/UnusedMethodArgument
23
23
  return @@map_files_to_owners if @@map_files_to_owners&.keys && @@map_files_to_owners.keys.count > 0
24
24
 
25
- @@map_files_to_owners = Teams.all.each_with_object({}) do |team, map| # rubocop:disable Style/ClassVars
25
+ @@map_files_to_owners = CodeTeams.all.each_with_object({}) do |team, map| # rubocop:disable Style/ClassVars
26
26
  TeamPlugins::Ownership.for(team).owned_globs.each do |glob|
27
27
  Dir.glob(glob).each do |filename|
28
28
  map[filename] = team
@@ -33,19 +33,19 @@ module CodeOwnership
33
33
 
34
34
  sig do
35
35
  override.params(file: String).
36
- returns(T.nilable(::Teams::Team))
36
+ returns(T.nilable(::CodeTeams::Team))
37
37
  end
38
38
  def map_file_to_owner(file)
39
39
  map_files_to_owners([file])[file]
40
40
  end
41
41
 
42
42
  sig do
43
- override.returns(T::Hash[String, T.nilable(::Teams::Team)])
43
+ override.returns(T::Hash[String, T.nilable(::CodeTeams::Team)])
44
44
  end
45
45
  def codeowners_lines_to_owners
46
46
  return @@codeowners_lines_to_owners if @@codeowners_lines_to_owners&.keys && @@codeowners_lines_to_owners.keys.count > 0
47
47
 
48
- @@codeowners_lines_to_owners = Teams.all.each_with_object({}) do |team, map| # rubocop:disable Style/ClassVars
48
+ @@codeowners_lines_to_owners = CodeTeams.all.each_with_object({}) do |team, map| # rubocop:disable Style/ClassVars
49
49
  TeamPlugins::Ownership.for(team).owned_globs.each do |owned_glob|
50
50
  map[owned_glob] = team
51
51
  end
@@ -32,6 +32,16 @@ module CodeOwnership
32
32
  name: package_name,
33
33
  metadata: package_loaded_json[METADATA] || {}
34
34
  )
35
+ rescue JSON::ParserError => e
36
+ error_message = <<~MESSAGE
37
+ #{e.inspect}
38
+
39
+ #{pathname} has invalid JSON, so code ownership cannot be determined.
40
+
41
+ Please either make the JSON in that file valid or specify `js_package_paths` in config/code_ownership.yml.
42
+ MESSAGE
43
+
44
+ raise InvalidCodeOwnershipConfigurationError.new(error_message)
35
45
  end
36
46
 
37
47
  sig { returns(Pathname) }
@@ -3,7 +3,7 @@
3
3
  module CodeOwnership
4
4
  module Private
5
5
  module TeamPlugins
6
- class Github < Teams::Plugin
6
+ class Github < CodeTeams::Plugin
7
7
  extend T::Sig
8
8
  extend T::Helpers
9
9
 
@@ -3,7 +3,7 @@
3
3
  module CodeOwnership
4
4
  module Private
5
5
  module TeamPlugins
6
- class Ownership < Teams::Plugin
6
+ class Ownership < CodeTeams::Plugin
7
7
  extend T::Sig
8
8
  extend T::Helpers
9
9
 
@@ -25,24 +25,66 @@ module CodeOwnership
25
25
  # https://help.github.com/en/articles/about-code-owners
26
26
  HEADER
27
27
 
28
- contents = [
29
- header,
28
+ expected_content_lines = [
29
+ *header.split("\n"),
30
+ nil, # For line between header and codeowners_file_lines
30
31
  *codeowners_file_lines,
31
32
  nil, # For end-of-file newline
32
- ].join("\n")
33
+ ]
34
+
35
+ expected_contents = expected_content_lines.join("\n")
36
+ actual_contents = codeowners_filepath.exist? ? codeowners_filepath.read : ""
37
+ actual_content_lines = actual_contents.split("\n")
33
38
 
34
- codeowners_up_to_date = codeowners_filepath.exist? && codeowners_filepath.read == contents
39
+ codeowners_up_to_date = actual_contents == expected_contents
35
40
 
36
41
  errors = T.let([], T::Array[String])
37
42
 
38
43
  if !codeowners_up_to_date
39
44
  if autocorrect
40
- codeowners_filepath.write(contents)
45
+ codeowners_filepath.write(expected_contents)
41
46
  if stage_changes
42
47
  `git add #{codeowners_filepath}`
43
48
  end
44
49
  else
45
- errors << "CODEOWNERS out of date. Ensure pre-commit hook is set up correctly and used. You can also run bin/codeownership validate to update the CODEOWNERS file\n"
50
+ # If there is no current file or its empty, display a shorter message.
51
+ missing_lines = expected_content_lines - actual_content_lines
52
+ extra_lines = actual_content_lines - expected_content_lines
53
+ missing_lines_text = if missing_lines.any?
54
+ <<~COMMENT
55
+ CODEOWNERS should contain the following lines, but does not:
56
+ #{(expected_content_lines - actual_content_lines).map { |line| "- \"#{line}\""}.join("\n")}
57
+ COMMENT
58
+ end
59
+
60
+ extra_lines_text = if extra_lines.any?
61
+ <<~COMMENT
62
+ CODEOWNERS should not contain the following lines, but it does:
63
+ #{(actual_content_lines - expected_content_lines).map { |line| "- \"#{line}\""}.join("\n")}
64
+ COMMENT
65
+ end
66
+
67
+ diff_text = if missing_lines_text && extra_lines_text
68
+ "#{missing_lines_text}\n#{extra_lines_text}".chomp
69
+ elsif missing_lines_text
70
+ missing_lines_text
71
+ elsif extra_lines_text
72
+ extra_lines_text
73
+ else
74
+ ""
75
+ end
76
+
77
+ if actual_contents == ""
78
+ errors << <<~CODEOWNERS_ERROR
79
+ CODEOWNERS out of date. Run `bin/codeownership validate` to update the CODEOWNERS file
80
+ CODEOWNERS_ERROR
81
+ else
82
+ errors << <<~CODEOWNERS_ERROR
83
+ CODEOWNERS out of date. Run `bin/codeownership validate` to update the CODEOWNERS file
84
+
85
+ #{diff_text.chomp}
86
+ CODEOWNERS_ERROR
87
+ end
46
88
  end
47
89
  end
48
90
 
@@ -56,7 +98,7 @@ module CodeOwnership
56
98
  # https://help.github.com/articles/about-codeowners/
57
99
  sig { returns(T::Array[String]) }
58
100
  def codeowners_file_lines
59
- github_team_map = Teams.all.each_with_object({}) do |team, map|
101
+ github_team_map = CodeTeams.all.each_with_object({}) do |team, map|
60
102
  team_github = TeamPlugins::Github.for(team).github
61
103
  next if team_github.do_not_add_to_codeowners_file
62
104
 
@@ -50,7 +50,7 @@ module CodeOwnership
50
50
  end
51
51
 
52
52
  if errors.any?
53
- errors << 'See https://github.com/bigrails/code_ownership#README.md for more details'
53
+ errors << 'See https://github.com/rubyatscale/code_ownership#README.md for more details'
54
54
  raise InvalidCodeOwnershipConfigurationError.new(errors.join("\n")) # rubocop:disable Style/RaiseArgs
55
55
  end
56
56
  end
@@ -92,11 +92,11 @@ module CodeOwnership
92
92
  @tracked_files ||= Dir.glob(configuration.owned_globs)
93
93
  end
94
94
 
95
- sig { params(team_name: String, location_of_reference: String).returns(Teams::Team) }
95
+ sig { params(team_name: String, location_of_reference: String).returns(CodeTeams::Team) }
96
96
  def self.find_team!(team_name, location_of_reference)
97
- found_team = Teams.find(team_name)
97
+ found_team = CodeTeams.find(team_name)
98
98
  if found_team.nil?
99
- raise StandardError, "Could not find team with name: `#{team_name}` in #{location_of_reference}. Make sure the team is one of `#{Teams.all.map(&:name).sort}`"
99
+ raise StandardError, "Could not find team with name: `#{team_name}` in #{location_of_reference}. Make sure the team is one of `#{CodeTeams.all.map(&:name).sort}`"
100
100
  else
101
101
  found_team
102
102
  end
@@ -3,7 +3,7 @@
3
3
  # typed: strict
4
4
 
5
5
  require 'set'
6
- require 'teams'
6
+ require 'code_teams'
7
7
  require 'sorbet-runtime'
8
8
  require 'json'
9
9
  require 'parse_packwerk'
@@ -17,15 +17,15 @@ module CodeOwnership
17
17
 
18
18
  requires_ancestor { Kernel }
19
19
 
20
- sig { params(file: String).returns(T.nilable(Teams::Team)) }
20
+ sig { params(file: String).returns(T.nilable(CodeTeams::Team)) }
21
21
  def for_file(file)
22
- @for_file ||= T.let(@for_file, T.nilable(T::Hash[String, T.nilable(Teams::Team)]))
22
+ @for_file ||= T.let(@for_file, T.nilable(T::Hash[String, T.nilable(CodeTeams::Team)]))
23
23
  @for_file ||= {}
24
24
 
25
25
  return nil if file.start_with?('./')
26
26
  return @for_file[file] if @for_file.key?(file)
27
27
 
28
- owner = T.let(nil, T.nilable(Teams::Team))
28
+ owner = T.let(nil, T.nilable(CodeTeams::Team))
29
29
 
30
30
  Private.mappers.each do |mapper|
31
31
  owner = mapper.map_file_to_owner(file)
@@ -61,7 +61,7 @@ module CodeOwnership
61
61
 
62
62
  # Given a backtrace from either `Exception#backtrace` or `caller`, find the
63
63
  # first line that corresponds to a file with assigned ownership
64
- sig { params(backtrace: T.nilable(T::Array[String]), excluded_teams: T::Array[::Teams::Team]).returns(T.nilable(::Teams::Team)) }
64
+ sig { params(backtrace: T.nilable(T::Array[String]), excluded_teams: T::Array[::CodeTeams::Team]).returns(T.nilable(::CodeTeams::Team)) }
65
65
  def for_backtrace(backtrace, excluded_teams: [])
66
66
  return unless backtrace
67
67
 
@@ -93,9 +93,9 @@ module CodeOwnership
93
93
  nil
94
94
  end
95
95
 
96
- sig { params(klass: T.nilable(T.any(Class, Module))).returns(T.nilable(::Teams::Team)) }
96
+ sig { params(klass: T.nilable(T.any(Class, Module))).returns(T.nilable(::CodeTeams::Team)) }
97
97
  def for_class(klass)
98
- @memoized_values ||= T.let(@memoized_values, T.nilable(T::Hash[String, T.nilable(::Teams::Team)]))
98
+ @memoized_values ||= T.let(@memoized_values, T.nilable(T::Hash[String, T.nilable(::CodeTeams::Team)]))
99
99
  @memoized_values ||= {}
100
100
  # We use key because the memoized value could be `nil`
101
101
  if !@memoized_values.key?(klass.to_s)
@@ -110,7 +110,7 @@ module CodeOwnership
110
110
  end
111
111
  end
112
112
 
113
- sig { params(package: ParsePackwerk::Package).returns(T.nilable(::Teams::Team)) }
113
+ sig { params(package: ParsePackwerk::Package).returns(T.nilable(::CodeTeams::Team)) }
114
114
  def for_package(package)
115
115
  Private::OwnershipMappers::PackageOwnership.new.owner_for_package(package)
116
116
  end
@@ -1,78 +1,78 @@
1
1
  # typed: true
2
2
 
3
3
  # DO NOT EDIT MANUALLY
4
- # This is an autogenerated file for types exported from the `bigrails-teams` gem.
5
- # Please instead update this file by running `bin/tapioca gem bigrails-teams`.
4
+ # This is an autogenerated file for types exported from the `code_teams` gem.
5
+ # Please instead update this file by running `bin/tapioca gem code_teams`.
6
6
 
7
- module Teams
7
+ module CodeTeams
8
8
  class << self
9
- sig { returns(T::Array[::Teams::Team]) }
9
+ sig { returns(T::Array[::CodeTeams::Team]) }
10
10
  def all; end
11
11
 
12
12
  sig { void }
13
13
  def bust_caches!; end
14
14
 
15
- sig { params(name: ::String).returns(T.nilable(::Teams::Team)) }
15
+ sig { params(name: ::String).returns(T.nilable(::CodeTeams::Team)) }
16
16
  def find(name); end
17
17
 
18
- sig { params(dir: ::String).returns(T::Array[::Teams::Team]) }
18
+ sig { params(dir: ::String).returns(T::Array[::CodeTeams::Team]) }
19
19
  def for_directory(dir); end
20
20
 
21
21
  sig { params(string: ::String).returns(::String) }
22
22
  def tag_value_for(string); end
23
23
 
24
- sig { params(teams: T::Array[::Teams::Team]).returns(T::Array[::String]) }
24
+ sig { params(teams: T::Array[::CodeTeams::Team]).returns(T::Array[::String]) }
25
25
  def validation_errors(teams); end
26
26
  end
27
27
  end
28
28
 
29
- class Teams::IncorrectPublicApiUsageError < ::StandardError; end
29
+ class CodeTeams::IncorrectPublicApiUsageError < ::StandardError; end
30
30
 
31
- class Teams::Plugin
31
+ class CodeTeams::Plugin
32
32
  abstract!
33
33
 
34
- sig { params(team: ::Teams::Team).void }
34
+ sig { params(team: ::CodeTeams::Team).void }
35
35
  def initialize(team); end
36
36
 
37
37
  class << self
38
- sig { returns(T::Array[T.class_of(Teams::Plugin)]) }
38
+ sig { returns(T::Array[T.class_of(CodeTeams::Plugin)]) }
39
39
  def all_plugins; end
40
40
 
41
- sig { params(team: ::Teams::Team).returns(T.attached_class) }
41
+ sig { params(team: ::CodeTeams::Team).returns(T.attached_class) }
42
42
  def for(team); end
43
43
 
44
44
  sig { params(base: T.untyped).void }
45
45
  def inherited(base); end
46
46
 
47
- sig { params(team: ::Teams::Team, key: ::String).returns(::String) }
47
+ sig { params(team: ::CodeTeams::Team, key: ::String).returns(::String) }
48
48
  def missing_key_error_message(team, key); end
49
49
 
50
- sig { params(teams: T::Array[::Teams::Team]).returns(T::Array[::String]) }
50
+ sig { params(teams: T::Array[::CodeTeams::Team]).returns(T::Array[::String]) }
51
51
  def validation_errors(teams); end
52
52
 
53
53
  private
54
54
 
55
- sig { params(team: ::Teams::Team).returns(T.attached_class) }
55
+ sig { params(team: ::CodeTeams::Team).returns(T.attached_class) }
56
56
  def register_team(team); end
57
57
 
58
- sig { returns(T::Hash[T.nilable(::String), T::Hash[::Class, ::Teams::Plugin]]) }
58
+ sig { returns(T::Hash[T.nilable(::String), T::Hash[::Class, ::CodeTeams::Plugin]]) }
59
59
  def registry; end
60
60
  end
61
61
  end
62
62
 
63
- module Teams::Plugins; end
63
+ module CodeTeams::Plugins; end
64
64
 
65
- class Teams::Plugins::Identity < ::Teams::Plugin
66
- sig { returns(::Teams::Plugins::Identity::IdentityStruct) }
65
+ class CodeTeams::Plugins::Identity < ::CodeTeams::Plugin
66
+ sig { returns(::CodeTeams::Plugins::Identity::IdentityStruct) }
67
67
  def identity; end
68
68
 
69
69
  class << self
70
- sig { override.params(teams: T::Array[::Teams::Team]).returns(T::Array[::String]) }
70
+ sig { override.params(teams: T::Array[::CodeTeams::Team]).returns(T::Array[::String]) }
71
71
  def validation_errors(teams); end
72
72
  end
73
73
  end
74
74
 
75
- class Teams::Plugins::Identity::IdentityStruct < ::Struct
75
+ class CodeTeams::Plugins::Identity::IdentityStruct < ::Struct
76
76
  def name; end
77
77
  def name=(_); end
78
78
 
@@ -84,7 +84,7 @@ class Teams::Plugins::Identity::IdentityStruct < ::Struct
84
84
  end
85
85
  end
86
86
 
87
- class Teams::Team
87
+ class CodeTeams::Team
88
88
  sig { params(config_yml: T.nilable(::String), raw_hash: T::Hash[T.untyped, T.untyped]).void }
89
89
  def initialize(config_yml:, raw_hash:); end
90
90
 
@@ -109,12 +109,12 @@ class Teams::Team
109
109
  def to_tag; end
110
110
 
111
111
  class << self
112
- sig { params(raw_hash: T::Hash[T.untyped, T.untyped]).returns(::Teams::Team) }
112
+ sig { params(raw_hash: T::Hash[T.untyped, T.untyped]).returns(::CodeTeams::Team) }
113
113
  def from_hash(raw_hash); end
114
114
 
115
- sig { params(config_yml: ::String).returns(::Teams::Team) }
115
+ sig { params(config_yml: ::String).returns(::CodeTeams::Team) }
116
116
  def from_yml(config_yml); end
117
117
  end
118
118
  end
119
119
 
120
- Teams::UNKNOWN_TEAM_STRING = T.let(T.unsafe(nil), String)
120
+ CodeTeams::UNKNOWN_TEAM_STRING = T.let(T.unsafe(nil), String)
@@ -6,12 +6,18 @@
6
6
 
7
7
  module ParsePackwerk
8
8
  class << self
9
- sig { params(package_yml_pathnames: T.nilable(T::Array[::Pathname])).returns(T::Array[::ParsePackwerk::Package]) }
10
- def all(package_yml_pathnames: T.unsafe(nil)); end
9
+ sig { returns(T::Array[::ParsePackwerk::Package]) }
10
+ def all; end
11
+
12
+ sig { void }
13
+ def bust_cache!; end
11
14
 
12
15
  sig { params(name: ::String).returns(T.nilable(::ParsePackwerk::Package)) }
13
16
  def find(name); end
14
17
 
18
+ sig { params(file_path: T.any(::Pathname, ::String)).returns(T.nilable(::ParsePackwerk::Package)) }
19
+ def package_from_path(file_path); end
20
+
15
21
  sig { params(package: ::ParsePackwerk::Package).void }
16
22
  def write_package_yml!(package); end
17
23
 
@@ -27,12 +33,24 @@ end
27
33
 
28
34
  class ParsePackwerk::Configuration < ::T::Struct
29
35
  const :exclude, T::Array[::String]
36
+ const :package_paths, T::Array[::String]
30
37
 
31
38
  class << self
39
+ sig { params(config_hash: T::Hash[T.untyped, T.untyped]).returns(T::Array[::String]) }
40
+ def excludes(config_hash); end
41
+
42
+ sig { returns(::ParsePackwerk::Configuration) }
43
+ def fetch; end
44
+
32
45
  def inherited(s); end
46
+
47
+ sig { params(config_hash: T::Hash[T.untyped, T.untyped]).returns(T::Array[::String]) }
48
+ def package_paths(config_hash); end
33
49
  end
34
50
  end
35
51
 
52
+ ParsePackwerk::DEFAULT_EXCLUDE_GLOBS = T.let(T.unsafe(nil), Array)
53
+ ParsePackwerk::DEFAULT_PACKAGE_PATHS = T.let(T.unsafe(nil), Array)
36
54
  ParsePackwerk::DEPENDENCIES = T.let(T.unsafe(nil), String)
37
55
  ParsePackwerk::DEPRECATED_REFERENCES_YML_NAME = T.let(T.unsafe(nil), String)
38
56
 
@@ -91,6 +109,23 @@ class ParsePackwerk::Package < ::T::Struct
91
109
  end
92
110
  end
93
111
 
112
+ class ParsePackwerk::PackageSet
113
+ class << self
114
+ sig do
115
+ params(
116
+ package_pathspec: T::Array[::String],
117
+ exclude_pathspec: T::Array[::String]
118
+ ).returns(T::Array[::ParsePackwerk::Package])
119
+ end
120
+ def from(package_pathspec:, exclude_pathspec:); end
121
+
122
+ private
123
+
124
+ sig { params(globs: T::Array[::String], path: ::Pathname).returns(T::Boolean) }
125
+ def exclude_path?(globs, path); end
126
+ end
127
+ end
128
+
94
129
  ParsePackwerk::ROOT_PACKAGE_NAME = T.let(T.unsafe(nil), String)
95
130
 
96
131
  class ParsePackwerk::Violation < ::T::Struct
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: code_ownership
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.26.0
4
+ version: 1.28.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gusto Engineers
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-06-01 00:00:00.000000000 Z
11
+ date: 2022-08-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: bigrails-teams
14
+ name: code_teams
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '1.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: '1.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: parse_packwerk
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -149,17 +149,17 @@ files:
149
149
  - lib/code_ownership/private/validations/github_codeowners_up_to_date.rb
150
150
  - lib/code_ownership/private/validations/interface.rb
151
151
  - sorbet/config
152
- - sorbet/rbi/gems/bigrails-teams@0.1.0.rbi
153
- - sorbet/rbi/gems/parse_packwerk@0.7.0.rbi
152
+ - sorbet/rbi/gems/code_teams@1.0.0.rbi
153
+ - sorbet/rbi/gems/parse_packwerk@0.12.0.rbi
154
154
  - sorbet/rbi/manual.rbi
155
155
  - sorbet/rbi/todo.rbi
156
- homepage: https://github.com/bigrails/code_ownership
156
+ homepage: https://github.com/rubyatscale/code_ownership
157
157
  licenses:
158
158
  - MIT
159
159
  metadata:
160
- homepage_uri: https://github.com/bigrails/code_ownership
161
- source_code_uri: https://github.com/bigrails/code_ownership
162
- changelog_uri: https://github.com/bigrails/code_ownership/releases
160
+ homepage_uri: https://github.com/rubyatscale/code_ownership
161
+ source_code_uri: https://github.com/rubyatscale/code_ownership
162
+ changelog_uri: https://github.com/rubyatscale/code_ownership/releases
163
163
  allowed_push_host: https://rubygems.org
164
164
  post_install_message:
165
165
  rdoc_options: []