packwerk 2.3.0 → 3.0.1
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 +4 -4
- data/.github/workflows/ci.yml +2 -5
- data/.ruby-version +1 -1
- data/Gemfile +0 -1
- data/Gemfile.lock +5 -95
- data/README.md +2 -7
- data/RESOLVING_VIOLATIONS.md +3 -8
- data/TROUBLESHOOT.md +2 -25
- data/UPGRADING.md +12 -0
- data/USAGE.md +136 -54
- data/dev.yml +1 -1
- data/exe/packwerk +4 -0
- data/gemfiles/Gemfile-rails-6-1 +1 -1
- data/lib/packwerk/application_validator.rb +54 -285
- data/lib/packwerk/association_inspector.rb +2 -0
- data/lib/packwerk/cache.rb +6 -5
- data/lib/packwerk/checker.rb +54 -0
- data/lib/packwerk/cli/result.rb +11 -0
- data/lib/packwerk/cli.rb +55 -40
- data/lib/packwerk/configuration.rb +61 -40
- data/lib/packwerk/const_node_inspector.rb +2 -0
- data/lib/packwerk/constant_context.rb +8 -0
- data/lib/packwerk/constant_discovery.rb +5 -6
- data/lib/packwerk/constant_name_inspector.rb +2 -0
- data/lib/packwerk/disable_sorbet.rb +41 -0
- data/lib/packwerk/extension_loader.rb +24 -0
- data/lib/packwerk/file_processor.rb +3 -1
- data/lib/packwerk/files_for_processing.rb +25 -12
- data/lib/packwerk/formatters/default_offenses_formatter.rb +77 -0
- data/lib/packwerk/formatters/progress_formatter.rb +31 -12
- data/lib/packwerk/generators/configuration_file.rb +7 -2
- data/lib/packwerk/generators/root_package.rb +5 -1
- data/lib/packwerk/generators/templates/package.yml +0 -10
- data/lib/packwerk/graph.rb +10 -2
- data/lib/packwerk/node.rb +1 -1
- data/lib/packwerk/node_helpers.rb +14 -7
- data/lib/packwerk/node_processor.rb +2 -0
- data/lib/packwerk/node_processor_factory.rb +6 -4
- data/lib/packwerk/node_visitor.rb +10 -1
- data/lib/packwerk/offense_collection.rb +26 -18
- data/lib/packwerk/offenses_formatter.rb +59 -2
- data/lib/packwerk/package.rb +7 -35
- data/lib/packwerk/package_set.rb +1 -1
- data/lib/packwerk/package_todo.rb +19 -20
- data/lib/packwerk/parse_run.rb +27 -34
- data/lib/packwerk/parsed_constant_definitions.rb +28 -5
- data/lib/packwerk/parsers/erb.rb +23 -4
- data/lib/packwerk/parsers/factory.rb +11 -2
- data/lib/packwerk/parsers/parser_interface.rb +1 -1
- data/lib/packwerk/parsers/ruby.rb +13 -3
- data/lib/packwerk/parsers.rb +6 -2
- data/lib/packwerk/{application_load_paths.rb → rails_load_paths.rb} +6 -4
- data/lib/packwerk/reference.rb +7 -1
- data/lib/packwerk/reference_checking/checkers/dependency_checker.rb +29 -6
- data/lib/packwerk/reference_checking/reference_checker.rb +1 -1
- data/lib/packwerk/reference_extractor.rb +24 -12
- data/lib/packwerk/reference_offense.rb +2 -2
- data/lib/packwerk/run_context.rb +7 -10
- data/lib/packwerk/spring_command.rb +9 -2
- data/lib/packwerk/unresolved_reference.rb +9 -1
- data/lib/packwerk/validator/result.rb +18 -0
- data/lib/packwerk/validator.rb +90 -0
- data/lib/packwerk/validators/dependency_validator.rb +154 -0
- data/lib/packwerk/version.rb +1 -1
- data/lib/packwerk.rb +64 -26
- data/packwerk.gemspec +4 -2
- data/sorbet/rbi/gems/{zeitwerk@2.6.0.rbi → zeitwerk@2.6.4.rbi} +291 -228
- data/sorbet/rbi/shims/minitest/test.rb +8 -0
- data/sorbet/rbi/shims/packwerk/reference.rbi +33 -0
- data/sorbet/rbi/shims/packwerk/unresolved_reference.rbi +33 -0
- data/sorbet/rbi/shims/parser.rbi +13 -0
- metadata +34 -15
- data/lib/packwerk/formatters/offenses_formatter.rb +0 -52
- data/lib/packwerk/reference_checking/checkers/checker.rb +0 -34
- data/lib/packwerk/reference_checking/checkers/privacy_checker.rb +0 -76
- data/lib/packwerk/result.rb +0 -9
- data/lib/packwerk/sanity_checker.rb +0 -8
- data/lib/packwerk/violation_type.rb +0 -11
- data/sorbet/rbi/gems/html_tokenizer@0.0.7.rbi +0 -46
- data/sorbet/rbi/gems/mini_portile2@2.8.0.rbi +0 -8
@@ -1,24 +1,31 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require "spring/commands"
|
5
|
+
require "sorbet-runtime"
|
5
6
|
|
6
7
|
module Packwerk
|
7
8
|
class SpringCommand
|
8
|
-
|
9
|
+
extend T::Sig
|
10
|
+
|
11
|
+
sig { params(args: T.untyped).returns(String) }
|
12
|
+
def env(args)
|
9
13
|
# Packwerk needs to run in a test environment, which has a set of autoload paths that are
|
10
14
|
# often a superset of the dev/prod paths (for example, test/support/helpers)
|
11
15
|
"test"
|
12
16
|
end
|
13
17
|
|
18
|
+
sig { returns(String) }
|
14
19
|
def exec_name
|
15
20
|
"packwerk"
|
16
21
|
end
|
17
22
|
|
23
|
+
sig { returns(String) }
|
18
24
|
def gem_name
|
19
25
|
"packwerk"
|
20
26
|
end
|
21
27
|
|
28
|
+
sig { returns(T::Boolean) }
|
22
29
|
def call
|
23
30
|
load(Gem.bin_path(gem_name, exec_name))
|
24
31
|
end
|
@@ -6,5 +6,13 @@ module Packwerk
|
|
6
6
|
# Unresolved means that we know how it's referred to in the file,
|
7
7
|
# and we have enough context on that reference to figure out the fully qualified reference such that we
|
8
8
|
# can produce a Reference in a separate pass. However, we have not yet resolved it to its fully qualified version.
|
9
|
-
UnresolvedReference = Struct.new(
|
9
|
+
UnresolvedReference = Struct.new(
|
10
|
+
:constant_name,
|
11
|
+
:namespace_path,
|
12
|
+
:relative_path,
|
13
|
+
:source_location,
|
14
|
+
keyword_init: true,
|
15
|
+
)
|
16
|
+
|
17
|
+
private_constant :UnresolvedReference
|
10
18
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Packwerk
|
5
|
+
module Validator
|
6
|
+
class Result < T::Struct
|
7
|
+
extend T::Sig
|
8
|
+
|
9
|
+
const :ok, T::Boolean
|
10
|
+
const :error_value, T.nilable(String)
|
11
|
+
|
12
|
+
sig { returns(T::Boolean) }
|
13
|
+
def ok?
|
14
|
+
ok
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "constant_resolver"
|
5
|
+
require "pathname"
|
6
|
+
require "yaml"
|
7
|
+
|
8
|
+
module Packwerk
|
9
|
+
module Validator
|
10
|
+
extend T::Sig
|
11
|
+
extend T::Helpers
|
12
|
+
|
13
|
+
abstract!
|
14
|
+
|
15
|
+
class << self
|
16
|
+
extend T::Sig
|
17
|
+
|
18
|
+
sig { params(base: Class).void }
|
19
|
+
def included(base)
|
20
|
+
@validators ||= T.let(@validators, T.nilable(T::Array[Class]))
|
21
|
+
@validators ||= []
|
22
|
+
@validators << base
|
23
|
+
end
|
24
|
+
|
25
|
+
sig { returns(T::Array[Validator]) }
|
26
|
+
def all
|
27
|
+
T.unsafe(@validators).map(&:new)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
sig { abstract.returns(T::Array[String]) }
|
32
|
+
def permitted_keys
|
33
|
+
end
|
34
|
+
|
35
|
+
sig { abstract.params(package_set: PackageSet, configuration: Configuration).returns(Validator::Result) }
|
36
|
+
def call(package_set, configuration)
|
37
|
+
end
|
38
|
+
|
39
|
+
sig { params(configuration: Configuration, setting: T.untyped).returns(T.untyped) }
|
40
|
+
def package_manifests_settings_for(configuration, setting)
|
41
|
+
package_manifests(configuration).map { |f| [f, (YAML.load_file(File.join(f)) || {})[setting]] }
|
42
|
+
end
|
43
|
+
|
44
|
+
sig do
|
45
|
+
params(configuration: Configuration,
|
46
|
+
glob_pattern: T.nilable(T.any(T::Array[String], String))).returns(T::Array[String])
|
47
|
+
end
|
48
|
+
def package_manifests(configuration, glob_pattern = nil)
|
49
|
+
glob_pattern ||= package_glob(configuration)
|
50
|
+
PackageSet.package_paths(configuration.root_path, glob_pattern, configuration.exclude)
|
51
|
+
.map { |f| File.realpath(f) }
|
52
|
+
end
|
53
|
+
|
54
|
+
sig { params(configuration: Configuration).returns(T.any(T::Array[String], String)) }
|
55
|
+
def package_glob(configuration)
|
56
|
+
configuration.package_paths
|
57
|
+
end
|
58
|
+
|
59
|
+
sig do
|
60
|
+
params(
|
61
|
+
results: T::Array[Validator::Result],
|
62
|
+
separator: String,
|
63
|
+
before_errors: String,
|
64
|
+
after_errors: String,
|
65
|
+
).returns(Validator::Result)
|
66
|
+
end
|
67
|
+
def merge_results(results, separator: "\n", before_errors: "", after_errors: "")
|
68
|
+
results.reject!(&:ok?)
|
69
|
+
|
70
|
+
if results.empty?
|
71
|
+
Validator::Result.new(ok: true)
|
72
|
+
else
|
73
|
+
Validator::Result.new(
|
74
|
+
ok: false,
|
75
|
+
error_value: [
|
76
|
+
before_errors,
|
77
|
+
separator.lstrip,
|
78
|
+
results.map(&:error_value).join(separator),
|
79
|
+
after_errors,
|
80
|
+
].join,
|
81
|
+
)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
sig { params(configuration: Configuration, path: String).returns(Pathname) }
|
86
|
+
def relative_path(configuration, path)
|
87
|
+
Pathname.new(path).relative_path_from(configuration.root_path)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Packwerk
|
5
|
+
module Validators
|
6
|
+
class DependencyValidator
|
7
|
+
extend T::Sig
|
8
|
+
include Validator
|
9
|
+
|
10
|
+
sig do
|
11
|
+
override.params(package_set: PackageSet, configuration: Configuration).returns(Validator::Result)
|
12
|
+
end
|
13
|
+
def call(package_set, configuration)
|
14
|
+
results = [
|
15
|
+
check_package_manifest_syntax(configuration),
|
16
|
+
check_acyclic_graph(package_set),
|
17
|
+
check_valid_package_dependencies(configuration),
|
18
|
+
]
|
19
|
+
|
20
|
+
merge_results(results)
|
21
|
+
end
|
22
|
+
|
23
|
+
sig { override.returns(T::Array[String]) }
|
24
|
+
def permitted_keys
|
25
|
+
[
|
26
|
+
"enforce_dependencies",
|
27
|
+
"dependencies",
|
28
|
+
]
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
sig { params(configuration: Configuration).returns(Validator::Result) }
|
34
|
+
def check_package_manifest_syntax(configuration)
|
35
|
+
errors = []
|
36
|
+
|
37
|
+
valid_settings = [true, false, "strict"]
|
38
|
+
package_manifests_settings_for(configuration, "enforce_dependencies").each do |config, setting|
|
39
|
+
next if setting.nil?
|
40
|
+
|
41
|
+
unless valid_settings.include?(setting)
|
42
|
+
errors << "\tInvalid 'enforce_dependencies' option: #{setting.inspect} in #{config.inspect}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
package_manifests_settings_for(configuration, "dependencies").each do |config, setting|
|
47
|
+
next if setting.nil?
|
48
|
+
|
49
|
+
unless setting.is_a?(Array)
|
50
|
+
errors << "\tInvalid 'dependencies' option: #{setting.inspect} in #{config.inspect}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
if errors.empty?
|
55
|
+
Validator::Result.new(ok: true)
|
56
|
+
else
|
57
|
+
merge_results(
|
58
|
+
errors.map { |error| Validator::Result.new(ok: false, error_value: error) },
|
59
|
+
separator: "\n",
|
60
|
+
before_errors: "Malformed syntax in the following manifests:\n\n",
|
61
|
+
after_errors: "\n",
|
62
|
+
)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
sig { params(package_set: PackageSet).returns(Validator::Result) }
|
67
|
+
def check_acyclic_graph(package_set)
|
68
|
+
edges = package_set.flat_map do |package|
|
69
|
+
package.dependencies.map do |dependency|
|
70
|
+
[package.name, package_set.fetch(dependency)&.name]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
dependency_graph = Graph.new(edges)
|
75
|
+
|
76
|
+
cycle_strings = build_cycle_strings(dependency_graph.cycles)
|
77
|
+
|
78
|
+
if dependency_graph.acyclic?
|
79
|
+
Validator::Result.new(ok: true)
|
80
|
+
else
|
81
|
+
Validator::Result.new(
|
82
|
+
ok: false,
|
83
|
+
error_value: <<~EOS
|
84
|
+
Expected the package dependency graph to be acyclic, but it contains the following circular dependencies:
|
85
|
+
|
86
|
+
#{cycle_strings.join("\n")}
|
87
|
+
EOS
|
88
|
+
)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
sig { params(configuration: Configuration).returns(Validator::Result) }
|
93
|
+
def check_valid_package_dependencies(configuration)
|
94
|
+
packages_dependencies = package_manifests_settings_for(configuration, "dependencies")
|
95
|
+
.delete_if { |_, deps| deps.nil? }
|
96
|
+
|
97
|
+
packages_with_invalid_dependencies =
|
98
|
+
packages_dependencies.each_with_object([]) do |(package, dependencies), invalid_packages|
|
99
|
+
invalid_dependencies = if dependencies.is_a?(Array)
|
100
|
+
dependencies.filter { |path| invalid_package_path?(configuration, path) }
|
101
|
+
else
|
102
|
+
[]
|
103
|
+
end
|
104
|
+
invalid_packages << [package, invalid_dependencies] if invalid_dependencies.any?
|
105
|
+
end
|
106
|
+
|
107
|
+
if packages_with_invalid_dependencies.empty?
|
108
|
+
Validator::Result.new(ok: true)
|
109
|
+
else
|
110
|
+
error_locations = packages_with_invalid_dependencies.map do |package, invalid_dependencies|
|
111
|
+
package ||= configuration.root_path
|
112
|
+
package_path = Pathname.new(package).relative_path_from(configuration.root_path)
|
113
|
+
all_invalid_dependencies = invalid_dependencies.map { |d| " - #{d}" }
|
114
|
+
|
115
|
+
<<~EOS
|
116
|
+
\t#{package_path}:
|
117
|
+
\t#{all_invalid_dependencies.join("\n\t")}
|
118
|
+
EOS
|
119
|
+
end
|
120
|
+
|
121
|
+
Validator::Result.new(
|
122
|
+
ok: false,
|
123
|
+
error_value: "These dependencies do not point to valid packages:\n\n#{error_locations.join("\n")}"
|
124
|
+
)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
sig { params(configuration: Configuration, path: T.untyped).returns(T::Boolean) }
|
129
|
+
def invalid_package_path?(configuration, path)
|
130
|
+
# Packages at the root can be implicitly specified as "."
|
131
|
+
return false if path == "."
|
132
|
+
|
133
|
+
package_path = File.join(configuration.root_path, path, PackageSet::PACKAGE_CONFIG_FILENAME)
|
134
|
+
!File.file?(package_path)
|
135
|
+
end
|
136
|
+
|
137
|
+
# Convert the cycles:
|
138
|
+
#
|
139
|
+
# [[a, b, c], [b, c]]
|
140
|
+
#
|
141
|
+
# to the string:
|
142
|
+
#
|
143
|
+
# ["a -> b -> c -> a", "b -> c -> b"]
|
144
|
+
sig { params(cycles: T.untyped).returns(T::Array[String]) }
|
145
|
+
def build_cycle_strings(cycles)
|
146
|
+
cycles.map do |cycle|
|
147
|
+
cycle_strings = cycle.map(&:to_s)
|
148
|
+
cycle_strings << cycle.first.to_s
|
149
|
+
"\t- #{cycle_strings.join(" → ")}"
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
data/lib/packwerk/version.rb
CHANGED
data/lib/packwerk.rb
CHANGED
@@ -7,45 +7,36 @@ require "fileutils"
|
|
7
7
|
|
8
8
|
# Provides String#pluralize
|
9
9
|
require "active_support/core_ext/string"
|
10
|
+
# Provides Object#to_json
|
11
|
+
require "active_support/core_ext/object/json"
|
10
12
|
|
11
13
|
module Packwerk
|
12
14
|
extend ActiveSupport::Autoload
|
13
15
|
|
14
|
-
|
15
|
-
autoload :
|
16
|
-
autoload :AssociationInspector
|
17
|
-
autoload :OffenseCollection
|
18
|
-
autoload :Cache
|
16
|
+
# Public APIs
|
17
|
+
autoload :Checker
|
19
18
|
autoload :Cli
|
20
19
|
autoload :Configuration
|
21
|
-
autoload :
|
22
|
-
autoload :ConstantNameInspector
|
23
|
-
autoload :ConstNodeInspector
|
24
|
-
autoload :PackageTodo
|
25
|
-
autoload :FileProcessor
|
26
|
-
autoload :FilesForProcessing
|
27
|
-
autoload :Graph
|
20
|
+
autoload :ConstantContext
|
28
21
|
autoload :Node
|
29
|
-
autoload :NodeHelpers
|
30
|
-
autoload :NodeProcessor
|
31
|
-
autoload :NodeProcessorFactory
|
32
|
-
autoload :NodeVisitor
|
33
22
|
autoload :Offense
|
23
|
+
autoload :OffenseCollection
|
34
24
|
autoload :OffensesFormatter
|
35
25
|
autoload :OutputStyle
|
36
26
|
autoload :Package
|
37
27
|
autoload :PackageSet
|
38
|
-
autoload :
|
28
|
+
autoload :PackageTodo
|
39
29
|
autoload :Parsers
|
40
|
-
autoload :
|
41
|
-
autoload :UnresolvedReference
|
30
|
+
autoload :RailsLoadPaths
|
42
31
|
autoload :Reference
|
43
|
-
autoload :ReferenceExtractor
|
44
32
|
autoload :ReferenceOffense
|
45
|
-
autoload :
|
46
|
-
|
47
|
-
|
48
|
-
|
33
|
+
autoload :Validator
|
34
|
+
|
35
|
+
class Cli
|
36
|
+
extend ActiveSupport::Autoload
|
37
|
+
|
38
|
+
autoload :Result
|
39
|
+
end
|
49
40
|
|
50
41
|
module OutputStyles
|
51
42
|
extend ActiveSupport::Autoload
|
@@ -61,10 +52,37 @@ module Packwerk
|
|
61
52
|
module Formatters
|
62
53
|
extend ActiveSupport::Autoload
|
63
54
|
|
64
|
-
autoload :OffensesFormatter
|
65
55
|
autoload :ProgressFormatter
|
66
56
|
end
|
67
57
|
|
58
|
+
module Validator
|
59
|
+
extend ActiveSupport::Autoload
|
60
|
+
|
61
|
+
autoload :Result
|
62
|
+
end
|
63
|
+
|
64
|
+
# Private APIs
|
65
|
+
# Please submit an issue if you have a use-case for these
|
66
|
+
autoload :ApplicationValidator
|
67
|
+
autoload :AssociationInspector
|
68
|
+
autoload :Cache
|
69
|
+
autoload :ConstantDiscovery
|
70
|
+
autoload :ConstantNameInspector
|
71
|
+
autoload :ConstNodeInspector
|
72
|
+
autoload :ExtensionLoader
|
73
|
+
autoload :FileProcessor
|
74
|
+
autoload :FilesForProcessing
|
75
|
+
autoload :Graph
|
76
|
+
autoload :NodeHelpers
|
77
|
+
autoload :NodeProcessor
|
78
|
+
autoload :NodeProcessorFactory
|
79
|
+
autoload :NodeVisitor
|
80
|
+
autoload :ParsedConstantDefinitions
|
81
|
+
autoload :ParseRun
|
82
|
+
autoload :ReferenceExtractor
|
83
|
+
autoload :RunContext
|
84
|
+
autoload :UnresolvedReference
|
85
|
+
|
68
86
|
module Generators
|
69
87
|
extend ActiveSupport::Autoload
|
70
88
|
|
@@ -72,6 +90,8 @@ module Packwerk
|
|
72
90
|
autoload :RootPackage
|
73
91
|
end
|
74
92
|
|
93
|
+
private_constant :Generators
|
94
|
+
|
75
95
|
module ReferenceChecking
|
76
96
|
extend ActiveSupport::Autoload
|
77
97
|
|
@@ -80,9 +100,27 @@ module Packwerk
|
|
80
100
|
module Checkers
|
81
101
|
extend ActiveSupport::Autoload
|
82
102
|
|
83
|
-
autoload :Checker
|
84
103
|
autoload :DependencyChecker
|
85
104
|
autoload :PrivacyChecker
|
86
105
|
end
|
87
106
|
end
|
107
|
+
|
108
|
+
private_constant :ReferenceChecking
|
109
|
+
|
110
|
+
class ApplicationValidator
|
111
|
+
extend ActiveSupport::Autoload
|
112
|
+
|
113
|
+
autoload :Helpers
|
114
|
+
end
|
88
115
|
end
|
116
|
+
|
117
|
+
require "packwerk/version"
|
118
|
+
|
119
|
+
# Required to register the DefaultOffensesFormatter
|
120
|
+
# We put this at the *end* of the file to specify all autoloads first
|
121
|
+
require "packwerk/formatters/default_offenses_formatter"
|
122
|
+
|
123
|
+
# Required to register the default DependencyChecker
|
124
|
+
require "packwerk/reference_checking/checkers/dependency_checker"
|
125
|
+
# Required to register the default DependencyValidator
|
126
|
+
require "packwerk/validators/dependency_validator"
|
data/packwerk.gemspec
CHANGED
@@ -38,9 +38,9 @@ Gem::Specification.new do |spec|
|
|
38
38
|
end
|
39
39
|
spec.require_paths = ["lib"]
|
40
40
|
|
41
|
-
spec.required_ruby_version = ">= 2.
|
41
|
+
spec.required_ruby_version = ">= 2.7"
|
42
42
|
|
43
|
-
spec.add_dependency("activesupport", ">=
|
43
|
+
spec.add_dependency("activesupport", ">= 6.0")
|
44
44
|
spec.add_dependency("bundler")
|
45
45
|
spec.add_dependency("constant_resolver", ">= 0.2.0")
|
46
46
|
spec.add_dependency("parallel")
|
@@ -53,4 +53,6 @@ Gem::Specification.new do |spec|
|
|
53
53
|
|
54
54
|
# For ERB parsing
|
55
55
|
spec.add_dependency("better_html")
|
56
|
+
|
57
|
+
spec.add_development_dependency("railties")
|
56
58
|
end
|