rubocop-solidus 0.1.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 +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +23 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +70 -0
- data/LICENSE.txt +21 -0
- data/README.md +70 -0
- data/Rakefile +34 -0
- data/config/default.yml +69 -0
- data/lib/rubocop/cop/mixin/target_solidus_version.rb +70 -0
- data/lib/rubocop/cop/solidus/class_eval_decorator.rb +47 -0
- data/lib/rubocop/cop/solidus/reimbursement_hook_deprecated.rb +31 -0
- data/lib/rubocop/cop/solidus/spree_calculator_free_shipping_deprecated.rb +24 -0
- data/lib/rubocop/cop/solidus/spree_calculator_percent_per_item_deprecated.rb +28 -0
- data/lib/rubocop/cop/solidus/spree_calculator_price_sack_deprecated.rb +24 -0
- data/lib/rubocop/cop/solidus/spree_default_credit_card_deprecated.rb +38 -0
- data/lib/rubocop/cop/solidus/spree_gateway_bogus_deprecated.rb +51 -0
- data/lib/rubocop/cop/solidus/spree_icon_deprecated.rb +39 -0
- data/lib/rubocop/cop/solidus/spree_refund_call_perform.rb +32 -0
- data/lib/rubocop/cop/solidus/spree_t_deprecated.rb +107 -0
- data/lib/rubocop/cop/solidus_cops.rb +14 -0
- data/lib/rubocop/solidus/inject.rb +20 -0
- data/lib/rubocop/solidus/version.rb +7 -0
- data/lib/rubocop/solidus.rb +16 -0
- data/lib/rubocop-solidus.rb +11 -0
- data/sig/rubocop/solidus.rbs +6 -0
- data/tasks/changelog.rake +34 -0
- data/tasks/changelog.rb +180 -0
- data/tasks/cut_release.rake +75 -0
- metadata +91 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 3f5300b213565a1a439d50b1e8a10f1fdb85559dd82c22590d583afaee88cd80
|
4
|
+
data.tar.gz: f449296bd8ce1235e5760eb0284ca29b33634ed6fc095230f4837bb60a72a28f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3c2704f57083a3bfdb599b5e8fd684271703a541a1e636307955a798c8ddcb3db79fa61698840ecc76b90917e6063f24c0582fb45fda1403b605abb4f99c28be
|
7
|
+
data.tar.gz: 40fe450071e0b1bfcf88b989090d1fdd4cd6e2837eadab97cdc88bc618124453050c1fce6a9118978cf32683d73fcc6655bed0ddc4878d141004f8a8f80c4bc1
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
AllCops:
|
2
|
+
NewCops: enable
|
3
|
+
TargetRubyVersion: 2.4
|
4
|
+
|
5
|
+
Naming/FileName:
|
6
|
+
Exclude:
|
7
|
+
- lib/rubocop-solidus.rb
|
8
|
+
|
9
|
+
Metrics/BlockLength:
|
10
|
+
Exclude:
|
11
|
+
- 'Rakefile'
|
12
|
+
- '**/*.rake'
|
13
|
+
- 'spec/**/*.rb'
|
14
|
+
- '*.gemspec'
|
15
|
+
|
16
|
+
Metrics/ClassLength:
|
17
|
+
Exclude:
|
18
|
+
- 'tasks/**/*.rb'
|
19
|
+
|
20
|
+
# Prevents Ruby 3.1 incompatibility error. You can enable this cop when Ruby 2.4 support is dropped.
|
21
|
+
# See https://github.com/rubocop/rubocop/issues/10258
|
22
|
+
Layout/BlockAlignment:
|
23
|
+
Enabled: false
|
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
rubocop-solidus (0.1.0)
|
5
|
+
rubocop
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
ast (2.4.2)
|
11
|
+
bump (0.10.0)
|
12
|
+
coderay (1.1.3)
|
13
|
+
diff-lcs (1.5.0)
|
14
|
+
method_source (1.0.0)
|
15
|
+
parallel (1.20.1)
|
16
|
+
parser (3.2.2.3)
|
17
|
+
ast (~> 2.4.1)
|
18
|
+
racc
|
19
|
+
pry (0.14.2)
|
20
|
+
coderay (~> 1.1)
|
21
|
+
method_source (~> 1.0)
|
22
|
+
racc (1.5.2)
|
23
|
+
rainbow (3.1.1)
|
24
|
+
rake (13.0.6)
|
25
|
+
regexp_parser (2.8.1)
|
26
|
+
rexml (3.2.5)
|
27
|
+
rspec (3.12.0)
|
28
|
+
rspec-core (~> 3.12.0)
|
29
|
+
rspec-expectations (~> 3.12.0)
|
30
|
+
rspec-mocks (~> 3.12.0)
|
31
|
+
rspec-core (3.12.2)
|
32
|
+
rspec-support (~> 3.12.0)
|
33
|
+
rspec-expectations (3.12.3)
|
34
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
35
|
+
rspec-support (~> 3.12.0)
|
36
|
+
rspec-mocks (3.12.6)
|
37
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
38
|
+
rspec-support (~> 3.12.0)
|
39
|
+
rspec-support (3.12.1)
|
40
|
+
rubocop (1.12.1)
|
41
|
+
parallel (~> 1.10)
|
42
|
+
parser (>= 3.0.0.0)
|
43
|
+
rainbow (>= 2.2.2, < 4.0)
|
44
|
+
regexp_parser (>= 1.8, < 3.0)
|
45
|
+
rexml
|
46
|
+
rubocop-ast (>= 1.2.0, < 2.0)
|
47
|
+
ruby-progressbar (~> 1.7)
|
48
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
49
|
+
rubocop-ast (1.4.1)
|
50
|
+
parser (>= 2.7.1.5)
|
51
|
+
ruby-progressbar (1.13.0)
|
52
|
+
unicode-display_width (2.4.2)
|
53
|
+
|
54
|
+
PLATFORMS
|
55
|
+
-darwin-22
|
56
|
+
arm64-darwin-21
|
57
|
+
arm64-darwin-22
|
58
|
+
x86_64-darwin-21
|
59
|
+
x86_64-linux
|
60
|
+
|
61
|
+
DEPENDENCIES
|
62
|
+
bump
|
63
|
+
pry
|
64
|
+
rake
|
65
|
+
rspec
|
66
|
+
rubocop
|
67
|
+
rubocop-solidus!
|
68
|
+
|
69
|
+
BUNDLED WITH
|
70
|
+
2.3.26
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2023 piyushswain
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
# Rubocop::Solidus
|
2
|
+
|
3
|
+
Automatic Solidus code style checking tool.
|
4
|
+
A RuboCop extension focused on enforcing Solidus best practices and coding conventions.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
gem 'rubocop-solidus', github: 'nebulab/rubocop-solidus', require: false
|
12
|
+
```
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
|
16
|
+
$ bundle install
|
17
|
+
|
18
|
+
Or install it yourself as:
|
19
|
+
|
20
|
+
$ gem install rubocop-solidus
|
21
|
+
|
22
|
+
## Usage
|
23
|
+
|
24
|
+
To Start using this extension in your application add the following lines to your `.rubocop.yml` file
|
25
|
+
|
26
|
+
```yaml
|
27
|
+
require:
|
28
|
+
- rubocop-solidus
|
29
|
+
```
|
30
|
+
|
31
|
+
After this simply use the `rubocop` command to start linting.
|
32
|
+
|
33
|
+
## Creating new cops
|
34
|
+
|
35
|
+
To create a new cop, run the following command:
|
36
|
+
|
37
|
+
```bash
|
38
|
+
$ bundle exec rake new_cop[Solidus/NameOfTheCop]
|
39
|
+
```
|
40
|
+
|
41
|
+
and then follow the instructions on the screen.
|
42
|
+
|
43
|
+
## Release a new version
|
44
|
+
|
45
|
+
To release a new version, run the following command:
|
46
|
+
|
47
|
+
```bash
|
48
|
+
$ bundle exec rake cut_release:[major|minor|patch]
|
49
|
+
```
|
50
|
+
|
51
|
+
and then follow the instructions on the screen.
|
52
|
+
|
53
|
+
The type of the release is determined by:
|
54
|
+
- `major` if there are breaking changes
|
55
|
+
- `minor` if there are new cops or new features
|
56
|
+
- `patch` if there are only bug fixes
|
57
|
+
|
58
|
+
To deploy the new version to RubyGems, run the following command:
|
59
|
+
|
60
|
+
```bash
|
61
|
+
$ bundle exec rake release
|
62
|
+
```
|
63
|
+
|
64
|
+
## Contributing
|
65
|
+
|
66
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/nebulab/rubocop-solidus.
|
67
|
+
|
68
|
+
## License
|
69
|
+
|
70
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
require 'rubocop/rake_task'
|
5
|
+
require 'rspec/core/rake_task'
|
6
|
+
|
7
|
+
Dir['tasks/**/*.rake'].each { |t| load t }
|
8
|
+
|
9
|
+
task default: %i[spec rubocop]
|
10
|
+
|
11
|
+
RuboCop::RakeTask.new
|
12
|
+
|
13
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
14
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
15
|
+
end
|
16
|
+
|
17
|
+
desc 'Generate a new cop with a template'
|
18
|
+
task :new_cop, [:cop] do |_task, args|
|
19
|
+
require 'rubocop'
|
20
|
+
|
21
|
+
cop_name = args.fetch(:cop) do
|
22
|
+
warn 'usage: bundle exec rake new_cop[Department/Name]'
|
23
|
+
exit!
|
24
|
+
end
|
25
|
+
|
26
|
+
generator = RuboCop::Cop::Generator.new(cop_name)
|
27
|
+
|
28
|
+
generator.write_source
|
29
|
+
generator.write_spec
|
30
|
+
generator.inject_require(root_file_path: 'lib/rubocop/cop/solidus_cops.rb')
|
31
|
+
generator.inject_config(config_file_path: 'config/default.yml')
|
32
|
+
|
33
|
+
puts generator.todo
|
34
|
+
end
|
data/config/default.yml
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
AllCops:
|
2
|
+
# What version of Solidus is the inspected code using? If a value is specified
|
3
|
+
# for TargetSolidusVersion then it is used. Acceptable values are specified
|
4
|
+
# as a float (i.e. 3.1); the patch version of Solidus should not be included.
|
5
|
+
# If TargetSolidusVersion is not set, RuboCop will parse the Gemfile.lock or
|
6
|
+
# gems.locked file to find the version of Solidus that has been bound to the
|
7
|
+
# application. If neither of those files exist, RuboCop will use Solidus 3.0
|
8
|
+
# as the default.
|
9
|
+
TargetSolidusVersion: ~
|
10
|
+
|
11
|
+
Solidus/ClassEvalDecorator:
|
12
|
+
Description: 'Checks if Class.class_eval is being used in the code'
|
13
|
+
Enabled: true
|
14
|
+
VersionAdded: '0.1.0'
|
15
|
+
Reference: 'https://github.com/nebulab/rubocop-solidus/issues/21'
|
16
|
+
|
17
|
+
Solidus/ReimbursementHookDeprecated:
|
18
|
+
Description: 'Checks if reimbursement_success_hooks and reimbursement_failed_hooks is being used'
|
19
|
+
Enabled: true
|
20
|
+
VersionAdded: '0.1.0'
|
21
|
+
Reference: 'https://github.com/nebulab/rubocop-solidus/issues/27'
|
22
|
+
|
23
|
+
Solidus/SpreeCalculatorFreeShippingDeprecated:
|
24
|
+
Description: 'Checks if Spree::Calculator::FreeShipping is being used and add deprecation message'
|
25
|
+
Enabled: true
|
26
|
+
VersionAdded: '0.1.0'
|
27
|
+
Reference: 'https://github.com/nebulab/rubocop-solidus/issues/29'
|
28
|
+
|
29
|
+
Solidus/SpreeCalculatorPercentPerItemDeprecated:
|
30
|
+
Description: 'Checks if Spree::Calculator::PercentPerItem is being used and add deprecation message'
|
31
|
+
Enabled: true
|
32
|
+
VersionAdded: '0.1.0'
|
33
|
+
Reference: 'https://github.com/nebulab/rubocop-solidus/issues/29'
|
34
|
+
|
35
|
+
Solidus/SpreeCalculatorPriceSackDeprecated:
|
36
|
+
Description: 'Checks if Spree::Calculator::PriceSack is being used and add deprecation message'
|
37
|
+
Enabled: true
|
38
|
+
VersionAdded: '0.1.0'
|
39
|
+
Reference: 'https://github.com/nebulab/rubocop-solidus/issues/29'
|
40
|
+
|
41
|
+
Solidus/SpreeDefaultCreditCardDeprecated:
|
42
|
+
Description: 'Checks if user.default_credit_card is used and suggest using user.wallet.default_wallet_payment_source'
|
43
|
+
Enabled: true
|
44
|
+
VersionAdded: '0.1.0'
|
45
|
+
Reference: 'https://github.com/nebulab/rubocop-solidus/issues/33'
|
46
|
+
|
47
|
+
Solidus/SpreeGatewayBogusDeprecated:
|
48
|
+
Description: 'Checks if SpreeGatewayBogus is being used and replaces it with Spree::PaymentMethod::BogusCreditCard'
|
49
|
+
Enabled: true
|
50
|
+
VersionAdded: '0.1.0'
|
51
|
+
Reference: 'https://github.com/nebulab/rubocop-solidus/issues/26'
|
52
|
+
|
53
|
+
Solidus/SpreeIconDeprecated:
|
54
|
+
Description: 'Checks if icon helper is being used and suggest `solidus_icon`'
|
55
|
+
Enabled: true
|
56
|
+
VersionAdded: '0.1.0'
|
57
|
+
Reference: 'https://github.com/nebulab/rubocop-solidus/issues/32'
|
58
|
+
|
59
|
+
Solidus/SpreeRefundCallPerform:
|
60
|
+
Description: 'Checks if Spree::Refund.create is being used and require calling .perform!'
|
61
|
+
Enabled: true
|
62
|
+
VersionAdded: '0.1.0'
|
63
|
+
Reference: 'https://github.com/nebulab/rubocop-solidus/issues/28'
|
64
|
+
|
65
|
+
Solidus/SpreeTDeprecated:
|
66
|
+
Description: 'Checks if Spree.t is being used and replaces it with I18n.t.'
|
67
|
+
Enabled: true
|
68
|
+
VersionAdded: '0.1.0'
|
69
|
+
Reference: 'https://github.com/nebulab/rubocop-solidus/issues/22'
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
# This module provides a way to specify a minimum Solidus version for a cop.
|
6
|
+
# It also provides a way to check if the current Solidus version is affected.
|
7
|
+
# The minimum Solidus version can be specified in the cop itself in this way:
|
8
|
+
# include TargetSolidusVersion
|
9
|
+
# minimum_solidus_version 2.11
|
10
|
+
module TargetSolidusVersion
|
11
|
+
DEFAULT_SOLIDUS_VERSION = 3.0
|
12
|
+
|
13
|
+
def self.included(target)
|
14
|
+
target.extend(ClassMethods)
|
15
|
+
end
|
16
|
+
|
17
|
+
# These class methods are automatically added to the cop when the module
|
18
|
+
# is included. They are used to specify the minimum Solidus version for the cop.
|
19
|
+
module ClassMethods
|
20
|
+
def minimum_solidus_version(version)
|
21
|
+
@minimum_solidus_version = version
|
22
|
+
end
|
23
|
+
|
24
|
+
def targeted_solidus_version?(version)
|
25
|
+
@minimum_solidus_version <= version
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# This method overrides the one in RuboCop::Cop::Base.
|
30
|
+
# Since this method is called for every offense, we can use it to check
|
31
|
+
# if the Solidus version is affected and skip the offense if it's not.
|
32
|
+
def add_offense(*args, **kwargs, &block)
|
33
|
+
return unless affected_solidus_version?
|
34
|
+
|
35
|
+
if Gem::Version.new(RUBY_VERSION) > Gem::Version.new('3')
|
36
|
+
super(*args, **kwargs, &block)
|
37
|
+
else
|
38
|
+
super(*args, &block)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def affected_solidus_version?
|
45
|
+
self.class.targeted_solidus_version?(target_solidus_version)
|
46
|
+
end
|
47
|
+
|
48
|
+
def target_solidus_version
|
49
|
+
@target_solidus_version ||=
|
50
|
+
config.for_all_cops['TargetSolidusVersion']&.to_f || solidus_version_from_lock_file || DEFAULT_SOLIDUS_VERSION
|
51
|
+
end
|
52
|
+
|
53
|
+
def solidus_version_from_lock_file
|
54
|
+
@solidus_version_from_lock_file ||= read_solidus_version_from_lock_file
|
55
|
+
end
|
56
|
+
|
57
|
+
def read_solidus_version_from_lock_file
|
58
|
+
lock_file_path = config.bundler_lock_file_path
|
59
|
+
return nil unless lock_file_path
|
60
|
+
|
61
|
+
File.foreach(lock_file_path) do |line|
|
62
|
+
# If Solidus (or one of its frameworks) is in Gemfile.lock, there should be a line like:
|
63
|
+
# solidus_core (X.X.X)
|
64
|
+
result = line.match(/^\s+solidus_core\s+\((\d+\.\d+)/)
|
65
|
+
return result.captures.first.to_f if result
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Solidus
|
6
|
+
# TODO: Write cop description and example of bad / good code. For every
|
7
|
+
# `SupportedStyle` and unique configuration, there needs to be examples.
|
8
|
+
# Examples must have valid Ruby syntax. Do not use upticks.
|
9
|
+
#
|
10
|
+
#
|
11
|
+
# @example EnforcedStyle: SpreeClass
|
12
|
+
# # Description of the `SpreeClass` style.
|
13
|
+
#
|
14
|
+
# # bad
|
15
|
+
# SpreeClass.class_eval do
|
16
|
+
# .
|
17
|
+
# .
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
#
|
21
|
+
# # good
|
22
|
+
# module SpreeClassDecorator
|
23
|
+
# .
|
24
|
+
# .
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
class ClassEvalDecorator < Base
|
28
|
+
MSG = 'Do not use `class_eval` flag. Use a decorator module instead. Check this link for an example https://guides.solidus.io/cookbook/redefining-checkout-steps'
|
29
|
+
|
30
|
+
# TODO: Don't call `on_send` unless the method name is in this list
|
31
|
+
# If you don't need `on_send` in the cop you created, remove it.
|
32
|
+
RESTRICT_ON_SEND = %i[class_eval].freeze
|
33
|
+
|
34
|
+
# @!method on_class_eval?(node)
|
35
|
+
def_node_matcher :on_class_eval?, <<~PATTERN
|
36
|
+
(send ($...) :class_eval)
|
37
|
+
PATTERN
|
38
|
+
|
39
|
+
def on_send(node)
|
40
|
+
return unless on_class_eval?(node)
|
41
|
+
|
42
|
+
add_offense(node)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Solidus
|
6
|
+
# This cop finds reimbursement_success_hooks and reimbursement_failed_hooks calls and
|
7
|
+
# asks to remove them and subscribe to reimbursement_reimbursed event instead.
|
8
|
+
class ReimbursementHookDeprecated < Base
|
9
|
+
include TargetSolidusVersion
|
10
|
+
minimum_solidus_version 2.11
|
11
|
+
|
12
|
+
MSG = 'Please remove reimbursement_success_hooks and reimbursement_failed_hooks. ' \
|
13
|
+
'Subscribe to reimbursement_reimbursed event instead.'
|
14
|
+
|
15
|
+
def_node_matcher :success_hook?, <<~PATTERN
|
16
|
+
(send (send nil? :reimbursement_success_hooks) ...)
|
17
|
+
PATTERN
|
18
|
+
|
19
|
+
def_node_matcher :fail_hook?, <<~PATTERN
|
20
|
+
(send (send nil? :reimbursement_failed_hooks) ...)
|
21
|
+
PATTERN
|
22
|
+
|
23
|
+
def on_send(node)
|
24
|
+
return unless success_hook?(node) || fail_hook?(node)
|
25
|
+
|
26
|
+
add_offense(node)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Solidus
|
6
|
+
# This cop finds Spree::Calculator::FreeShipping calls.
|
7
|
+
# This cop is needed as they have been deprecated in future version.
|
8
|
+
#
|
9
|
+
class SpreeCalculatorFreeShippingDeprecated < Base
|
10
|
+
MSG = 'Spree::Calculator::FreeShipping is deprecated.'
|
11
|
+
|
12
|
+
def_node_matcher :free_shipping?, <<~PATTERN
|
13
|
+
(send (... (... :Calculator) :FreeShipping) $_)
|
14
|
+
PATTERN
|
15
|
+
|
16
|
+
def on_send(node)
|
17
|
+
return unless free_shipping?(node)
|
18
|
+
|
19
|
+
add_offense(node)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Solidus
|
6
|
+
# This cop finds Spree::Calculator::PercentPerItem calls.
|
7
|
+
# This cop is needed as they have been deprecated in future version.
|
8
|
+
#
|
9
|
+
class SpreeCalculatorPercentPerItemDeprecated < Base
|
10
|
+
extend AutoCorrector
|
11
|
+
|
12
|
+
MSG = 'Spree::Calculator::PercentPerItem is deprecated.'
|
13
|
+
|
14
|
+
def_node_matcher :percent_per_item?, <<~PATTERN
|
15
|
+
(send (... (... :Calculator) :PercentPerItem) $_)
|
16
|
+
PATTERN
|
17
|
+
|
18
|
+
def on_send(node)
|
19
|
+
percent_per_item?(node) do |method_used|
|
20
|
+
add_offense(node, message: MSG) do |corrector|
|
21
|
+
corrector.replace(node, "Spree::Calculator::PercentOnLineItem.#{method_used}")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Solidus
|
6
|
+
# This cop finds Spree::Calculator::PriceSack calls.
|
7
|
+
# This cop is needed as they have been deprecated in future version.
|
8
|
+
#
|
9
|
+
class SpreeCalculatorPriceSackDeprecated < Base
|
10
|
+
MSG = 'Spree::Calculator::PriceSack is deprecated.'
|
11
|
+
|
12
|
+
def_node_matcher :price_sack?, <<~PATTERN
|
13
|
+
(send (... (... :Calculator) :PriceSack) $_)
|
14
|
+
PATTERN
|
15
|
+
|
16
|
+
def on_send(node)
|
17
|
+
return unless price_sack?(node)
|
18
|
+
|
19
|
+
add_offense(node)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Solidus
|
6
|
+
# This cop finds user.default_credit_card suggest using user.wallet.default_wallet_payment_source
|
7
|
+
#
|
8
|
+
# @example EnforcedStyle:
|
9
|
+
# # bad
|
10
|
+
# user.default_credit_card
|
11
|
+
#
|
12
|
+
# # good
|
13
|
+
# user.wallet.default_wallet_payment_source
|
14
|
+
#
|
15
|
+
#
|
16
|
+
class SpreeDefaultCreditCardDeprecated < Base
|
17
|
+
extend AutoCorrector
|
18
|
+
include TargetSolidusVersion
|
19
|
+
minimum_solidus_version 2.2
|
20
|
+
|
21
|
+
MSG = 'user.default_credit_card is deprecated. Please use user.wallet.default_wallet_payment_source instead.'
|
22
|
+
|
23
|
+
# @!method bad_method?(node)
|
24
|
+
def_node_matcher :default_credit_card?, <<~PATTERN
|
25
|
+
(send ... :default_credit_card)
|
26
|
+
PATTERN
|
27
|
+
|
28
|
+
def on_send(node)
|
29
|
+
return unless default_credit_card?(node)
|
30
|
+
|
31
|
+
add_offense(node) do |corrector|
|
32
|
+
corrector.replace(node, node.source.gsub('default_credit_card', 'wallet.default_wallet_payment_source'))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Solidus
|
6
|
+
# This cop finds Spree::Gateway::Bogus calls and replaces them with the Spree::PaymentMethod::BogusCreditCard call
|
7
|
+
# This cop is needed as the Spree::Gateway::Bogus has been deprecated in future version.
|
8
|
+
#
|
9
|
+
# @example EnforcedStyle:
|
10
|
+
# # bad
|
11
|
+
# Spree::Gateway::Bogus.new
|
12
|
+
#
|
13
|
+
# # good
|
14
|
+
# Spree::PaymentMethod::BogusCreditCard.new
|
15
|
+
#
|
16
|
+
# # bad
|
17
|
+
# Spree::Gateway::Bogus.create
|
18
|
+
#
|
19
|
+
# # good
|
20
|
+
# Spree::PaymentMethod::BogusCreditCard.create
|
21
|
+
#
|
22
|
+
# # bad
|
23
|
+
# Spree::Gateway::Bogus.create!
|
24
|
+
#
|
25
|
+
# # good
|
26
|
+
# Spree::PaymentMethod::BogusCreditCard.create!
|
27
|
+
#
|
28
|
+
#
|
29
|
+
class SpreeGatewayBogusDeprecated < Base
|
30
|
+
extend AutoCorrector
|
31
|
+
include TargetSolidusVersion
|
32
|
+
minimum_solidus_version 2.10
|
33
|
+
|
34
|
+
MSG = 'Spree::Gateway::Bogus is deprecated. Please use Spree::PaymentMethod::BogusCreditCard instead.'
|
35
|
+
|
36
|
+
# @!method bad_method?(node)
|
37
|
+
def_node_matcher :bad_class?, <<~PATTERN
|
38
|
+
(send (... (... :Gateway) :Bogus) $_)
|
39
|
+
PATTERN
|
40
|
+
|
41
|
+
def on_send(node)
|
42
|
+
bad_class?(node) do |method_used|
|
43
|
+
add_offense(node, message: MSG) do |corrector|
|
44
|
+
corrector.replace(node, "Spree::PaymentMethod::BogusCreditCard.#{method_used}")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Solidus
|
6
|
+
# This cop finds icon helper calls and suggest using solidus_icon
|
7
|
+
#
|
8
|
+
# @example EnforcedStyle:
|
9
|
+
# # bad
|
10
|
+
# helper.icon('example')
|
11
|
+
#
|
12
|
+
# # good
|
13
|
+
# helper.solidus_icon('example')
|
14
|
+
#
|
15
|
+
#
|
16
|
+
class SpreeIconDeprecated < Base
|
17
|
+
extend AutoCorrector
|
18
|
+
include TargetSolidusVersion
|
19
|
+
minimum_solidus_version 2.3
|
20
|
+
|
21
|
+
MSG = 'In Solidus 2.3, `icon` helper has been deprecated in favor of `solidus_icon`'
|
22
|
+
|
23
|
+
RESTRICT_ON_SEND = %i[icon].freeze
|
24
|
+
|
25
|
+
def_node_matcher :icon?, <<~PATTERN
|
26
|
+
(send (send nil? ...) :icon ...)
|
27
|
+
PATTERN
|
28
|
+
|
29
|
+
def on_send(node)
|
30
|
+
return unless icon?(node)
|
31
|
+
|
32
|
+
add_offense(node) do |corrector|
|
33
|
+
corrector.replace(node, node.source.gsub('icon', 'solidus_icon'))
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Solidus
|
6
|
+
# This cop finds Spree::Refund.create(your: attributes) calls and
|
7
|
+
# replaces them with the Spree::Refund.create(your: attributes, perform_after_create: false).perform! call
|
8
|
+
#
|
9
|
+
class SpreeRefundCallPerform < Base
|
10
|
+
include TargetSolidusVersion
|
11
|
+
minimum_solidus_version 2.11
|
12
|
+
|
13
|
+
MSG = 'From Solidus v3.0 onwards, #perform! will need to be explicitly called when creating new refunds. ' \
|
14
|
+
'Please, change your code from `Spree::Refund.create(your: attributes)` ' \
|
15
|
+
'to `Spree::Refund.create(your: attributes, perform_after_create: false).perform!`'
|
16
|
+
|
17
|
+
RESTRICT_ON_SEND = %i[create].freeze
|
18
|
+
|
19
|
+
# @!method bad_method?(node)
|
20
|
+
def_node_matcher :create_refund?, <<~PATTERN
|
21
|
+
(send (const (const nil? :Spree) :Refund) :create ...)
|
22
|
+
PATTERN
|
23
|
+
|
24
|
+
def on_send(node)
|
25
|
+
return unless create_refund?(node)
|
26
|
+
|
27
|
+
add_offense(node)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Solidus
|
6
|
+
# This cop finds Spree.t method calls and replaces them with the I18n,t method call
|
7
|
+
# This cop is needed as the Spree.t version has been deprecated in future version.
|
8
|
+
#
|
9
|
+
#
|
10
|
+
# @example EnforcedStyle: bar (default)
|
11
|
+
# # bad
|
12
|
+
# Spree.t(:bar)
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# I18n.t(:bar, scope: :spree)
|
16
|
+
#
|
17
|
+
# # bad
|
18
|
+
# Spree.t(:bar, scope: [:city])
|
19
|
+
#
|
20
|
+
# # good
|
21
|
+
# I18n.t(:bar, scope: [:spree, :city])
|
22
|
+
#
|
23
|
+
# # bad
|
24
|
+
# Spree.t(:bar, scope: [:city], email: email)
|
25
|
+
#
|
26
|
+
# # good
|
27
|
+
# I18n.t(:bar, scope: [:spree, :city], email: email)
|
28
|
+
#
|
29
|
+
# # bad
|
30
|
+
# Spree.t('bar', scope: 'admin.city')
|
31
|
+
#
|
32
|
+
# # good
|
33
|
+
# I18n.t('bar', scope: 'spree.admin.city')
|
34
|
+
#
|
35
|
+
#
|
36
|
+
class SpreeTDeprecated < Base
|
37
|
+
extend AutoCorrector
|
38
|
+
MSG = 'Use I18n.t instead of Spree.t which has been deprecated in future versions.'
|
39
|
+
|
40
|
+
RESTRICT_ON_SEND = %i[t].freeze
|
41
|
+
|
42
|
+
# @!method spree_t?(node)
|
43
|
+
def_node_matcher :spree_t?, <<~PATTERN
|
44
|
+
(send ($...) :t ...)
|
45
|
+
PATTERN
|
46
|
+
|
47
|
+
def on_send(node)
|
48
|
+
return unless spree_t?(node)
|
49
|
+
|
50
|
+
return unless spree_t?(node).include?(:Spree)
|
51
|
+
|
52
|
+
add_offense(node) do |corrector|
|
53
|
+
corrector.replace(node, corrected_statement(node))
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# rubocop:disable Metrics/MethodLength
|
58
|
+
def corrected_statement(node)
|
59
|
+
arguments = node.arguments
|
60
|
+
|
61
|
+
new_statement = 'I18n.t('
|
62
|
+
new_statement += arguments.first.source
|
63
|
+
new_statement += ', scope: :spree' if scope_missing?(arguments)
|
64
|
+
|
65
|
+
node.arguments.drop(1).each do |argument|
|
66
|
+
if argument.source.include? 'scope:'
|
67
|
+
new_argument = add_spree_scope(argument)
|
68
|
+
new_statement += ", #{new_argument}"
|
69
|
+
else
|
70
|
+
new_statement += ", #{argument.source}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
new_statement += ')'
|
74
|
+
new_statement
|
75
|
+
end
|
76
|
+
# rubocop:enable Metrics/MethodLength
|
77
|
+
|
78
|
+
def scope_missing?(arguments)
|
79
|
+
arguments.each do |argument|
|
80
|
+
return false if argument.source.include? 'scope:'
|
81
|
+
end
|
82
|
+
true
|
83
|
+
end
|
84
|
+
|
85
|
+
# rubocop:disable Metrics/MethodLength
|
86
|
+
def add_spree_scope(argument)
|
87
|
+
modified_argument = ''
|
88
|
+
|
89
|
+
argument.each_pair do |key, value|
|
90
|
+
if key.source == 'scope'
|
91
|
+
modified_argument = if value.type == :array
|
92
|
+
"#{key.source}: #{value.source.gsub('[', '[:spree, ')}"
|
93
|
+
else
|
94
|
+
"#{key.source}: 'spree.#{value.source.gsub("'", '')}'"
|
95
|
+
end
|
96
|
+
else
|
97
|
+
modified_argument += ", #{key.source}: #{value.source}"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
modified_argument
|
102
|
+
end
|
103
|
+
# rubocop:enable Metrics/MethodLength
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'mixin/target_solidus_version'
|
4
|
+
|
5
|
+
require_relative 'solidus/class_eval_decorator'
|
6
|
+
require_relative 'solidus/reimbursement_hook_deprecated'
|
7
|
+
require_relative 'solidus/spree_calculator_free_shipping_deprecated'
|
8
|
+
require_relative 'solidus/spree_calculator_percent_per_item_deprecated'
|
9
|
+
require_relative 'solidus/spree_calculator_price_sack_deprecated'
|
10
|
+
require_relative 'solidus/spree_default_credit_card_deprecated'
|
11
|
+
require_relative 'solidus/spree_gateway_bogus_deprecated'
|
12
|
+
require_relative 'solidus/spree_icon_deprecated'
|
13
|
+
require_relative 'solidus/spree_refund_call_perform'
|
14
|
+
require_relative 'solidus/spree_t_deprecated'
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# The original code is from https://github.com/rubocop/rubocop-rspec/blob/master/lib/rubocop/rspec/inject.rb
|
4
|
+
# See https://github.com/rubocop/rubocop-rspec/blob/master/MIT-LICENSE.md
|
5
|
+
module RuboCop
|
6
|
+
module Solidus
|
7
|
+
# Because RuboCop doesn't yet support plugins, we have to monkey patch in a
|
8
|
+
# bit of our configuration.
|
9
|
+
module Inject
|
10
|
+
def self.defaults!
|
11
|
+
path = CONFIG_DEFAULT.to_s
|
12
|
+
hash = ConfigLoader.send(:load_yaml_configuration, path)
|
13
|
+
config = Config.new(hash, path).tap(&:make_excludes_absolute)
|
14
|
+
puts "configuration from #{path}" if ConfigLoader.debug?
|
15
|
+
config = ConfigLoader.merge_with_default(config, path)
|
16
|
+
ConfigLoader.instance_variable_set(:@default_configuration, config)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'solidus/version'
|
4
|
+
|
5
|
+
module RuboCop
|
6
|
+
# RuboCop Solidus project namespace
|
7
|
+
module Solidus
|
8
|
+
class Error < StandardError; end
|
9
|
+
# Your code goes here...
|
10
|
+
PROJECT_ROOT = Pathname.new(__dir__).parent.parent.expand_path.freeze
|
11
|
+
CONFIG_DEFAULT = PROJECT_ROOT.join('config', 'default.yml').freeze
|
12
|
+
CONFIG = YAML.safe_load(CONFIG_DEFAULT.read).freeze
|
13
|
+
|
14
|
+
private_constant(:CONFIG_DEFAULT, :PROJECT_ROOT)
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rubocop'
|
4
|
+
|
5
|
+
require_relative 'rubocop/solidus'
|
6
|
+
require_relative 'rubocop/solidus/version'
|
7
|
+
require_relative 'rubocop/solidus/inject'
|
8
|
+
|
9
|
+
RuboCop::Solidus::Inject.defaults!
|
10
|
+
|
11
|
+
require_relative 'rubocop/cop/solidus_cops'
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
autoload :Changelog, "#{__dir__}/changelog"
|
4
|
+
|
5
|
+
namespace :changelog do
|
6
|
+
%i[new fix change].each do |type|
|
7
|
+
desc "Create a Changelog entry (#{type})"
|
8
|
+
task type, [:id] do |_task, args|
|
9
|
+
ref_type = :pull if args[:id]
|
10
|
+
path = Changelog::Entry.new(type: type, ref_id: args[:id], ref_type: ref_type).write
|
11
|
+
cmd = "git add #{path}"
|
12
|
+
system cmd
|
13
|
+
puts "Entry '#{path}' created and added to git index"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
desc 'Merge entries and delete them'
|
18
|
+
task :merge do
|
19
|
+
raise 'No entries!' unless Changelog.pending?
|
20
|
+
|
21
|
+
Changelog.new.merge!.and_delete!
|
22
|
+
cmd = "git commit -a -m 'Update Changelog'"
|
23
|
+
puts cmd
|
24
|
+
system cmd
|
25
|
+
end
|
26
|
+
|
27
|
+
task :check_clean do
|
28
|
+
next unless Changelog.pending?
|
29
|
+
|
30
|
+
puts '*** Pending changelog entries!'
|
31
|
+
puts 'Do `bundle exec rake changelog:merge`'
|
32
|
+
exit(1)
|
33
|
+
end
|
34
|
+
end
|
data/tasks/changelog.rb
ADDED
@@ -0,0 +1,180 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Changelog utility
|
4
|
+
class Changelog
|
5
|
+
ENTRIES_PATH = 'changelog/'
|
6
|
+
FIRST_HEADER = /#{Regexp.escape("## master (unreleased)\n")}/m.freeze
|
7
|
+
ENTRIES_PATH_TEMPLATE = "#{ENTRIES_PATH}%<type>s_%<name>s.md"
|
8
|
+
TYPE_REGEXP = /#{Regexp.escape(ENTRIES_PATH)}([a-z]+)_/.freeze
|
9
|
+
TYPE_TO_HEADER = { new: 'New features', fix: 'Bug fixes', change: 'Changes' }.freeze
|
10
|
+
HEADER = /### (.*)/.freeze
|
11
|
+
PATH = 'CHANGELOG.md'
|
12
|
+
REF_URL = 'https://github.com/nebulab/rubocop-solidus'
|
13
|
+
MAX_LENGTH = 40
|
14
|
+
CONTRIBUTOR = '[@%<user>s]: https://github.com/%<user>s'
|
15
|
+
SIGNATURE = Regexp.new(format(Regexp.escape('[@%<user>s][]'), user: '([\w-]+)'))
|
16
|
+
EOF = "\n"
|
17
|
+
|
18
|
+
# New entry
|
19
|
+
Entry = Struct.new(:type, :body, :ref_type, :ref_id, :user, keyword_init: true) do
|
20
|
+
def initialize(type:, body: last_commit_title, ref_type: nil, ref_id: nil, user: github_user)
|
21
|
+
id, body = extract_id(body)
|
22
|
+
ref_id ||= id || 'x'
|
23
|
+
ref_type ||= id ? :issues : :pull
|
24
|
+
super
|
25
|
+
end
|
26
|
+
|
27
|
+
def write
|
28
|
+
File.write(path, content)
|
29
|
+
path
|
30
|
+
end
|
31
|
+
|
32
|
+
def path
|
33
|
+
format(ENTRIES_PATH_TEMPLATE, type: type, name: str_to_filename(body))
|
34
|
+
end
|
35
|
+
|
36
|
+
def content
|
37
|
+
period = '.' unless body.end_with? '.'
|
38
|
+
"* #{ref}: #{body}#{period} ([@#{user}][])\n"
|
39
|
+
end
|
40
|
+
|
41
|
+
def ref
|
42
|
+
"[##{ref_id}](#{REF_URL}/#{ref_type}/#{ref_id})"
|
43
|
+
end
|
44
|
+
|
45
|
+
def last_commit_title
|
46
|
+
`git log -1 --pretty=%B`.lines.first.chomp
|
47
|
+
end
|
48
|
+
|
49
|
+
def extract_id(body)
|
50
|
+
/^\[Fix(?:es)? #(\d+)\] (.*)/.match(body)&.captures || [nil, body]
|
51
|
+
end
|
52
|
+
|
53
|
+
def str_to_filename(str)
|
54
|
+
str
|
55
|
+
.split
|
56
|
+
.reject(&:empty?)
|
57
|
+
.map { |s| prettify(s) }
|
58
|
+
.inject do |result, word|
|
59
|
+
s = "#{result}_#{word}"
|
60
|
+
return result if s.length > MAX_LENGTH
|
61
|
+
|
62
|
+
s
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def github_user
|
67
|
+
user = `git config --global credential.username`.chomp
|
68
|
+
warn 'Set your username with `git config --global credential.username "myusernamehere"`' if user.empty?
|
69
|
+
|
70
|
+
user
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def prettify(str)
|
76
|
+
str.gsub!(/\W/, '_')
|
77
|
+
|
78
|
+
# Separate word boundaries by `_`.
|
79
|
+
str.gsub!(/([A-Z]+)(?=[A-Z][a-z])|([a-z\d])(?=[A-Z])/) do
|
80
|
+
(Regexp.last_match(1) || Regexp.last_match(2)) << '_'
|
81
|
+
end
|
82
|
+
|
83
|
+
str.gsub!(/\A_+|_+\z/, '')
|
84
|
+
str.downcase!
|
85
|
+
str
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.pending?
|
90
|
+
entry_paths.any?
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.entry_paths
|
94
|
+
Dir["#{ENTRIES_PATH}*"]
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.read_entries
|
98
|
+
entry_paths.to_h { |path| [path, File.read(path)] }
|
99
|
+
end
|
100
|
+
|
101
|
+
attr_reader :header, :rest
|
102
|
+
|
103
|
+
def initialize(content: File.read(PATH), entries: Changelog.read_entries)
|
104
|
+
require 'strscan'
|
105
|
+
|
106
|
+
parse(content)
|
107
|
+
@entries = entries
|
108
|
+
end
|
109
|
+
|
110
|
+
def and_delete!
|
111
|
+
@entries.each_key { |path| File.delete(path) }
|
112
|
+
end
|
113
|
+
|
114
|
+
def merge!
|
115
|
+
File.write(PATH, merge_content)
|
116
|
+
self
|
117
|
+
end
|
118
|
+
|
119
|
+
def unreleased_content
|
120
|
+
entry_map = parse_entries(@entries)
|
121
|
+
merged_map = merge_entries(entry_map)
|
122
|
+
merged_map.flat_map { |header, things| ["### #{header}\n", *things, ''] }.join("\n")
|
123
|
+
end
|
124
|
+
|
125
|
+
def merge_content
|
126
|
+
merged_content = [@header, unreleased_content, @rest.chomp, *new_contributor_lines].join("\n")
|
127
|
+
|
128
|
+
merged_content << EOF
|
129
|
+
end
|
130
|
+
|
131
|
+
def new_contributor_lines
|
132
|
+
contributors
|
133
|
+
.map { |user| format(CONTRIBUTOR, user: user) }
|
134
|
+
.reject { |line| @rest.include?(line) }
|
135
|
+
end
|
136
|
+
|
137
|
+
def contributors
|
138
|
+
contributors = @entries.values.flat_map do |entry|
|
139
|
+
entry.match(/\. \((?<contributors>.+)\)\n/)[:contributors].split(',')
|
140
|
+
end
|
141
|
+
|
142
|
+
contributors.join.scan(SIGNATURE).flatten
|
143
|
+
end
|
144
|
+
|
145
|
+
private
|
146
|
+
|
147
|
+
def merge_entries(entry_map)
|
148
|
+
all = @unreleased.merge(entry_map) { |_k, v1, v2| v1.concat(v2) }
|
149
|
+
canonical = TYPE_TO_HEADER.values.to_h { |v| [v, nil] }
|
150
|
+
canonical.merge(all).compact
|
151
|
+
end
|
152
|
+
|
153
|
+
def parse(content)
|
154
|
+
ss = StringScanner.new(content)
|
155
|
+
@header = ss.scan_until(FIRST_HEADER)
|
156
|
+
@unreleased = parse_release(ss.scan_until(/\n(?=## )/m))
|
157
|
+
@rest = ss.rest
|
158
|
+
end
|
159
|
+
|
160
|
+
# @return [Hash<type, Array<String>]]
|
161
|
+
def parse_release(unreleased)
|
162
|
+
unreleased
|
163
|
+
.lines
|
164
|
+
.map(&:chomp)
|
165
|
+
.reject(&:empty?)
|
166
|
+
.slice_before(HEADER)
|
167
|
+
.to_h do |header, *entries|
|
168
|
+
[HEADER.match(header)[1], entries]
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def parse_entries(path_content_map)
|
173
|
+
changes = Hash.new { |h, k| h[k] = [] }
|
174
|
+
path_content_map.each do |path, content|
|
175
|
+
header = TYPE_TO_HEADER.fetch(TYPE_REGEXP.match(path)[1].to_sym)
|
176
|
+
changes[header].concat(content.lines.map(&:chomp))
|
177
|
+
end
|
178
|
+
changes
|
179
|
+
end
|
180
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bump'
|
4
|
+
|
5
|
+
namespace :cut_release do
|
6
|
+
%w[major minor patch pre].each do |release_type|
|
7
|
+
desc "Cut a new #{release_type} release and create release notes."
|
8
|
+
task release_type => 'changelog:check_clean' do
|
9
|
+
run(release_type)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def add_header_to_changelog(version)
|
14
|
+
changelog = File.read('CHANGELOG.md')
|
15
|
+
head, tail = changelog.split("## master (unreleased)\n\n", 2)
|
16
|
+
|
17
|
+
File.open('CHANGELOG.md', 'w') do |f|
|
18
|
+
f << head
|
19
|
+
f << "## master (unreleased)\n\n"
|
20
|
+
f << "## #{version} (#{Time.now.strftime('%F')})\n\n"
|
21
|
+
f << tail
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def create_release_notes(version)
|
26
|
+
release_notes = new_version_changes.strip
|
27
|
+
contributor_links = user_links(release_notes)
|
28
|
+
|
29
|
+
File.open("relnotes/v#{version}.md", 'w') do |file|
|
30
|
+
file << release_notes
|
31
|
+
file << "\n\n"
|
32
|
+
file << contributor_links
|
33
|
+
file << "\n"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def version_sans_patch(version)
|
38
|
+
version.split('.').take(2).join('.')
|
39
|
+
end
|
40
|
+
|
41
|
+
# Replace `<<next>>` (and variations) with version being cut.
|
42
|
+
def update_cop_versions(_old_version, new_version)
|
43
|
+
update_file('config/default.yml') do |default|
|
44
|
+
default.gsub(/['"]?<<\s*next\s*>>['"]?/i, "'#{version_sans_patch(new_version)}'")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def new_version_changes
|
49
|
+
changelog = File.read('CHANGELOG.md')
|
50
|
+
_, _, new_changes, _older_changes = changelog.split(/^## .*$/, 4)
|
51
|
+
new_changes
|
52
|
+
end
|
53
|
+
|
54
|
+
def update_file(path)
|
55
|
+
content = File.read(path)
|
56
|
+
File.write(path, yield(content))
|
57
|
+
end
|
58
|
+
|
59
|
+
def user_links(text)
|
60
|
+
names = text.scan(/\[@(\S+)\]\[\]/).map(&:first).uniq
|
61
|
+
names.map { |name| "[@#{name}]: https://github.com/#{name}" }.join("\n")
|
62
|
+
end
|
63
|
+
|
64
|
+
def run(release_type)
|
65
|
+
old_version = Bump::Bump.current
|
66
|
+
Bump::Bump.run(release_type, commit: false, bundle: false, tag: false)
|
67
|
+
new_version = Bump::Bump.current
|
68
|
+
|
69
|
+
update_cop_versions(old_version, new_version)
|
70
|
+
add_header_to_changelog(new_version)
|
71
|
+
create_release_notes(new_version)
|
72
|
+
|
73
|
+
puts "Changed version from #{old_version} to #{new_version}."
|
74
|
+
end
|
75
|
+
end
|
metadata
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rubocop-solidus
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- piyushswain
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-07-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rubocop
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
description: |
|
28
|
+
Automatic Solidus code style checking tool.
|
29
|
+
A RuboCop extension focused on enforcing Solidus best practices and coding conventions.
|
30
|
+
email:
|
31
|
+
- danielepalombo@gmail.com
|
32
|
+
executables: []
|
33
|
+
extensions: []
|
34
|
+
extra_rdoc_files: []
|
35
|
+
files:
|
36
|
+
- ".rspec"
|
37
|
+
- ".rubocop.yml"
|
38
|
+
- CHANGELOG.md
|
39
|
+
- Gemfile
|
40
|
+
- Gemfile.lock
|
41
|
+
- LICENSE.txt
|
42
|
+
- README.md
|
43
|
+
- Rakefile
|
44
|
+
- config/default.yml
|
45
|
+
- lib/rubocop-solidus.rb
|
46
|
+
- lib/rubocop/cop/mixin/target_solidus_version.rb
|
47
|
+
- lib/rubocop/cop/solidus/class_eval_decorator.rb
|
48
|
+
- lib/rubocop/cop/solidus/reimbursement_hook_deprecated.rb
|
49
|
+
- lib/rubocop/cop/solidus/spree_calculator_free_shipping_deprecated.rb
|
50
|
+
- lib/rubocop/cop/solidus/spree_calculator_percent_per_item_deprecated.rb
|
51
|
+
- lib/rubocop/cop/solidus/spree_calculator_price_sack_deprecated.rb
|
52
|
+
- lib/rubocop/cop/solidus/spree_default_credit_card_deprecated.rb
|
53
|
+
- lib/rubocop/cop/solidus/spree_gateway_bogus_deprecated.rb
|
54
|
+
- lib/rubocop/cop/solidus/spree_icon_deprecated.rb
|
55
|
+
- lib/rubocop/cop/solidus/spree_refund_call_perform.rb
|
56
|
+
- lib/rubocop/cop/solidus/spree_t_deprecated.rb
|
57
|
+
- lib/rubocop/cop/solidus_cops.rb
|
58
|
+
- lib/rubocop/solidus.rb
|
59
|
+
- lib/rubocop/solidus/inject.rb
|
60
|
+
- lib/rubocop/solidus/version.rb
|
61
|
+
- sig/rubocop/solidus.rbs
|
62
|
+
- tasks/changelog.rake
|
63
|
+
- tasks/changelog.rb
|
64
|
+
- tasks/cut_release.rake
|
65
|
+
homepage: https://www.github.com/nebulab/rubocop-solidus
|
66
|
+
licenses:
|
67
|
+
- MIT
|
68
|
+
metadata:
|
69
|
+
homepage_uri: https://www.github.com/nebulab/rubocop-solidus
|
70
|
+
source_code_uri: https://www.github.com/nebulab/rubocop-solidus
|
71
|
+
changelog_uri: https://www.github.com/nebulab/rubocop-solidus
|
72
|
+
post_install_message:
|
73
|
+
rdoc_options: []
|
74
|
+
require_paths:
|
75
|
+
- lib
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: 2.4.0
|
81
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
requirements: []
|
87
|
+
rubygems_version: 3.3.17
|
88
|
+
signing_key:
|
89
|
+
specification_version: 4
|
90
|
+
summary: Automatic Solidus code style checking tool.
|
91
|
+
test_files: []
|