packwerk 1.2.0 → 1.3.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: ced63ca0995c039913777f3e8ba1aac428970d8fc515b1629c9212f71baab34b
4
- data.tar.gz: 331b0a5f30e7104b4eb3e44920739ea592e7e3dc7df3dca339a74260fa13d62b
3
+ metadata.gz: c73a1063d42615133bdd6a3cc797838f0d4a0b71c716a5a6dd2730c125723ca8
4
+ data.tar.gz: ede1cf336fb3c64f0093c9b853bc4db9e06004d8bfd297fd9ff60a6253c16e1c
5
5
  SHA512:
6
- metadata.gz: a487a501ca28d341a888eea2e0ec13c4831897680ce1d17bef2a4943408ff718d75cffe9a50030fd93d7a2388d161c7a3cd946a0764930f89016c2f2c81e5306
7
- data.tar.gz: d4685f869617c8b1141125fcaacbde96839be3d239aa2422db6f76dbcb485f42fcde97e0c6aaa580ef4abcd847ebbfd9979fe4896f0bc5c7421d104673346981
6
+ metadata.gz: 3a2dd60787d4b8bb40e40491fb364321c0e2d086df7315b64ccb7a27b21f28d4e5e1855d40b52c1aadcbaf61d02ececa43d186fc10abdbe1de2c9609469586ef
7
+ data.tar.gz: 327267b82f798960ccf5a295125a980077bcfb9dfc00587583dcefbdcd1bfcea935f79f0f4c2efebad8d90d08807d6f08d800240bc4315ded513abdca9efcce0
@@ -30,7 +30,7 @@ jobs:
30
30
  run: |
31
31
  gem install bundler
32
32
  bundle install --jobs 4 --retry 3
33
- bundle exec rake
33
+ bin/rake
34
34
  lint:
35
35
  runs-on: ubuntu-latest
36
36
  steps:
@@ -43,7 +43,7 @@ jobs:
43
43
  run: |
44
44
  gem install bundler
45
45
  bundle install --jobs 4 --retry 3
46
- bundle exec rubocop
46
+ bin/rubocop
47
47
  static-type-checking:
48
48
  runs-on: ubuntu-latest
49
49
  steps:
@@ -56,4 +56,4 @@ jobs:
56
56
  run: |
57
57
  gem install bundler
58
58
  bundle install --jobs 4 --retry 3
59
- bundle exec srb tc
59
+ bin/srb tc
data/Gemfile.lock CHANGED
@@ -87,7 +87,7 @@ GIT
87
87
  PATH
88
88
  remote: .
89
89
  specs:
90
- packwerk (1.2.0)
90
+ packwerk (1.3.0)
91
91
  activesupport (>= 5.2)
92
92
  ast
93
93
  better_html
data/README.md CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  ## NOTE: Packwerk is considered to be feature-complete for Shopify's uses. We are currently accepting bug fixes only, and it is not being actively developed. Please fork this project if you are interested in adding new features.
4
4
 
5
- > "I know who you are and because of that I know what you do."
6
- > This knowledge is a dependency that raises the cost of change.
5
+ > "I know who you are and because of that I know what you do."
6
+ > This knowledge is a dependency that raises the cost of change.
7
7
 
8
8
  -- _Sandi Metz, Practical Object-Oriented Design in Ruby_
9
9
 
@@ -47,7 +47,7 @@ Or install it yourself as:
47
47
 
48
48
  $ gem install packwerk
49
49
 
50
- 3. Run `bundle exec packwerk init` to generate the configuration files
50
+ 3. Run `packwerk init` to generate the configuration files
51
51
 
52
52
  ## Usage
53
53
 
@@ -59,7 +59,7 @@ Read [USAGE.md](USAGE.md) for usage once Packwerk is installed on your project.
59
59
 
60
60
  ## Development
61
61
 
62
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
62
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
63
63
 
64
64
  ## Limitations
65
65
 
data/TROUBLESHOOT.md CHANGED
@@ -14,9 +14,9 @@ Packwerk can give feedback via continuous integration (CI) if you have it set up
14
14
 
15
15
  You can specify folders or packages in Packwerk commands for a shorter run time:
16
16
 
17
- bundle exec packwerk check components/your_package
17
+ packwerk check components/your_package
18
18
 
19
- bundle exec packwerk update-deprecations components/your_package
19
+ packwerk update-deprecations components/your_package
20
20
 
21
21
  _Note: You cannot specify folders or packages for `packwerk validate` because the command runs for the entire application._
22
22
 
data/USAGE.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # Packwerk usage
2
2
 
3
3
  ## Table of Contents
4
+
4
5
  * [What problem does Packwerk solve?](#what-problem-does-packwerk-solve)
5
6
  * [What is a package?](#what-is-a-package)
6
7
  * [Package principles](#package-principles)
@@ -19,11 +20,13 @@
19
20
  * [Understanding the list of deprecated references](#understanding-the-list-of-deprecated-references)
20
21
 
21
22
  ## What problem does Packwerk solve?
23
+
22
24
  Large applications need clear boundaries to avoid turning into a [ball of mud](https://en.wikipedia.org/wiki/Big_ball_of_mud). However, Ruby does not provide a good solution to enforcing boundaries between code.
23
25
 
24
26
  Packwerk is a gem that can be used to enforce boundaries between groups of code we call packages.
25
27
 
26
28
  ## What is a package?
29
+
27
30
  A package is a folder containing autoloaded code. To decide whether code belongs together in a package, these are some design best practices:
28
31
 
29
32
  - We should package things together that have high functional [cohesion](https://en.wikipedia.org/wiki/Cohesion_(computer_science)).
@@ -41,7 +44,7 @@ The [package principles](https://en.wikipedia.org/wiki/Package_principles) page
41
44
 
42
45
  After including Packwerk in the Gemfile, you can generate the necessary files to get Packwerk running by executing:
43
46
 
44
- bundle exec packwerk init
47
+ packwerk init
45
48
 
46
49
  Here is a list of files generated:
47
50
 
@@ -49,8 +52,6 @@ Here is a list of files generated:
49
52
  |-----------------------------|--------------|------------|
50
53
  | Packwerk configuration | packwerk.yml | See [Setting up the configuration file](#Setting-up-the-configuration-file) |
51
54
  | Root package | package.yml | A package for the root folder |
52
- | Bin script | bin/packwerk | For Rails applications to run Packwerk validation on CI, see [Validating the package system](#Validating-the-package-system) |
53
- | Validation test | test/packwerk_validator_test.rb | For Ruby projects to run Packwerk validation using tests, see [Validating the package system](#Validating-the-package-system) |
54
55
  | Custom inflections | config/inflections.yml | A custom inflections file is only required if you have custom inflections in `inflections.rb`, see [Inflections](#Inflections) |
55
56
 
56
57
  After that, you may begin creating packages for your application. See [Defining packages](#Defining-packages)
@@ -133,18 +134,14 @@ Any new inflectors should be added to `config/inflections.yml`.
133
134
 
134
135
  There are some criteria that an application must meet in order to have a valid package system. These criteria include having a valid autoload path cache, package definition files, and application folder structure. The dependency graph within the package system also has to be acyclic.
135
136
 
136
- The package system can be validated through a series of built in validation checks. Currently, the validation checks require the application to be booted either through `spring` or as part of its test suite.
137
-
138
137
  We recommend setting up the package system validation for your Rails application in a CI step (or through a test suite for Ruby projects) separate from `packwerk check`.
139
138
 
140
- If running `packwerk init` generates a `bin/packwerk` script, proceed to run:
139
+ Use the following command to validate the application:
141
140
 
142
- bin/packwerk validate
141
+ packwerk validate
143
142
 
144
143
  ![](static/packwerk_validate.gif)
145
144
 
146
- If running `packwerk init` on your Ruby project generates `test/packwerk_validator_test.rb`, you can use this test as validation.
147
-
148
145
  ## Defining packages
149
146
 
150
147
  You can create a `package.yml` in any folder to make it a package. The package name is the path to the folder from the project root.
@@ -152,6 +149,7 @@ You can create a `package.yml` in any folder to make it a package. The package n
152
149
  _Note: It is helpful to define a namespace that corresponds to the package name and contains at least all the public constants of the package. This makes it more obvious which package a constant is defined in._
153
150
 
154
151
  ### Package metadata
152
+
155
153
  Package metadata can be included in the `package.yml`. Metadata won't be validated, and can thus be anything. We recommend including information on ownership and stewardship of the package.
156
154
 
157
155
  Example:
@@ -169,6 +167,7 @@ Example:
169
167
  Packwerk can perform two types of boundary checks: privacy and dependency.
170
168
 
171
169
  #### Enforcing privacy boundary
170
+
172
171
  A package's privacy boundary is violated when there is a reference to the package's private constants from a source outside the package.
173
172
 
174
173
  There are two ways you can enforce privacy for your package:
@@ -228,13 +227,13 @@ It will be a dependency violation when `components/shop_identity` tries to refer
228
227
 
229
228
  After enforcing the boundary checks for a package, you may execute:
230
229
 
231
- bundle exec packwerk check
230
+ packwerk check
232
231
 
233
- Packwerk will check the entire codebase for any violations.
232
+ Packwerk will check the entire codebase for any new or stale violations.
234
233
 
235
234
  You can also specify folders or packages for a shorter run time:
236
235
 
237
- bundle exec packwerk check components/your_package
236
+ packwerk check components/your_package
238
237
 
239
238
  ![](static/packwerk_check.gif)
240
239
 
@@ -248,11 +247,11 @@ For existing codebases, packages are likely to have existing boundary violations
248
247
 
249
248
  If so, you will want to stop the bleeding and prevent more violations from occuring. The existing violations in the codebase can be recorded in a [deprecated references list](#Understanding_the_list_of_deprecated_references) by executing:
250
249
 
251
- bundle exec packwerk update-deprecations
250
+ packwerk update-deprecations
252
251
 
253
252
  Similar to `packwerk check`, you may also run `packwerk update-deprecations` on folders or packages:
254
253
 
255
- bundle exec packwerk update-deprecations components/your_package
254
+ packwerk update-deprecations components/your_package
256
255
 
257
256
  ![](static/packwerk_update.gif)
258
257
 
data/bin/m ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'm' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("m", "m")
data/bin/rake ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rake' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("rake", "rake")
data/bin/rubocop ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rubocop' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("rubocop", "rubocop")
data/bin/srb ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'srb' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("sorbet", "srb")
data/bin/tapioca ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'tapioca' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("tapioca", "tapioca")
data/dev.yml CHANGED
@@ -12,21 +12,21 @@ commands:
12
12
  if [[ "$*" =~ ":"[0-9]+ ]];
13
13
  then
14
14
  # run test by its line number
15
- bundle exec m "$@"
15
+ bin/m "$@"
16
16
  elif [[ "$#" -eq 1 && -f "$1" ]];
17
17
  then
18
18
  # run all tests in given file(s)
19
- bundle exec rake test TEST="$@"
19
+ bin/rake test TEST="$@"
20
20
  else
21
21
  # run all tests
22
- bundle exec rake test
22
+ bin/rake test
23
23
  fi
24
- style: "bundle exec rubocop -D --auto-correct"
24
+ style: "bin/rubocop -D --auto-correct"
25
25
  typecheck:
26
26
  desc: "run Sorbet typechecking"
27
- run: "bundle exec srb tc"
27
+ run: "bin/srb tc"
28
28
  aliases: ['tc']
29
29
  subcommands:
30
30
  update:
31
31
  desc: "update RBIs for gems"
32
- run: "bundle exec tapioca sync -c 'dev typecheck update'"
32
+ run: "bin/tapioca sync -c 'dev typecheck update'"
data/lib/packwerk.rb CHANGED
@@ -73,7 +73,6 @@ module Packwerk
73
73
  module Generators
74
74
  extend ActiveSupport::Autoload
75
75
 
76
- autoload :ApplicationValidation
77
76
  autoload :ConfigurationFile
78
77
  autoload :InflectionsFile
79
78
  autoload :RootPackage
@@ -8,20 +8,15 @@ module Packwerk
8
8
  class << self
9
9
  extend T::Sig
10
10
 
11
- sig { returns(T::Array[String]) }
12
- def extract_relevant_paths
13
- assert_application_booted
11
+ sig { params(root: String, environment: String).returns(T::Array[String]) }
12
+ def extract_relevant_paths(root, environment)
13
+ require_application(root, environment)
14
14
  all_paths = extract_application_autoload_paths
15
15
  relevant_paths = filter_relevant_paths(all_paths)
16
16
  assert_load_paths_present(relevant_paths)
17
17
  relative_path_strings(relevant_paths)
18
18
  end
19
19
 
20
- sig { void }
21
- def assert_application_booted
22
- raise "The application needs to be booted to extract load paths" unless defined?(::Rails)
23
- end
24
-
25
20
  sig { returns(T::Array[String]) }
26
21
  def extract_application_autoload_paths
27
22
  Rails.application.railties
@@ -54,6 +49,21 @@ module Packwerk
54
49
  .uniq
55
50
  end
56
51
 
52
+ private
53
+
54
+ sig { params(root: String, environment: String).void }
55
+ def require_application(root, environment)
56
+ environment_file = "#{root}/config/environment"
57
+
58
+ if File.file?("#{environment_file}.rb")
59
+ ENV["RAILS_ENV"] ||= environment
60
+
61
+ require environment_file
62
+ else
63
+ raise "A Rails application could not be found in #{root}"
64
+ end
65
+ end
66
+
57
67
  sig { params(paths: T::Array[T.untyped]).void }
58
68
  def assert_load_paths_present(paths)
59
69
  if paths.empty?
@@ -1,4 +1,4 @@
1
- # typed: false
1
+ # typed: true
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "active_support/inflector/inflections"
@@ -8,11 +8,12 @@ require "yaml"
8
8
 
9
9
  module Packwerk
10
10
  class ApplicationValidator
11
- def initialize(config_file_path:, configuration:)
11
+ def initialize(config_file_path:, configuration:, environment:)
12
12
  @config_file_path = config_file_path
13
13
  @configuration = configuration
14
+ @environment = environment
14
15
 
15
- @application_load_paths = ApplicationLoadPaths.extract_relevant_paths
16
+ @application_load_paths = ApplicationLoadPaths.extract_relevant_paths(configuration.root_path, environment)
16
17
  end
17
18
 
18
19
  Result = Struct.new(:ok?, :error_value)
@@ -176,21 +177,9 @@ module Packwerk
176
177
  edges = package_set.flat_map do |package|
177
178
  package.dependencies.map { |dependency| [package, package_set.fetch(dependency)] }
178
179
  end
179
- dependency_graph = Packwerk::Graph.new(*edges)
180
-
181
- # Convert the cycle
182
- #
183
- # [a, b, c]
184
- #
185
- # to the string
186
- #
187
- # a -> b -> c -> a
188
- #
189
- cycle_strings = dependency_graph.cycles.map do |cycle|
190
- cycle_strings = cycle.map(&:to_s)
191
- cycle_strings << cycle.first.to_s
192
- "\t- #{cycle_strings.join(" → ")}"
193
- end
180
+ dependency_graph = Packwerk::Graph.new(*T.unsafe(edges))
181
+
182
+ cycle_strings = build_cycle_strings(dependency_graph.cycles)
194
183
 
195
184
  if dependency_graph.acyclic?
196
185
  Result.new(true)
@@ -279,6 +268,21 @@ module Packwerk
279
268
 
280
269
  private
281
270
 
271
+ # Convert the cycles:
272
+ #
273
+ # [[a, b, c], [b, c]]
274
+ #
275
+ # to the string:
276
+ #
277
+ # ["a -> b -> c -> a", "b -> c -> b"]
278
+ def build_cycle_strings(cycles)
279
+ cycles.map do |cycle|
280
+ cycle_strings = cycle.map(&:to_s)
281
+ cycle_strings << cycle.first.to_s
282
+ "\t- #{cycle_strings.join(" → ")}"
283
+ end
284
+ end
285
+
282
286
  def package_manifests_settings_for(setting)
283
287
  package_manifests.map { |f| [f, (YAML.load_file(File.join(f)) || {})[setting]] }
284
288
  end
data/lib/packwerk/cli.rb CHANGED
@@ -10,6 +10,7 @@ module Packwerk
10
10
  configuration: T.nilable(Configuration),
11
11
  out: T.any(StringIO, IO),
12
12
  err_out: T.any(StringIO, IO),
13
+ environment: String,
13
14
  style: Packwerk::OutputStyle,
14
15
  offenses_formatter: T.nilable(Packwerk::OffensesFormatter)
15
16
  ).void
@@ -18,11 +19,13 @@ module Packwerk
18
19
  configuration: nil,
19
20
  out: $stdout,
20
21
  err_out: $stderr,
22
+ environment: "test",
21
23
  style: OutputStyles::Plain.new,
22
24
  offenses_formatter: nil
23
25
  )
24
26
  @out = out
25
27
  @err_out = err_out
28
+ @environment = environment
26
29
  @style = style
27
30
  @configuration = configuration || Configuration.from_path
28
31
  @progress_formatter = Formatters::ProgressFormatter.new(@out, style: style)
@@ -77,28 +80,12 @@ module Packwerk
77
80
  def init
78
81
  @out.puts("📦 Initializing Packwerk...")
79
82
 
80
- application_validation = Packwerk::Generators::ApplicationValidation.generate(
81
- for_rails_app: rails_app?,
82
- root: @configuration.root_path,
83
- out: @out
84
- )
85
-
86
- if application_validation
87
- if rails_app?
88
- # To run in the same space as the Rails process,
89
- # in order to fetch load paths for the configuration generator
90
- exec("bin/packwerk", "generate_configs")
91
- else
92
- generate_configurations = generate_configs
93
- end
94
- end
95
-
96
- application_validation && generate_configurations
83
+ generate_configs
97
84
  end
98
85
 
99
86
  def generate_configs
100
87
  configuration_file = Packwerk::Generators::ConfigurationFile.generate(
101
- load_paths: Packwerk::ApplicationLoadPaths.extract_relevant_paths,
88
+ load_paths: Packwerk::ApplicationLoadPaths.extract_relevant_paths(@configuration.root_path, @environment),
102
89
  root: @configuration.root_path,
103
90
  out: @out
104
91
  )
@@ -144,14 +131,11 @@ module Packwerk
144
131
  end
145
132
 
146
133
  def validate(_paths)
147
- warn("`packwerk validate` should be run within the application. "\
148
- "Generate the bin script using `packwerk init` and"\
149
- " use `bin/packwerk validate` instead.") unless defined?(::Rails)
150
-
151
134
  @progress_formatter.started_validation do
152
135
  checker = Packwerk::ApplicationValidator.new(
153
136
  config_file_path: @configuration.config_path,
154
- configuration: @configuration
137
+ configuration: @configuration,
138
+ environment: @environment,
155
139
  )
156
140
  result = checker.check_all
157
141
 
@@ -171,15 +155,6 @@ module Packwerk
171
155
  end
172
156
  end
173
157
 
174
- sig { returns(T::Boolean) }
175
- def rails_app?
176
- if File.exist?("config/application.rb") && File.exist?("bin/rails")
177
- File.foreach("Gemfile").any? { |line| line.match?(/['"]rails['"]/) }
178
- else
179
- false
180
- end
181
- end
182
-
183
158
  def parse_run(paths)
184
159
  ParseRun.new(
185
160
  files: fetch_files_to_process(paths),
@@ -73,7 +73,7 @@ module Packwerk
73
73
  #
74
74
  # You can regenerate this file using the following command:
75
75
  #
76
- # bundle exec packwerk update-deprecations #{@package.name}
76
+ # packwerk update-deprecations #{@package.name}
77
77
  MESSAGE
78
78
  File.open(@filepath, "w") do |f|
79
79
  f.write(message)
@@ -15,7 +15,7 @@ module Packwerk
15
15
 
16
16
  sig { override.params(offenses: T::Array[T.nilable(Offense)]).returns(String) }
17
17
  def show_offenses(offenses)
18
- return "No offenses detected 🎉" if offenses.empty?
18
+ return "No offenses detected" if offenses.empty?
19
19
 
20
20
  <<~EOS
21
21
  #{offenses_list(offenses)}
@@ -23,6 +23,15 @@ module Packwerk
23
23
  EOS
24
24
  end
25
25
 
26
+ sig { override.params(offense_collection: Packwerk::OffenseCollection).returns(String) }
27
+ def show_stale_violations(offense_collection)
28
+ if offense_collection.stale_violations?
29
+ "There were stale violations found, please run `packwerk update-deprecations`"
30
+ else
31
+ "No stale violations detected"
32
+ end
33
+ end
34
+
26
35
  private
27
36
 
28
37
  sig { params(offenses: T::Array[T.nilable(Offense)]).returns(String) }
@@ -11,5 +11,9 @@ module Packwerk
11
11
  sig { abstract.params(offenses: T::Array[T.nilable(Offense)]).returns(String) }
12
12
  def show_offenses(offenses)
13
13
  end
14
+
15
+ sig { abstract.params(offense_collection: Packwerk::OffenseCollection).returns(String) }
16
+ def show_stale_violations(offense_collection)
17
+ end
14
18
  end
15
19
  end
@@ -33,7 +33,15 @@ module Packwerk
33
33
  end
34
34
 
35
35
  def public_path
36
- @public_path ||= File.join(@name, user_defined_public_path || "app/public/")
36
+ @public_path ||= begin
37
+ unprefixed_public_path = user_defined_public_path || "app/public/"
38
+
39
+ if root?
40
+ unprefixed_public_path
41
+ else
42
+ File.join(@name, unprefixed_public_path)
43
+ end
44
+ end
37
45
  end
38
46
 
39
47
  def public_path?(path)
@@ -24,11 +24,7 @@ module Packwerk
24
24
  offense_collection = find_offenses
25
25
 
26
26
  result_status = !offense_collection.stale_violations?
27
- message = if result_status
28
- "No stale violations detected"
29
- else
30
- "There were stale violations found, please run `packwerk update-deprecations`"
31
- end
27
+ message = @offenses_formatter.show_stale_violations(offense_collection)
32
28
 
33
29
  Result.new(message: message, status: result_status)
34
30
  end
@@ -47,8 +43,14 @@ module Packwerk
47
43
 
48
44
  def check
49
45
  offense_collection = find_offenses(show_errors: true)
50
- message = @offenses_formatter.show_offenses(offense_collection.outstanding_offenses)
51
- Result.new(message: message, status: offense_collection.outstanding_offenses.empty?)
46
+
47
+ messages = [
48
+ @offenses_formatter.show_offenses(offense_collection.outstanding_offenses),
49
+ @offenses_formatter.show_stale_violations(offense_collection),
50
+ ]
51
+ result_status = offense_collection.outstanding_offenses.empty? && !offense_collection.stale_violations?
52
+
53
+ Result.new(message: messages.join("\n") + "\n", status: result_status)
52
54
  end
53
55
 
54
56
  private
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Packwerk
5
- VERSION = "1.2.0"
5
+ VERSION = "1.3.0"
6
6
  end
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.2.0
4
+ version: 1.3.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: 2021-06-10 00:00:00.000000000 Z
11
+ date: 2021-07-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -192,7 +192,12 @@ files:
192
192
  - TROUBLESHOOT.md
193
193
  - USAGE.md
194
194
  - bin/console
195
+ - bin/m
196
+ - bin/rake
197
+ - bin/rubocop
195
198
  - bin/setup
199
+ - bin/srb
200
+ - bin/tapioca
196
201
  - dev.yml
197
202
  - docs/cohesion.png
198
203
  - exe/packwerk
@@ -213,15 +218,12 @@ files:
213
218
  - lib/packwerk/files_for_processing.rb
214
219
  - lib/packwerk/formatters/offenses_formatter.rb
215
220
  - lib/packwerk/formatters/progress_formatter.rb
216
- - lib/packwerk/generators/application_validation.rb
217
221
  - lib/packwerk/generators/configuration_file.rb
218
222
  - lib/packwerk/generators/inflections_file.rb
219
223
  - lib/packwerk/generators/root_package.rb
220
224
  - lib/packwerk/generators/templates/inflections.yml
221
225
  - lib/packwerk/generators/templates/package.yml
222
- - lib/packwerk/generators/templates/packwerk
223
226
  - lib/packwerk/generators/templates/packwerk.yml.erb
224
- - lib/packwerk/generators/templates/packwerk_validator_test.rb
225
227
  - lib/packwerk/graph.rb
226
228
  - lib/packwerk/inflections/custom.rb
227
229
  - lib/packwerk/inflections/default.rb
@@ -251,7 +253,6 @@ files:
251
253
  - lib/packwerk/result.rb
252
254
  - lib/packwerk/run_context.rb
253
255
  - lib/packwerk/sanity_checker.rb
254
- - lib/packwerk/spring_command.rb
255
256
  - lib/packwerk/version.rb
256
257
  - lib/packwerk/violation_type.rb
257
258
  - library.yml
@@ -353,7 +354,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
353
354
  - !ruby/object:Gem::Version
354
355
  version: '0'
355
356
  requirements: []
356
- rubygems_version: 3.2.17
357
+ rubygems_version: 3.2.20
357
358
  signing_key:
358
359
  specification_version: 4
359
360
  summary: Packages for applications based on the zeitwerk autoloader
@@ -1,62 +0,0 @@
1
- # typed: true
2
- # frozen_string_literal: true
3
-
4
- module Packwerk
5
- module Generators
6
- class ApplicationValidation
7
- class << self
8
- def generate(for_rails_app: false, root: ".", out: $stdout)
9
- new(root, out: out).generate(for_rails_app: for_rails_app)
10
- end
11
- end
12
-
13
- def initialize(root, out: $stdout)
14
- @root = root
15
- @out = out
16
- end
17
-
18
- def generate(for_rails_app:)
19
- @out.puts("📦 Generating application validator...")
20
- if for_rails_app
21
- generate_packwerk_validate_script
22
- else
23
- generate_validation_test
24
- end
25
- end
26
-
27
- private
28
-
29
- def generate_packwerk_validate_script
30
- destination_file_path = File.join(@root, "bin")
31
- FileUtils.mkdir_p(destination_file_path)
32
-
33
- if File.exist?(File.join(destination_file_path, "packwerk"))
34
- @out.puts("⚠️ Packwerk application validation bin script already exists.")
35
- return true
36
- end
37
-
38
- source_file_path = File.expand_path("templates/packwerk", __dir__)
39
- FileUtils.cp(source_file_path, destination_file_path)
40
-
41
- @out.puts("✅ Packwerk application validation bin script generated in #{destination_file_path}")
42
- true
43
- end
44
-
45
- def generate_validation_test
46
- destination_file_path = File.join(@root, "test")
47
- FileUtils.mkdir_p(destination_file_path)
48
-
49
- if File.exist?(File.join(destination_file_path, "packwerk_validator_test.rb"))
50
- @out.puts("⚠️ Packwerk application validation test already exists.")
51
- return true
52
- end
53
-
54
- source_file_path = File.expand_path("templates/packwerk_validator_test.rb", __dir__)
55
- FileUtils.cp(source_file_path, destination_file_path)
56
-
57
- @out.puts("✅ Packwerk application validation test generated in #{destination_file_path}")
58
- true
59
- end
60
- end
61
- end
62
- end
@@ -1,23 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- # This file was auto-generated by Packwerk through `packwerk init`
5
-
6
- # Needs to be run in test environment in order to have test helper paths available in the autoload paths
7
- ENV["RAILS_ENV"] = "test"
8
-
9
- # Command line arguments needs to be duplicated because spring modifies it
10
- packwerk_argv = ARGV.dup
11
-
12
- begin
13
- load(File.expand_path("spring", __dir__))
14
- rescue LoadError => e
15
- raise unless e.message.include?("spring")
16
- end
17
-
18
- require File.expand_path("../config/environment", __dir__)
19
-
20
- require "packwerk"
21
-
22
- cli = Packwerk::Cli.new
23
- cli.run(packwerk_argv)
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "test_helper"
4
- require "packwerk"
5
-
6
- # This test is necessary to make sure that the package system is working correctly
7
- class PackwerkValidatorTest < Minitest::Test
8
- def test_the_application_is_correctly_set_up_for_the_package_system
9
- assert(Packwerk::Cli.new.execute_command(["validate"]))
10
- end
11
- end
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
- # typed: false
3
-
4
- require "spring/commands"
5
-
6
- module Packwerk
7
- class SpringCommand
8
- def env(*)
9
- # Packwerk needs to run in a test environment, which has a set of autoload paths that are
10
- # often a superset of the dev/prod paths (for example, test/support/helpers)
11
- "test"
12
- end
13
-
14
- def exec_name
15
- "packwerk"
16
- end
17
-
18
- def gem_name
19
- "packwerk"
20
- end
21
-
22
- def call
23
- load(Gem.bin_path(gem_name, exec_name))
24
- end
25
- end
26
-
27
- Spring.register_command("packwerk", SpringCommand.new)
28
- end