packwerk 1.0.2 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/USAGE.md +22 -1
- data/lib/packwerk/application_validator.rb +3 -3
- data/lib/packwerk/cache_deprecated_references.rb +47 -0
- data/lib/packwerk/cli.rb +21 -10
- data/lib/packwerk/commands/detect_stale_violations_command.rb +63 -0
- data/lib/packwerk/commands/offense_progress_marker.rb +24 -0
- data/lib/packwerk/deprecated_references.rb +19 -0
- data/lib/packwerk/detect_stale_deprecated_references.rb +14 -0
- data/lib/packwerk/package_set.rb +6 -2
- data/lib/packwerk/parsers/erb.rb +4 -0
- data/lib/packwerk/parsers/factory.rb +10 -1
- data/lib/packwerk/run_context.rb +2 -1
- data/lib/packwerk/updating_deprecated_references.rb +2 -39
- data/lib/packwerk/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 91ec92f15d9d87fa8c54861afd424fe6149ef8f8e05f114b6ee04559fa6053fc
|
4
|
+
data.tar.gz: b83cc17ff9cd7d2d37db4456017d429b4a8f8e45766cdfa4551ace2e32c58183
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 596f4f1a6b026e96ab6299e9ba7ceb63b7d709bd49c0629390f50e62e751174e4a92557243bef3a8f7f36aaf416e54fbf1fdb9f368fc2e478eb033e208358dc6
|
7
|
+
data.tar.gz: fdca4107315ea6140d7b92e5cd7b53216a73f65fac4c1c3147c798a1d407f75d3898b31517bec6bf2452e7ca0a3d1ad87599142250cf75684ccc9a48436bcd91
|
data/Gemfile.lock
CHANGED
data/USAGE.md
CHANGED
@@ -63,10 +63,31 @@ Packwerk reads from the `packwerk.yml` configuration file in the root directory.
|
|
63
63
|
|----------------------|-------------------------------------------|--------------|
|
64
64
|
| include | **/*.{rb,rake,erb} | list of patterns for folder paths to include |
|
65
65
|
| exclude | {bin,node_modules,script,tmp,vendor}/**/* | list of patterns for folder paths to exclude |
|
66
|
-
| package_paths | **/ | patterns to find package configuration files, see: Defining packages |
|
66
|
+
| package_paths | **/ | a single pattern or a list of patterns to find package configuration files, see: [Defining packages](#Defining-packages) |
|
67
67
|
| load_paths | All application autoload paths | list of load paths |
|
68
68
|
| custom_associations | N/A | list of custom associations, if any |
|
69
69
|
|
70
|
+
### Using a custom ERB parser
|
71
|
+
|
72
|
+
You can specify a custom ERB parser if needed. For example, if you're using `<%graphql>` tags from https://github.com/github/graphql-client in your ERBs, you can use a custom parser subclass to comment them out so that Packwerk can parse the rest of the file:
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
class CustomParser < Packwerk::Parsers::Erb
|
76
|
+
def parse_buffer(buffer, file_path:)
|
77
|
+
preprocessed_source = buffer.source
|
78
|
+
|
79
|
+
# Comment out <%graphql ... %> tags. They won't contain any object
|
80
|
+
# references anyways.
|
81
|
+
preprocessed_source = preprocessed_source.gsub(/<%graphql/, "<%#")
|
82
|
+
|
83
|
+
preprocessed_buffer = Parser::Source::Buffer.new(file_path)
|
84
|
+
preprocessed_buffer.source = preprocessed_source
|
85
|
+
super(preprocessed_buffer, file_path: file_path)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
Packwerk::Parsers::Factory.instance.erb_parser_class = CustomParser
|
90
|
+
```
|
70
91
|
|
71
92
|
### Inflections
|
72
93
|
|
@@ -32,7 +32,7 @@ module Packwerk
|
|
32
32
|
check_acyclic_graph,
|
33
33
|
check_package_manifest_paths,
|
34
34
|
check_valid_package_dependencies,
|
35
|
-
|
35
|
+
check_root_package_exists,
|
36
36
|
]
|
37
37
|
|
38
38
|
results.reject!(&:ok?)
|
@@ -207,7 +207,7 @@ module Packwerk
|
|
207
207
|
end
|
208
208
|
|
209
209
|
def check_acyclic_graph
|
210
|
-
packages = Packwerk::PackageSet.load_all_from(
|
210
|
+
packages = Packwerk::PackageSet.load_all_from(@configuration.root_path)
|
211
211
|
|
212
212
|
edges = packages.flat_map do |package|
|
213
213
|
package.dependencies.map { |dependency| [package, packages.fetch(dependency)] }
|
@@ -297,7 +297,7 @@ module Packwerk
|
|
297
297
|
end
|
298
298
|
end
|
299
299
|
|
300
|
-
def
|
300
|
+
def check_root_package_exists
|
301
301
|
root_package_path = File.join(@configuration.root_path, "package.yml")
|
302
302
|
all_packages_manifests = package_manifests(package_glob)
|
303
303
|
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "sorbet-runtime"
|
5
|
+
|
6
|
+
require "packwerk/deprecated_references"
|
7
|
+
require "packwerk/reference"
|
8
|
+
require "packwerk/reference_lister"
|
9
|
+
require "packwerk/violation_type"
|
10
|
+
|
11
|
+
module Packwerk
|
12
|
+
class CacheDeprecatedReferences
|
13
|
+
extend T::Sig
|
14
|
+
extend T::Helpers
|
15
|
+
include ReferenceLister
|
16
|
+
abstract!
|
17
|
+
|
18
|
+
def initialize(root_path, deprecated_references = {})
|
19
|
+
@root_path = root_path
|
20
|
+
@deprecated_references = T.let(deprecated_references, T::Hash[String, Packwerk::DeprecatedReferences])
|
21
|
+
end
|
22
|
+
|
23
|
+
sig do
|
24
|
+
params(reference: Packwerk::Reference, violation_type: ViolationType)
|
25
|
+
.returns(T::Boolean)
|
26
|
+
.override
|
27
|
+
end
|
28
|
+
def listed?(reference, violation_type:)
|
29
|
+
deprecated_references = deprecated_references_for(reference.source_package)
|
30
|
+
deprecated_references.add_entries(reference, violation_type.serialize)
|
31
|
+
true
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def deprecated_references_for(package)
|
37
|
+
@deprecated_references[package] ||= Packwerk::DeprecatedReferences.new(
|
38
|
+
package,
|
39
|
+
deprecated_references_file_for(package),
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
def deprecated_references_file_for(package)
|
44
|
+
File.join(@root_path, package.name, "deprecated_references.yml")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/packwerk/cli.rb
CHANGED
@@ -12,10 +12,13 @@ require "packwerk/output_styles"
|
|
12
12
|
require "packwerk/run_context"
|
13
13
|
require "packwerk/updating_deprecated_references"
|
14
14
|
require "packwerk/checking_deprecated_references"
|
15
|
+
require "packwerk/commands/detect_stale_violations_command"
|
16
|
+
require "packwerk/commands/offense_progress_marker"
|
15
17
|
|
16
18
|
module Packwerk
|
17
19
|
class Cli
|
18
20
|
extend T::Sig
|
21
|
+
include OffenseProgressMarker
|
19
22
|
|
20
23
|
def initialize(run_context: nil, configuration: nil, out: $stdout, err_out: $stderr, style: OutputStyles::Plain)
|
21
24
|
@out = out
|
@@ -45,6 +48,8 @@ module Packwerk
|
|
45
48
|
generate_configs
|
46
49
|
when "check"
|
47
50
|
check(args)
|
51
|
+
when "detect-stale-violations"
|
52
|
+
detect_stale_violations(args)
|
48
53
|
when "update"
|
49
54
|
update(args)
|
50
55
|
when "update-deprecations"
|
@@ -142,7 +147,9 @@ module Packwerk
|
|
142
147
|
all_offenses = T.let([], T.untyped)
|
143
148
|
execution_time = Benchmark.realtime do
|
144
149
|
all_offenses = files.flat_map do |path|
|
145
|
-
@run_context.process_file(file: path).tap
|
150
|
+
@run_context.process_file(file: path).tap do |offenses|
|
151
|
+
mark_progress(offenses: offenses, progress_formatter: @progress_formatter)
|
152
|
+
end
|
146
153
|
end
|
147
154
|
|
148
155
|
updating_deprecated_references.dump_deprecated_references_files
|
@@ -165,7 +172,7 @@ module Packwerk
|
|
165
172
|
execution_time = Benchmark.realtime do
|
166
173
|
files.each do |path|
|
167
174
|
@run_context.process_file(file: path).tap do |offenses|
|
168
|
-
mark_progress(offenses)
|
175
|
+
mark_progress(offenses: offenses, progress_formatter: @progress_formatter)
|
169
176
|
all_offenses.concat(offenses)
|
170
177
|
end
|
171
178
|
end
|
@@ -181,6 +188,18 @@ module Packwerk
|
|
181
188
|
all_offenses.empty?
|
182
189
|
end
|
183
190
|
|
191
|
+
def detect_stale_violations(paths)
|
192
|
+
detect_stale_violations = DetectStaleViolationsCommand.new(
|
193
|
+
files: fetch_files_to_process(paths),
|
194
|
+
configuration: @configuration,
|
195
|
+
progress_formatter: @progress_formatter
|
196
|
+
)
|
197
|
+
result = detect_stale_violations.run
|
198
|
+
@out.puts
|
199
|
+
@out.puts(result.message)
|
200
|
+
result.status
|
201
|
+
end
|
202
|
+
|
184
203
|
def fetch_files_to_process(paths)
|
185
204
|
files = FilesForProcessing.fetch(paths: paths, configuration: @configuration)
|
186
205
|
abort("No files found or given. "\
|
@@ -188,14 +207,6 @@ module Packwerk
|
|
188
207
|
files
|
189
208
|
end
|
190
209
|
|
191
|
-
def mark_progress(offenses)
|
192
|
-
if offenses.empty?
|
193
|
-
@progress_formatter.mark_as_inspected
|
194
|
-
else
|
195
|
-
@progress_formatter.mark_as_failed
|
196
|
-
end
|
197
|
-
end
|
198
|
-
|
199
210
|
def validate(_paths)
|
200
211
|
warn("`packwerk validate` should be run within the application. "\
|
201
212
|
"Generate the bin script using `packwerk init` and"\
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
require "packwerk/cli"
|
4
|
+
require "sorbet-runtime"
|
5
|
+
require "benchmark"
|
6
|
+
require "packwerk/configuration"
|
7
|
+
require "packwerk/formatters/progress_formatter"
|
8
|
+
require "packwerk/run_context"
|
9
|
+
require "packwerk/detect_stale_deprecated_references"
|
10
|
+
require "packwerk/commands/offense_progress_marker"
|
11
|
+
|
12
|
+
module Packwerk
|
13
|
+
class DetectStaleViolationsCommand
|
14
|
+
extend T::Sig
|
15
|
+
include OffenseProgressMarker
|
16
|
+
Result = Struct.new(:message, :status)
|
17
|
+
|
18
|
+
def initialize(files:, configuration:, run_context: nil, progress_formatter: nil, reference_lister: nil)
|
19
|
+
@configuration = configuration
|
20
|
+
@run_context = run_context
|
21
|
+
@reference_lister = reference_lister
|
22
|
+
@progress_formatter = progress_formatter
|
23
|
+
@files = files
|
24
|
+
end
|
25
|
+
|
26
|
+
sig { returns(Result) }
|
27
|
+
def run
|
28
|
+
@progress_formatter.started(@files)
|
29
|
+
|
30
|
+
all_offenses = T.let([], T.untyped)
|
31
|
+
execution_time = Benchmark.realtime do
|
32
|
+
all_offenses = @files.flat_map do |path|
|
33
|
+
run_context.process_file(file: path).tap do |offenses|
|
34
|
+
mark_progress(offenses: offenses, progress_formatter: @progress_formatter)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
@progress_formatter.finished(execution_time)
|
40
|
+
calculate_result
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def run_context
|
46
|
+
@run_context ||= Packwerk::RunContext.from_configuration(@configuration, reference_lister: reference_lister)
|
47
|
+
end
|
48
|
+
|
49
|
+
def reference_lister
|
50
|
+
@reference_lister ||= ::Packwerk::DetectStaleDeprecatedReferences.new(@configuration.root_path)
|
51
|
+
end
|
52
|
+
|
53
|
+
sig { returns Result }
|
54
|
+
def calculate_result
|
55
|
+
result_status = !reference_lister.stale_violations?
|
56
|
+
message = "There were stale violations found, please run `packwerk update`"
|
57
|
+
if result_status
|
58
|
+
message = "No stale violations detected"
|
59
|
+
end
|
60
|
+
Result.new(message, result_status)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# typed: strict
|
3
|
+
require "sorbet-runtime"
|
4
|
+
require "packwerk/formatters/progress_formatter"
|
5
|
+
|
6
|
+
module Packwerk
|
7
|
+
module OffenseProgressMarker
|
8
|
+
extend T::Sig
|
9
|
+
|
10
|
+
sig do
|
11
|
+
params(
|
12
|
+
offenses: T::Array[T.nilable(::Packwerk::Offense)],
|
13
|
+
progress_formatter: ::Packwerk::Formatters::ProgressFormatter
|
14
|
+
).void
|
15
|
+
end
|
16
|
+
def mark_progress(offenses:, progress_formatter:)
|
17
|
+
if offenses.empty?
|
18
|
+
progress_formatter.mark_as_inspected
|
19
|
+
else
|
20
|
+
progress_formatter.mark_as_failed
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -3,6 +3,7 @@
|
|
3
3
|
|
4
4
|
require "sorbet-runtime"
|
5
5
|
require "yaml"
|
6
|
+
require "sorbet-runtime"
|
6
7
|
|
7
8
|
require "packwerk/reference"
|
8
9
|
require "packwerk/reference_lister"
|
@@ -47,6 +48,24 @@ module Packwerk
|
|
47
48
|
@new_entries[reference.constant.package.name] = package_violations
|
48
49
|
end
|
49
50
|
|
51
|
+
sig { returns(T::Boolean) }
|
52
|
+
def stale_violations?
|
53
|
+
prepare_entries_for_dump
|
54
|
+
deprecated_references.any? do |package, package_violations|
|
55
|
+
package_violations.any? do |constant_name, entries_for_file|
|
56
|
+
new_entries_violation_types = @new_entries.dig(package, constant_name, "violations")
|
57
|
+
return true if new_entries_violation_types.nil?
|
58
|
+
if entries_for_file["violations"].all? { |type| new_entries_violation_types.include?(type) }
|
59
|
+
stale_violations =
|
60
|
+
entries_for_file["files"] - Array(@new_entries.dig(package, constant_name, "files"))
|
61
|
+
stale_violations.present?
|
62
|
+
else
|
63
|
+
return true
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
50
69
|
def dump
|
51
70
|
if @new_entries.empty?
|
52
71
|
File.delete(@filepath) if File.exist?(@filepath)
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "packwerk/cache_deprecated_references"
|
5
|
+
|
6
|
+
module Packwerk
|
7
|
+
class DetectStaleDeprecatedReferences < CacheDeprecatedReferences
|
8
|
+
extend T::Sig
|
9
|
+
sig { returns(T::Boolean) }
|
10
|
+
def stale_violations?
|
11
|
+
@deprecated_references.values.any?(&:stale_violations?)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/packwerk/package_set.rb
CHANGED
@@ -28,8 +28,12 @@ module Packwerk
|
|
28
28
|
def package_paths(root_path, package_pathspec)
|
29
29
|
bundle_path_match = Bundler.bundle_path.join("**").to_s
|
30
30
|
|
31
|
-
|
32
|
-
.
|
31
|
+
glob_patterns = Array(package_pathspec).map do |pathspec|
|
32
|
+
File.join(root_path, pathspec, PACKAGE_CONFIG_FILENAME)
|
33
|
+
end
|
34
|
+
|
35
|
+
Dir.glob(glob_patterns)
|
36
|
+
.map { |path| Pathname.new(path).cleanpath }
|
33
37
|
.reject { |path| path.realpath.fnmatch(bundle_path_match) }
|
34
38
|
end
|
35
39
|
|
data/lib/packwerk/parsers/erb.rb
CHANGED
@@ -19,6 +19,10 @@ module Packwerk
|
|
19
19
|
def call(io:, file_path: "<unknown>")
|
20
20
|
buffer = Parser::Source::Buffer.new(file_path)
|
21
21
|
buffer.source = io.read
|
22
|
+
parse_buffer(buffer, file_path: file_path)
|
23
|
+
end
|
24
|
+
|
25
|
+
def parse_buffer(buffer, file_path:)
|
22
26
|
parser = @parser_class.new(buffer, template_language: :html)
|
23
27
|
to_ruby_ast(parser.ast, file_path)
|
24
28
|
rescue EncodingError => e
|
@@ -26,9 +26,18 @@ module Packwerk
|
|
26
26
|
when RUBY_REGEX
|
27
27
|
@ruby_parser ||= Ruby.new
|
28
28
|
when ERB_REGEX
|
29
|
-
@erb_parser ||=
|
29
|
+
@erb_parser ||= erb_parser_class.new
|
30
30
|
end
|
31
31
|
end
|
32
|
+
|
33
|
+
def erb_parser_class
|
34
|
+
@erb_parser_class || Erb
|
35
|
+
end
|
36
|
+
|
37
|
+
def erb_parser_class=(klass)
|
38
|
+
@erb_parser_class = klass
|
39
|
+
@erb_parser = nil
|
40
|
+
end
|
32
41
|
end
|
33
42
|
end
|
34
43
|
end
|
data/lib/packwerk/run_context.rb
CHANGED
@@ -1,51 +1,14 @@
|
|
1
1
|
# typed: true
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require "
|
5
|
-
|
6
|
-
require "packwerk/deprecated_references"
|
7
|
-
require "packwerk/reference"
|
8
|
-
require "packwerk/reference_lister"
|
9
|
-
require "packwerk/violation_type"
|
4
|
+
require "packwerk/cache_deprecated_references"
|
10
5
|
|
11
6
|
module Packwerk
|
12
|
-
class UpdatingDeprecatedReferences
|
13
|
-
extend T::Sig
|
14
|
-
include ReferenceLister
|
15
|
-
|
16
|
-
def initialize(root_path, deprecated_references = {})
|
17
|
-
@root_path = root_path
|
18
|
-
@deprecated_references = deprecated_references
|
19
|
-
end
|
20
|
-
|
21
|
-
sig do
|
22
|
-
params(reference: Packwerk::Reference, violation_type: ViolationType)
|
23
|
-
.returns(T::Boolean)
|
24
|
-
.override
|
25
|
-
end
|
26
|
-
def listed?(reference, violation_type:)
|
27
|
-
deprecated_references = deprecated_references_for(reference.source_package)
|
28
|
-
deprecated_references.add_entries(reference, violation_type.serialize)
|
29
|
-
true
|
30
|
-
end
|
31
|
-
|
7
|
+
class UpdatingDeprecatedReferences < CacheDeprecatedReferences
|
32
8
|
def dump_deprecated_references_files
|
33
9
|
@deprecated_references.each do |_, deprecated_references_file|
|
34
10
|
deprecated_references_file.dump
|
35
11
|
end
|
36
12
|
end
|
37
|
-
|
38
|
-
private
|
39
|
-
|
40
|
-
def deprecated_references_for(package)
|
41
|
-
@deprecated_references[package] ||= Packwerk::DeprecatedReferences.new(
|
42
|
-
package,
|
43
|
-
deprecated_references_file_for(package),
|
44
|
-
)
|
45
|
-
end
|
46
|
-
|
47
|
-
def deprecated_references_file_for(package)
|
48
|
-
File.join(@root_path, package.name, "deprecated_references.yml")
|
49
|
-
end
|
50
13
|
end
|
51
14
|
end
|
data/lib/packwerk/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: packwerk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shopify Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-11-
|
11
|
+
date: 2020-11-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -186,15 +186,19 @@ files:
|
|
186
186
|
- lib/packwerk/application_load_paths.rb
|
187
187
|
- lib/packwerk/application_validator.rb
|
188
188
|
- lib/packwerk/association_inspector.rb
|
189
|
+
- lib/packwerk/cache_deprecated_references.rb
|
189
190
|
- lib/packwerk/checker.rb
|
190
191
|
- lib/packwerk/checking_deprecated_references.rb
|
191
192
|
- lib/packwerk/cli.rb
|
193
|
+
- lib/packwerk/commands/detect_stale_violations_command.rb
|
194
|
+
- lib/packwerk/commands/offense_progress_marker.rb
|
192
195
|
- lib/packwerk/configuration.rb
|
193
196
|
- lib/packwerk/const_node_inspector.rb
|
194
197
|
- lib/packwerk/constant_discovery.rb
|
195
198
|
- lib/packwerk/constant_name_inspector.rb
|
196
199
|
- lib/packwerk/dependency_checker.rb
|
197
200
|
- lib/packwerk/deprecated_references.rb
|
201
|
+
- lib/packwerk/detect_stale_deprecated_references.rb
|
198
202
|
- lib/packwerk/file_processor.rb
|
199
203
|
- lib/packwerk/files_for_processing.rb
|
200
204
|
- lib/packwerk/formatters/progress_formatter.rb
|