code_ownership 1.28.0 → 1.28.2

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: d73cb8995d6430d05780252417863b38bd14a461bf8f3afe4b9724abb407efea
4
- data.tar.gz: 7cc3c3c4a2968b8e3a265f990c28395b0c4e6163b7ba48ad2b0c8be64123990c
3
+ metadata.gz: bf48240fd31979132287823a3f9d40d6b03776df405583c31a56cb87e6dfbe40
4
+ data.tar.gz: 1cbd9b0fee826c7a23dd71335043eab358f99157bb7f677a94b8d4abc1782f4e
5
5
  SHA512:
6
- metadata.gz: 6f2a2c2331aa980b414343e54429ba3ab367fa6a38cdad44811b84193afd8a6d3846baf77ae8b7cd78a2754b65865b5799644382ff5182ba0439bb3cb3884cf6
7
- data.tar.gz: d0ecc33dd542a3dc606caceb52fb38ed32743a12076f5253b96a2c2c6b7fa24a0b1445df6d1a41878ef350a87fe5075cbb17ebc5bb3964211cbac18ee005bfd5
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.
6
+
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.
7
8
 
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
@@ -31,6 +34,29 @@ 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
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.
@@ -71,7 +97,9 @@ 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
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.
@@ -16,7 +16,7 @@ module CodeOwnership
16
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
 
@@ -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
@@ -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) }
@@ -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,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: code_ownership
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.28.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-14 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
14
  name: code_teams
@@ -150,7 +150,7 @@ files:
150
150
  - lib/code_ownership/private/validations/interface.rb
151
151
  - sorbet/config
152
152
  - sorbet/rbi/gems/code_teams@1.0.0.rbi
153
- - sorbet/rbi/gems/parse_packwerk@0.7.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
156
  homepage: https://github.com/rubyatscale/code_ownership