package_protections 1.1.1 → 1.2.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: 41803352508cd5d4ede0fe0caf1121516474fe3e95a030e4db7e0f05badfa9a2
|
4
|
+
data.tar.gz: bc594511c3b3da35dcd9efcfba0f989928e074e0da429a8f0f538e0537eff5be
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 352aa3ea22bf0d7cf765023c35ed88c6026fda2b52036aa73fbcf35e4aca1df52df24486ce028a238dcf50db89f2864f4080e77d6da52d9f7be7fa984cd70dc7
|
7
|
+
data.tar.gz: 6bb8ab188d27a3656cd6979d00fcaf725165176b17a42704be114ef0bbfbe7150facf21ae44ebc3c1633ce5b21876fd9b8088179c6e702f8addd49f890d7e1e3
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
module ApplicationFixtureHelper
|
7
|
+
def write_file(path, content = '')
|
8
|
+
pathname = Pathname.new(path)
|
9
|
+
FileUtils.mkdir_p(pathname.dirname)
|
10
|
+
pathname.write(content)
|
11
|
+
path
|
12
|
+
end
|
13
|
+
|
14
|
+
def write_package_yml(
|
15
|
+
pack_name,
|
16
|
+
dependencies: [],
|
17
|
+
enforce_dependencies: true,
|
18
|
+
enforce_privacy: true,
|
19
|
+
protections: {},
|
20
|
+
global_namespaces: [],
|
21
|
+
visible_to: []
|
22
|
+
)
|
23
|
+
defaults = {
|
24
|
+
'prevent_this_package_from_violating_its_stated_dependencies' => 'fail_on_new',
|
25
|
+
'prevent_other_packages_from_using_this_packages_internals' => 'fail_on_new',
|
26
|
+
'prevent_this_package_from_exposing_an_untyped_api' => 'fail_on_new',
|
27
|
+
'prevent_this_package_from_creating_other_namespaces' => 'fail_on_new',
|
28
|
+
'prevent_other_packages_from_using_this_package_without_explicit_visibility' => 'fail_never'
|
29
|
+
}
|
30
|
+
protections_with_defaults = defaults.merge(protections)
|
31
|
+
metadata = { 'protections' => protections_with_defaults }
|
32
|
+
if visible_to.any?
|
33
|
+
metadata.merge!('visible_to' => visible_to)
|
34
|
+
end
|
35
|
+
|
36
|
+
if global_namespaces.any?
|
37
|
+
metadata.merge!('global_namespaces' => global_namespaces)
|
38
|
+
end
|
39
|
+
|
40
|
+
package = ParsePackwerk::Package.new(
|
41
|
+
name: pack_name,
|
42
|
+
dependencies: dependencies,
|
43
|
+
enforce_dependencies: enforce_dependencies,
|
44
|
+
enforce_privacy: enforce_privacy,
|
45
|
+
metadata: metadata
|
46
|
+
)
|
47
|
+
|
48
|
+
ParsePackwerk.write_package_yml!(package)
|
49
|
+
end
|
50
|
+
|
51
|
+
def delete_app_file(path)
|
52
|
+
File.delete(path)
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
def offense(
|
2
|
+
package_name, message, file, violation_type
|
3
|
+
)
|
4
|
+
|
5
|
+
package = ParsePackwerk.all.find { |p| p.name == package_name }
|
6
|
+
PackageProtections::Offense.new(
|
7
|
+
package: package,
|
8
|
+
message: message,
|
9
|
+
file: file,
|
10
|
+
violation_type: violation_type
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
def serialize_offenses_diff(actual_offenses, expected_offense)
|
15
|
+
color_by_match = ->(actual, expected) { actual == expected ? Rainbow(actual).green : "#{Rainbow(actual).red} (expected: #{expected})" }
|
16
|
+
|
17
|
+
actual_offenses.map do |offense|
|
18
|
+
# We color each field red or green depending on if the attributes match our expected
|
19
|
+
<<~SERIALIZED_OFFENSE
|
20
|
+
File: #{color_by_match.call(offense.file, expected_offense.file)}
|
21
|
+
Message: #{color_by_match.call(offense.message, expected_offense.message)}
|
22
|
+
Violation Type: #{color_by_match.call(offense.violation_type, expected_offense.violation_type)}
|
23
|
+
Package: #{color_by_match.call(offense.package.name, expected_offense.package.name)}
|
24
|
+
SERIALIZED_OFFENSE
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def serialize_offenses(actual_offenses)
|
29
|
+
actual_offenses.map do |offense|
|
30
|
+
<<~SERIALIZED_OFFENSE
|
31
|
+
File: #{offense.file}
|
32
|
+
Message: #{offense.message}
|
33
|
+
Violation Type: #{offense.violation_type}
|
34
|
+
Package: #{offense.package.name}
|
35
|
+
SERIALIZED_OFFENSE
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
RSpec::Matchers.define(:include_offense) do |expected_offense|
|
40
|
+
match do |actual_offenses|
|
41
|
+
@actual_offenses = actual_offenses
|
42
|
+
@expected_offense = expected_offense
|
43
|
+
if ENV['DEBUG']
|
44
|
+
PackageProtections.print_offenses(actual_offenses)
|
45
|
+
end
|
46
|
+
@matching_offense = actual_offenses.find do |actual_offense|
|
47
|
+
actual_offense.file == expected_offense.file &&
|
48
|
+
actual_offense.message == expected_offense.message &&
|
49
|
+
actual_offense.violation_type == expected_offense.violation_type &&
|
50
|
+
actual_offense.package.name == expected_offense.package.name
|
51
|
+
end
|
52
|
+
!@matching_offense.nil?
|
53
|
+
end
|
54
|
+
|
55
|
+
description do
|
56
|
+
"to have an offense with type `#{expected_offense.type}` tied to package `#{expected_offense.package_name}` with message `#{expected_offense.message}` and instances `#{expected_offense.submessages.join(', ')}`"
|
57
|
+
end
|
58
|
+
|
59
|
+
failure_message do
|
60
|
+
<<~MSG
|
61
|
+
Could not find offense! Here are the found offenses:
|
62
|
+
#{serialize_offenses_diff(@actual_offenses, expected_offense).join("\n\n")}
|
63
|
+
MSG
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
RSpec::Matchers.define(:contain_exactly) do |number_of_offenses|
|
68
|
+
match do |actual_offenses|
|
69
|
+
@actual_offenses = actual_offenses || []
|
70
|
+
@offenses = []
|
71
|
+
@actual_offenses.each do |offense|
|
72
|
+
@offenses << offense
|
73
|
+
end
|
74
|
+
@offenses.size == number_of_offenses
|
75
|
+
end
|
76
|
+
|
77
|
+
chain :offense, :number_of_offenses
|
78
|
+
chain :offenses, :number_of_offenses
|
79
|
+
|
80
|
+
description do
|
81
|
+
'to contain offenses'
|
82
|
+
end
|
83
|
+
|
84
|
+
failure_message_when_negated do
|
85
|
+
"Found the following offenses:\n#{@offenses.map { |r| "#{r.package_name}: #{r.message}" }}"
|
86
|
+
end
|
87
|
+
|
88
|
+
failure_message do
|
89
|
+
if @offenses.empty?
|
90
|
+
"Found #{@offenses.size} instead."
|
91
|
+
else
|
92
|
+
<<~MSG
|
93
|
+
Found #{@offenses.size} instead.
|
94
|
+
|
95
|
+
#{serialize_offenses(@offenses).join("\n")}
|
96
|
+
MSG
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Require this file to load code that supports testing using RSpec.
|
4
|
+
|
5
|
+
require_relative 'application_fixture_helper'
|
6
|
+
require_relative 'matchers'
|
7
|
+
|
8
|
+
def get_resulting_rubocop
|
9
|
+
write_file('config/default.yml', <<~YML.strip)
|
10
|
+
<%= PackageProtections.rubocop_yml %>
|
11
|
+
YML
|
12
|
+
YAML.safe_load(ERB.new(File.read('config/default.yml')).result(binding))
|
13
|
+
end
|
14
|
+
|
15
|
+
RSpec.configure do |config|
|
16
|
+
config.include ApplicationFixtureHelper
|
17
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: package_protections
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.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: 2022-
|
11
|
+
date: 2022-07-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -186,6 +186,9 @@ files:
|
|
186
186
|
- lib/package_protections/private/visibility_protection.rb
|
187
187
|
- lib/package_protections/protected_package.rb
|
188
188
|
- lib/package_protections/protection_interface.rb
|
189
|
+
- lib/package_protections/rspec/application_fixture_helper.rb
|
190
|
+
- lib/package_protections/rspec/matchers.rb
|
191
|
+
- lib/package_protections/rspec/support.rb
|
189
192
|
- lib/package_protections/rubocop_protection_interface.rb
|
190
193
|
- lib/package_protections/violation_behavior.rb
|
191
194
|
- lib/rubocop/cop/package_protections/namespaced_under_package_name.rb
|