package_protections 2.3.0 → 2.5.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: ba0b3c74ccdd20872e0cf789b6cf062e918ff25d6aa2c70515939f3cd57c4f17
4
- data.tar.gz: '08c71c84b5a76786ff42b5c9e065afdea30a3ceb38775d0ca0b20c9e10ca568b'
3
+ metadata.gz: 15fbea313e27bfc23cc01afc2bbae8e5851a3008b376952c05868cf50dfe3603
4
+ data.tar.gz: 0dfd11a1d3985011213dac38f6e60e46f8891ead717fd273b11ece18056929a9
5
5
  SHA512:
6
- metadata.gz: ccea3e0cf794040c52d283816e3905571973917e4d777b655dabbc15f871bb76672097f5c00897972e239a5146b14c6aa10b5ecdec1c6e6998be93bf2d0654ce
7
- data.tar.gz: 7c33132a1fb7d27aaaa154254315776498dbe58654ebe6f3cfbbd2d3e8efe4b2067fa3dcde1cf6cb8ef06e1d5be79b00915bd7bc2343b8bd7544e7328607213c
6
+ metadata.gz: 89215ad6809c4dc4de07dc07f87cbbd7f163feeed780c23ca43ea93e4fa0e47b9a0fcda22a183b6df8eb72c7624c0435998eb9b378b1bc425bf9e5b6432c724b
7
+ data.tar.gz: da424f1faa7130c10d8dd07cdcc3d94a6c9c9f69ed1ca892703ca604de112fcb4878308e244fea894b5039cfd25f0f8c79447cebd06197401a80e6420fbd770c
@@ -5,32 +5,26 @@ module PackageProtections
5
5
  class Configuration
6
6
  extend T::Sig
7
7
 
8
- sig { params(protections: T::Array[ProtectionInterface]).void }
9
- attr_writer :protections
8
+ sig { returns(T::Array[ProtectionInterface]) }
9
+ attr_accessor :protections
10
+
11
+ sig { returns(T::Array[String]) }
12
+ attr_accessor :globally_permitted_namespaces
10
13
 
11
- sig { params(globally_permitted_namespaces: T::Array[String]).void }
12
- attr_writer :globally_permitted_namespaces
14
+ sig { returns(T::Array[String]) }
15
+ attr_accessor :acceptable_parent_classes
13
16
 
14
17
  sig { void }
15
18
  def initialize
16
19
  @protections = T.let(default_protections, T::Array[ProtectionInterface])
17
20
  @globally_permitted_namespaces = T.let([], T::Array[String])
21
+ @acceptable_parent_classes = T.let([], T::Array[String])
18
22
  end
19
-
20
- sig { returns(T::Array[ProtectionInterface]) }
21
- def protections
22
- @protections
23
- end
24
-
25
- sig { returns(T::Array[String]) }
26
- def globally_permitted_namespaces
27
- @globally_permitted_namespaces
28
- end
29
-
30
23
  sig { void }
31
24
  def bust_cache!
32
25
  @protections = default_protections
33
26
  @globally_permitted_namespaces = []
27
+ @acceptable_parent_classes = []
34
28
  end
35
29
 
36
30
  sig { returns(T::Array[ProtectionInterface]) }
@@ -40,7 +34,9 @@ module PackageProtections
40
34
  Private::IncomingPrivacyProtection.new,
41
35
  RuboCop::Cop::PackageProtections::TypedPublicApi.new,
42
36
  RuboCop::Cop::PackageProtections::NamespacedUnderPackageName.new,
43
- Private::VisibilityProtection.new
37
+ Private::VisibilityProtection.new,
38
+ RuboCop::Cop::PackageProtections::OnlyClassMethods.new,
39
+ RuboCop::Cop::PackageProtections::RequireDocumentedPublicApis.new
44
40
  ]
45
41
  end
46
42
  end
@@ -24,7 +24,8 @@ module ApplicationFixtureHelper
24
24
  'prevent_other_packages_from_using_this_packages_internals' => 'fail_on_new',
25
25
  'prevent_this_package_from_exposing_an_untyped_api' => 'fail_on_new',
26
26
  'prevent_this_package_from_creating_other_namespaces' => 'fail_on_new',
27
- 'prevent_other_packages_from_using_this_package_without_explicit_visibility' => 'fail_never'
27
+ 'prevent_other_packages_from_using_this_package_without_explicit_visibility' => 'fail_never',
28
+ 'prevent_this_package_from_exposing_instance_method_public_apis' => 'fail_never'
28
29
  }
29
30
  protections_with_defaults = defaults.merge(protections)
30
31
  metadata = { 'protections' => protections_with_defaults }
@@ -8,7 +8,7 @@ require 'set'
8
8
  require 'parse_packwerk'
9
9
  require 'rubocop'
10
10
  require 'rubocop-sorbet'
11
- require 'rubocop-modularization'
11
+ require 'rubocop-packs'
12
12
 
13
13
  #
14
14
  # Welcome to PackageProtections!
@@ -40,6 +40,8 @@ module PackageProtections
40
40
  # Implementation of rubocop-based protections
41
41
  require 'rubocop/cop/package_protections/namespaced_under_package_name'
42
42
  require 'rubocop/cop/package_protections/typed_public_api'
43
+ require 'rubocop/cop/package_protections/only_class_methods'
44
+ require 'rubocop/cop/package_protections/require_documented_public_apis'
43
45
 
44
46
  class << self
45
47
  extend T::Sig
@@ -6,7 +6,7 @@ require 'active_support/core_ext/string/inflections'
6
6
  module RuboCop
7
7
  module Cop
8
8
  module PackageProtections
9
- class NamespacedUnderPackageName < Base
9
+ class NamespacedUnderPackageName < Packs::NamespaceConvention
10
10
  extend T::Sig
11
11
  include ::PackageProtections::RubocopProtectionInterface
12
12
 
@@ -0,0 +1,58 @@
1
+ # typed: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module PackageProtections
6
+ class OnlyClassMethods < Packs::ClassMethodsAsPublicApis
7
+ extend T::Sig
8
+ include ::PackageProtections::RubocopProtectionInterface
9
+
10
+ IDENTIFIER = 'prevent_this_package_from_exposing_instance_method_public_apis'.freeze
11
+
12
+ sig { override.returns(String) }
13
+ def humanized_protection_description
14
+ <<~MESSAGE
15
+ Public API methods can only be static methods.
16
+ This is failing because these files are in `.rubocop_todo.yml` under `#{cop_name}`.
17
+ If you want to be able to ignore these files, you'll need to open the file's package's `package.yml` file and
18
+ change `#{IDENTIFIER}` to `#{::PackageProtections::ViolationBehavior::FailOnNew.serialize}`
19
+ MESSAGE
20
+ end
21
+
22
+ sig do
23
+ override.params(file: String).returns(String)
24
+ end
25
+ def message_for_fail_on_any(file)
26
+ "`#{file}` must only contain static (class or module level) methods"
27
+ end
28
+
29
+ sig { override.returns(T::Array[String]) }
30
+ def included_globs_for_pack
31
+ [
32
+ 'app/public/**/*'
33
+ ]
34
+ end
35
+
36
+ sig { override.returns(String) }
37
+ def identifier
38
+ IDENTIFIER
39
+ end
40
+
41
+ sig { override.returns(String) }
42
+ def humanized_protection_name
43
+ 'Class Method Public APIs'
44
+ end
45
+
46
+ sig { override.returns(String) }
47
+ def cop_name
48
+ 'PackageProtections/OnlyClassMethods'
49
+ end
50
+
51
+ sig { override.returns(::PackageProtections::ViolationBehavior) }
52
+ def default_behavior
53
+ ::PackageProtections::ViolationBehavior::FailNever
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,70 @@
1
+ # typed: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module PackageProtections
6
+ class RequireDocumentedPublicApis < Packs::RequireDocumentedPublicApis
7
+ extend T::Sig
8
+ include ::PackageProtections::RubocopProtectionInterface
9
+
10
+ IDENTIFIER = 'prevent_this_package_from_exposing_undocumented_public_apis'.freeze
11
+
12
+ include ::PackageProtections::RubocopProtectionInterface
13
+
14
+ sig { override.returns(String) }
15
+ def identifier
16
+ IDENTIFIER
17
+ end
18
+
19
+ sig { override.returns(T::Array[String]) }
20
+ def included_globs_for_pack
21
+ [
22
+ 'app/public/**/*'
23
+ ]
24
+ end
25
+
26
+ sig { override.params(behavior: ::PackageProtections::ViolationBehavior, package: ParsePackwerk::Package).returns(T.nilable(String)) }
27
+ def unmet_preconditions_for_behavior(behavior, package)
28
+ if !behavior.fail_never?
29
+ readme_path = package.directory.join('README.md')
30
+ if !readme_path.exist?
31
+ "This package must have a readme at #{readme_path} to use this protection"
32
+ end
33
+ end
34
+ end
35
+
36
+ sig do
37
+ override.params(file: String).returns(String)
38
+ end
39
+ def message_for_fail_on_any(file)
40
+ "`#{file}` must contain documentation on every method (between signature and method)"
41
+ end
42
+
43
+ sig { override.returns(String) }
44
+ def cop_name
45
+ 'PackageProtections/RequireDocumentedPublicApis'
46
+ end
47
+
48
+ sig { override.returns(String) }
49
+ def humanized_protection_name
50
+ 'Documented Public APIs'
51
+ end
52
+
53
+ sig { override.returns(::PackageProtections::ViolationBehavior) }
54
+ def default_behavior
55
+ ::PackageProtections::ViolationBehavior::FailNever
56
+ end
57
+
58
+ sig { override.returns(String) }
59
+ def humanized_protection_description
60
+ <<~MESSAGE
61
+ All public API must have a documentation comment (between the signature and method).
62
+ This is failing because these files are in `.rubocop_todo.yml` under `#{cop_name}`.
63
+ If you want to be able to ignore these files, you'll need to open the file's package's `package.yml` file and
64
+ change `#{IDENTIFIER}` to `#{::PackageProtections::ViolationBehavior::FailOnNew.serialize}`
65
+ MESSAGE
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -15,7 +15,7 @@ module RuboCop
15
15
  #
16
16
  # We can apply this same pattern if we want to use other cops in the context of package protections and prevent clashing.
17
17
  #
18
- class TypedPublicApi < Modularization::TypedPublicApi
18
+ class TypedPublicApi < Packs::TypedPublicApi
19
19
  extend T::Sig
20
20
 
21
21
  include ::PackageProtections::ProtectionInterface
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: package_protections
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.0
4
+ version: 2.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gusto Engineers
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: rubocop-modularization
56
+ name: rubocop-packs
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -206,6 +206,8 @@ files:
206
206
  - lib/package_protections/rubocop_protection_interface.rb
207
207
  - lib/package_protections/violation_behavior.rb
208
208
  - lib/rubocop/cop/package_protections/namespaced_under_package_name.rb
209
+ - lib/rubocop/cop/package_protections/only_class_methods.rb
210
+ - lib/rubocop/cop/package_protections/require_documented_public_apis.rb
209
211
  - lib/rubocop/cop/package_protections/typed_public_api.rb
210
212
  homepage: https://github.com/rubyatscale/package_protections
211
213
  licenses: