package_protections 2.3.0 → 2.5.0

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: 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: