rubocop_pr 0.1.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.overcommit.yml +93 -0
- data/.rubocop.yml +14 -0
- data/.travis.yml +7 -2
- data/Gemfile +4 -2
- data/README.md +56 -11
- data/Rakefile +5 -3
- data/bin/console +4 -3
- data/exe/rubocop_pr +17 -0
- data/lib/rubocop_pr.rb +23 -2
- data/lib/rubocop_pr/cli.rb +33 -0
- data/lib/rubocop_pr/cli/process_cop.rb +54 -0
- data/lib/rubocop_pr/cop.rb +18 -0
- data/lib/rubocop_pr/environment_checker.rb +29 -0
- data/lib/rubocop_pr/git.rb +52 -0
- data/lib/rubocop_pr/options.rb +141 -0
- data/lib/rubocop_pr/repositories/github.rb +109 -0
- data/lib/rubocop_pr/repositories/github/checks/verify_hub_version.rb +29 -0
- data/lib/rubocop_pr/repository.rb +29 -0
- data/lib/rubocop_pr/rubocop.rb +47 -0
- data/lib/rubocop_pr/version.rb +3 -1
- data/rubocop_pr.gemspec +22 -17
- metadata +96 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8a991a0a8cb80ef2954672a3437172cd1a7bc84d4d3e95fc53cdff0a89c6c252
|
4
|
+
data.tar.gz: c834cbddaec6aeb63dc8d1d60adfa36ac9c07c7a010bdfad112fb3652c5eb2e6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e59a54556c98590dae490a3c468060cb38b4469db01145e8696c7bf9273affc76924ee1e79972127624dc8bb2a0f5d70b2ed8815d571eba40c615cc761d46493
|
7
|
+
data.tar.gz: 5840cc106f27f682e74530c84182f6b75c2cd6ebc1b18a873bb6d8d3bca841842c743aa6c6c398469ca5445dcc00f35a8defb4612a550a73c2af52c22e7eb4cc
|
data/.gitignore
CHANGED
data/.overcommit.yml
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
verify_signatures: false
|
2
|
+
CommitMsg:
|
3
|
+
ALL:
|
4
|
+
CapitalizedSubject:
|
5
|
+
enabled: true
|
6
|
+
description: 'Checking subject capitalization'
|
7
|
+
quiet: true
|
8
|
+
on_warn: fail
|
9
|
+
EmptyMessage:
|
10
|
+
enabled: true
|
11
|
+
description: 'Checking for empty commit message'
|
12
|
+
quiet: true
|
13
|
+
HardTabs:
|
14
|
+
enabled: true
|
15
|
+
description: 'Checking for hard tabs'
|
16
|
+
RussianNovel:
|
17
|
+
enabled: true
|
18
|
+
description: 'Checking length of commit message'
|
19
|
+
quiet: true
|
20
|
+
SingleLineSubject:
|
21
|
+
enabled: true
|
22
|
+
description: 'Checking subject line'
|
23
|
+
SpellCheck:
|
24
|
+
enabled: true
|
25
|
+
description: 'Checking for misspelled words'
|
26
|
+
required_executable: 'hunspell'
|
27
|
+
flags: ['-a']
|
28
|
+
on_fail: warn
|
29
|
+
TextWidth:
|
30
|
+
enabled: true
|
31
|
+
description: 'Checking text width'
|
32
|
+
max_subject_width: 60
|
33
|
+
max_body_width: 72
|
34
|
+
on_warn: fail
|
35
|
+
TrailingPeriod:
|
36
|
+
enabled: true
|
37
|
+
description: 'Checking for trailing periods in subject'
|
38
|
+
on_warn: fail
|
39
|
+
MessageFormat:
|
40
|
+
enabled: false
|
41
|
+
description: 'Message must be ended with task number'
|
42
|
+
expected_pattern_message: '<Commit Message Description> <Issue Id>'
|
43
|
+
sample_message: 'Refactored Onboarding flow FOO-1234'
|
44
|
+
pattern: '\s([A-Z]{1,4}-\d{1,4}|\d{1,6})$'
|
45
|
+
PreCommit:
|
46
|
+
ALL:
|
47
|
+
problem_on_unmodified_line: report
|
48
|
+
requires_files: true
|
49
|
+
required: false
|
50
|
+
quiet: false
|
51
|
+
AuthorEmail:
|
52
|
+
enabled: true
|
53
|
+
description: 'Checking author email'
|
54
|
+
requires_files: false
|
55
|
+
required: true
|
56
|
+
quiet: true
|
57
|
+
pattern: '^[^@]+@.*$'
|
58
|
+
AuthorName:
|
59
|
+
enabled: false
|
60
|
+
description: 'Checking for author name'
|
61
|
+
requires_files: false
|
62
|
+
required: true
|
63
|
+
quiet: true
|
64
|
+
BrokenSymlinks:
|
65
|
+
enabled: true
|
66
|
+
description: 'Checking for broken symlinks'
|
67
|
+
quiet: true
|
68
|
+
CaseConflicts:
|
69
|
+
enabled: true
|
70
|
+
description: 'Checking for case-insensitivity conflicts'
|
71
|
+
quiet: true
|
72
|
+
MergeConflicts:
|
73
|
+
enabled: true
|
74
|
+
description: 'Checking for merge conflicts'
|
75
|
+
quiet: true
|
76
|
+
required_executable: 'grep'
|
77
|
+
flags: ['-IHn', "^<<<<<<<[ \t]"]
|
78
|
+
|
79
|
+
RuboCop:
|
80
|
+
enabled: true
|
81
|
+
required: true
|
82
|
+
quiet: false
|
83
|
+
description: 'Analyzing with RuboCop'
|
84
|
+
command: ['bundle', 'exec', 'rubocop']
|
85
|
+
flags: ['--format=emacs', '--force-exclusion', '--display-cop-names']
|
86
|
+
install_command: 'gem install rubocop'
|
87
|
+
on_warn: fail
|
88
|
+
include:
|
89
|
+
- '**/*.gemspec'
|
90
|
+
- '**/*.rake'
|
91
|
+
- '**/*.rb'
|
92
|
+
- '**/Gemfile'
|
93
|
+
- '**/Rakefile'
|
data/.rubocop.yml
ADDED
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
source 'https://rubygems.org'
|
4
|
+
|
5
|
+
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
4
6
|
|
5
7
|
# Specify your gem's dependencies in rubocop_pr.gemspec
|
6
8
|
gemspec
|
data/README.md
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
# RubocopPr
|
2
2
|
|
3
|
-
|
3
|
+
[![Version ][rubygems_badge]][rubygems]
|
4
|
+
[![Build Status ][travisci_badge]][travisci]
|
5
|
+
[![Codacy Badge ][codacy_badge]][codacy]
|
6
|
+
[![Reviewed by Hound ][hound_badge]][hound]
|
4
7
|
|
5
|
-
|
8
|
+
CLI Issues and PR creator for Rubocop Cops. 1 linter == 1 issue == 1 PR.
|
9
|
+
|
10
|
+
Simplify the inception or version bump of [Rubocop][rubocop_repo] on the project.
|
11
|
+
|
12
|
+
With RubocopPr you can apply [Rubocop][rubocop_repo] clean and in a few minutes,
|
13
|
+
see the [example][rubocop_pr_example].
|
14
|
+
|
15
|
+
## Requirements
|
16
|
+
|
17
|
+
* Ruby 2.1+
|
18
|
+
* Hub 2.12.3 (tested with this version only, but should work with older versions)
|
19
|
+
* Github
|
6
20
|
|
7
21
|
## Installation
|
8
22
|
|
9
23
|
Add this line to your application's Gemfile:
|
10
24
|
|
11
25
|
```ruby
|
12
|
-
gem 'rubocop_pr'
|
26
|
+
gem 'rubocop_pr', require: false
|
13
27
|
```
|
14
28
|
|
15
29
|
And then execute:
|
@@ -22,22 +36,53 @@ Or install it yourself as:
|
|
22
36
|
|
23
37
|
## Usage
|
24
38
|
|
25
|
-
|
26
|
-
|
27
|
-
|
39
|
+
```bash
|
40
|
+
Usage: rubocop_pr [options]
|
41
|
+
-r, --post-checkout [command] Running after each git checkout (default: "")
|
42
|
+
-c, --continue Continue previous session (default: false)
|
43
|
+
-b, --branch [branch] internal branch with '.rubocop_todo.yml' (default: 'rubocop_todo_branch')
|
44
|
+
-m, --master [branch] branch which will be the base for all PR's (default: 'master')
|
45
|
+
-v, --version Display version
|
46
|
+
-o, --origin [origin] origin option for 'git push' (default: 'origin')
|
47
|
+
-u, --hub-version [version] Set manually minimum required version of 'hub' utility for github (default: 2.12.3)
|
48
|
+
-i, --issue-labels [labels] Labels for created issues, separated by comma (default: rubocop)
|
49
|
+
-p [labels], Labels for created pull requests, separated by comma (default: rubocop)
|
50
|
+
--pull-request-labels
|
51
|
+
-a, --issue-assignees [name] Issue assignees, separated by comma (default: "")
|
52
|
+
-t [name], Pull request assignees, separated by comma (default: "")
|
53
|
+
--pull-request-assignees
|
54
|
+
-g, --repository [name] Set repository host (default: github)
|
55
|
+
-l, --limit [limit] Limit the PS's for one run (default: 10)
|
56
|
+
-h, --help Display help
|
57
|
+
```
|
28
58
|
|
29
|
-
|
59
|
+
#### Notes
|
30
60
|
|
31
|
-
|
61
|
+
* `brach` option is useful, if you want to prepare the `.rubocop-todo.yml` manually and feed it to `rubocop_pr`.
|
62
|
+
* `post-checkout` handy for old Ruby versions, when shell may "forget" Ruby version.
|
32
63
|
|
33
64
|
## Contributing
|
34
65
|
|
35
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
66
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/kvokka/rubocop_pr. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant][contributor_covenant_link] code of conduct.
|
36
67
|
|
37
68
|
## License
|
38
69
|
|
39
|
-
The gem is available as open source under the terms of the [MIT License]
|
70
|
+
The gem is available as open source under the terms of the [MIT License][mit_link].
|
40
71
|
|
41
72
|
## Code of Conduct
|
42
73
|
|
43
|
-
Everyone interacting in the RubocopPr project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct]
|
74
|
+
Everyone interacting in the RubocopPr project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct][code_of_conduct_link].
|
75
|
+
|
76
|
+
[rubocop_repo]: https://github.com/rubocop-hq/rubocop
|
77
|
+
[contributor_covenant_link]: http://contributor-covenant.org
|
78
|
+
[mit_link]: https://opensource.org/licenses/MIT
|
79
|
+
[code_of_conduct_link]: https://github.com/[USERNAME]/rubocop_pr/blob/master/CODE_OF_CONDUCT.md
|
80
|
+
[rubocop_pr_example]: https://github.com/kvokka/rubocop_pr_example
|
81
|
+
[travisci_badge]: https://travis-ci.org/kvokka/rubocop_pr.svg?branch=master
|
82
|
+
[travisci]: https://travis-ci.org/kvokka/rubocop_pr
|
83
|
+
[rubygems]: https://rubygems.org/gems/rubocop_pr
|
84
|
+
[rubygems_badge]: http://img.shields.io/gem/v/rubocop_pr.svg
|
85
|
+
[codacy_badge]: https://api.codacy.com/project/badge/Grade/8be41ff90d294d7bb4c01fb3c98ebac9
|
86
|
+
[codacy]: https://app.codacy.com/app/kvokka/rubocop_pr?utm_source=github.com&utm_medium=referral&utm_content=kvokka/rubocop_pr&utm_campaign=Badge_Grade_Dashboard
|
87
|
+
[hound_badge]: https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg
|
88
|
+
[hound]: https://houndci.com
|
data/Rakefile
CHANGED
data/bin/console
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
|
-
require
|
4
|
-
require
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'rubocop_pr'
|
5
6
|
|
6
7
|
# You can add fixtures and/or initialization code here to make experimenting
|
7
8
|
# with your gem easier. You can also use a different console, if you like.
|
@@ -10,5 +11,5 @@ require "rubocop_pr"
|
|
10
11
|
# require "pry"
|
11
12
|
# Pry.start
|
12
13
|
|
13
|
-
require
|
14
|
+
require 'irb'
|
14
15
|
IRB.start(__FILE__)
|
data/exe/rubocop_pr
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
$LOAD_PATH.unshift("#{__dir__}/../lib")
|
5
|
+
|
6
|
+
require 'rubocop_pr'
|
7
|
+
require 'benchmark'
|
8
|
+
|
9
|
+
cli = RubocopPr::CLI.new(ARGV)
|
10
|
+
result = 0
|
11
|
+
|
12
|
+
time = Benchmark.realtime do
|
13
|
+
result = cli.run!
|
14
|
+
end
|
15
|
+
|
16
|
+
puts "Finished in #{time} seconds" if cli.options[:debug]
|
17
|
+
exit result
|
data/lib/rubocop_pr.rb
CHANGED
@@ -1,6 +1,27 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'optparse'
|
4
|
+
require 'ostruct'
|
5
|
+
require 'active_support/core_ext/hash'
|
6
|
+
require 'yaml'
|
7
|
+
|
8
|
+
require 'pry'
|
9
|
+
|
10
|
+
require 'rubocop_pr/version'
|
11
|
+
require 'rubocop_pr/options'
|
12
|
+
require 'rubocop_pr/environment_checker'
|
13
|
+
require 'rubocop_pr/cli/process_cop'
|
14
|
+
require 'rubocop_pr/cop'
|
15
|
+
require 'rubocop_pr/rubocop'
|
16
|
+
require 'rubocop_pr/git'
|
17
|
+
require 'rubocop_pr/repository'
|
18
|
+
require 'rubocop_pr/repositories/github'
|
19
|
+
require 'rubocop_pr/repositories/github/checks/verify_hub_version'
|
20
|
+
require 'rubocop_pr/cli'
|
21
|
+
|
22
|
+
# The entry point
|
3
23
|
module RubocopPr
|
4
24
|
class Error < StandardError; end
|
5
|
-
|
25
|
+
|
26
|
+
HUB_VERSION = '2.12.3'.freeze
|
6
27
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubocopPr
|
4
|
+
# Cunner from CLI interface
|
5
|
+
class CLI
|
6
|
+
attr_reader :options, :repository, :rubocop, :git
|
7
|
+
|
8
|
+
def initialize(argv = [])
|
9
|
+
@options = Options.new(argv).parse
|
10
|
+
@git = Git.new(post_checkout: @options.post_checkout, origin: @options.git_origin)
|
11
|
+
@repository = Repository.all.fetch(@options.repository)
|
12
|
+
@rubocop = RubocopPr::Rubocop.new(branch: @options.rubocop_todo_branch, git: @git)
|
13
|
+
end
|
14
|
+
|
15
|
+
def run!
|
16
|
+
EnvironmentChecker.call(repository, options)
|
17
|
+
run
|
18
|
+
git.checkout Rubocop::TODO_FILENAME
|
19
|
+
git.checkout(options.master_branch)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def run
|
25
|
+
rubocop.each do |cop|
|
26
|
+
break if options.limit <= 0
|
27
|
+
|
28
|
+
next unless ProcessCop.new(git: git, repository: repository, cop: cop, options: options).call
|
29
|
+
options.limit -= 1
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module RubocopPr
|
2
|
+
class CLI
|
3
|
+
# Cop processor
|
4
|
+
class ProcessCop
|
5
|
+
attr_reader :options, :git, :repository, :cop
|
6
|
+
|
7
|
+
def initialize(git:, repository:, cop:, options:)
|
8
|
+
@git = git
|
9
|
+
@repository = repository
|
10
|
+
@cop = cop
|
11
|
+
@options = options
|
12
|
+
end
|
13
|
+
|
14
|
+
def call
|
15
|
+
return false if exit_early?
|
16
|
+
checkout_to_target_branch_throw_master_branch
|
17
|
+
git.commit_all(issue.title)
|
18
|
+
git.push
|
19
|
+
create_pr
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def rubocop
|
25
|
+
@rubocop ||= RubocopPr::Rubocop.new(git: git)
|
26
|
+
end
|
27
|
+
|
28
|
+
def exit_early?
|
29
|
+
return true if options.continue && cop_was_processed? || git.status.blank?
|
30
|
+
Rubocop.correct!
|
31
|
+
|
32
|
+
git.checkout Rubocop::TODO_FILENAME
|
33
|
+
git.status.blank?
|
34
|
+
end
|
35
|
+
|
36
|
+
def cop_was_processed?
|
37
|
+
git.branch.match cop.branch
|
38
|
+
end
|
39
|
+
|
40
|
+
def issue
|
41
|
+
@issue ||= repository.issue(cop: cop, **options.to_h).create
|
42
|
+
end
|
43
|
+
|
44
|
+
def checkout_to_target_branch_throw_master_branch
|
45
|
+
git.checkout(options.master_branch)
|
46
|
+
git.checkout("#{issue.number}-#{cop.branch}")
|
47
|
+
end
|
48
|
+
|
49
|
+
def create_pr
|
50
|
+
repository.pull_request(cop: cop, body: "Closes ##{issue.number}", **options.to_h).create
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module RubocopPr
|
2
|
+
# Simple representation of the Cop
|
3
|
+
class Cop
|
4
|
+
attr_reader :name
|
5
|
+
|
6
|
+
def initialize(name:)
|
7
|
+
@name = name
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_s
|
11
|
+
name.to_s
|
12
|
+
end
|
13
|
+
|
14
|
+
def branch
|
15
|
+
"rubocop-fix-#{name.underscore.tr('/_', '-')}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubocopPr
|
4
|
+
# Service class, which only goal is to check that the system is suitable to run the script.
|
5
|
+
class EnvironmentChecker
|
6
|
+
def self.checks
|
7
|
+
@checks ||= [GitStatus]
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.call(repository, options)
|
11
|
+
checks.each { |c| c.call options }
|
12
|
+
repository.checks.each { |c| c.call options }
|
13
|
+
end
|
14
|
+
|
15
|
+
# Check that we do not have any un-commited changes
|
16
|
+
module GitStatus
|
17
|
+
module_function
|
18
|
+
|
19
|
+
def call(*)
|
20
|
+
return true if git_status.empty?
|
21
|
+
raise 'You have un-commited changes in this branch'
|
22
|
+
end
|
23
|
+
|
24
|
+
def git_status
|
25
|
+
RubocopPr::Git.new.status
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module RubocopPr
|
2
|
+
# small helper for git commands, everything should be stubbed in tests
|
3
|
+
class Git
|
4
|
+
attr_reader :post_checkout, :origin
|
5
|
+
|
6
|
+
def initialize(post_checkout: '', origin: '', **_options)
|
7
|
+
@post_checkout = post_checkout
|
8
|
+
@origin = origin
|
9
|
+
end
|
10
|
+
|
11
|
+
def checkout(file_or_branch)
|
12
|
+
return process_post_checkout if exec_checkout(file_or_branch)
|
13
|
+
exec_checkout file_or_branch, flags: ['-b']
|
14
|
+
process_post_checkout
|
15
|
+
end
|
16
|
+
|
17
|
+
def commit_all(message)
|
18
|
+
system 'git add .'
|
19
|
+
system "git commit -m '#{message}'"
|
20
|
+
end
|
21
|
+
|
22
|
+
def push
|
23
|
+
system "git push --set-upstream #{origin} #{current_branch}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def current_branch
|
27
|
+
`git branch --show-current`.chomp
|
28
|
+
end
|
29
|
+
|
30
|
+
def status
|
31
|
+
`git status -s`
|
32
|
+
end
|
33
|
+
|
34
|
+
def branch
|
35
|
+
`git branch`
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def process_post_checkout
|
41
|
+
post_checkout.blank? ? true : exec_post_checkout
|
42
|
+
end
|
43
|
+
|
44
|
+
def exec_checkout(branch, flags: [])
|
45
|
+
system "git checkout #{flags.join(' ')} #{branch}"
|
46
|
+
end
|
47
|
+
|
48
|
+
def exec_post_checkout
|
49
|
+
system post_checkout.to_s
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubocopPr
|
4
|
+
# Parse the options from the command line
|
5
|
+
class Options
|
6
|
+
attr_reader :options, :args
|
7
|
+
|
8
|
+
def initialize(args)
|
9
|
+
@args = args
|
10
|
+
@options = OpenStruct.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def parse
|
14
|
+
build_parser.parse!(args)
|
15
|
+
options
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
attr_accessor :opts
|
21
|
+
|
22
|
+
# options will be printed in order, as they are declared in this file
|
23
|
+
def build_parser
|
24
|
+
@parser = OptionParser.new do |op|
|
25
|
+
self.opts = op
|
26
|
+
opts.banner = 'Usage: rubocop_pr [options]'
|
27
|
+
|
28
|
+
private_methods(false).map(&:to_s).select { |m| m.start_with?('add_') }.each { |m| send m }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def add_limit_option
|
33
|
+
@options.limit = 10
|
34
|
+
msg = "Limit the PS's for one run (default: 10)"
|
35
|
+
opts.on('-l [limit]', '--limit [limit]', Integer, msg) do |v|
|
36
|
+
@options.limit = v
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def add_post_checkout_option
|
41
|
+
@options.post_checkout = ''
|
42
|
+
msg = 'Running after each git checkout (default: "")'
|
43
|
+
opts.on('-r [command]', '--post-checkout [command]', String, msg) do |v|
|
44
|
+
@options.post_checkout = v
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def add_rubocop_todo_branch_option
|
49
|
+
@options.rubocop_todo_branch = 'rubocop_todo_branch'
|
50
|
+
msg = "internal branch with '.rubocop_todo.yml' (default: 'rubocop_todo_branch')"
|
51
|
+
opts.on('-b [branch]', '--branch [branch]', String, msg) do |v|
|
52
|
+
@options.rubocop_todo_branch = v
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def add_master_branch_option
|
57
|
+
@options.master_branch = 'master'
|
58
|
+
msg = "branch which will be the base for all PR's (default: 'master')"
|
59
|
+
opts.on('-m [branch]', '--master [branch]', String, msg) do |v|
|
60
|
+
@options.master_branch = v
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def add_git_origin_option
|
65
|
+
@options.git_origin = 'origin'
|
66
|
+
msg = "origin option for 'git push' (default: 'origin')"
|
67
|
+
opts.on('-o [origin]', '--origin [origin]', String, msg) do |v|
|
68
|
+
@options.git_origin = v
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def add_hub_version_option
|
73
|
+
@options.hub_version = HUB_VERSION
|
74
|
+
msg = "Set manually minimum required version of 'hub' utility for github (default: #{HUB_VERSION})"
|
75
|
+
opts.on('-u [version] ', '--hub-version [version]', msg) do |v|
|
76
|
+
@options.hub_version = v
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def add_issue_labels_option
|
81
|
+
@options.issue_labels = ['rubocop']
|
82
|
+
msg = 'Labels for created issues, separated by comma (default: rubocop)'
|
83
|
+
opts.on('-i [labels] ', '--issue-labels [labels]', Array, msg) do |v|
|
84
|
+
@options.issue_labels = v
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def add_pull_request_labels_option
|
89
|
+
@options.pull_request_labels = ['rubocop']
|
90
|
+
msg = 'Labels for created pull requests, separated by comma (default: rubocop)'
|
91
|
+
opts.on('-p [labels] ', '--pull-request-labels [labels]', Array, msg) do |v|
|
92
|
+
@options.pull_request_labels = v
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def add_issue_assignees_option
|
97
|
+
@options.issue_assignees = []
|
98
|
+
msg = 'Issue assignees, separated by comma (default: "")'
|
99
|
+
opts.on('-a [name] ', '--issue-assignees [name]', Array, msg) do |v|
|
100
|
+
@options.issue_assignees = v
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def add_pull_request_assignees_option
|
105
|
+
@options.pull_request_assignees = []
|
106
|
+
msg = 'Pull request assignees, separated by comma (default: "")'
|
107
|
+
opts.on('-t [name] ', '--pull-request-assignees [name]', Array, msg) do |v|
|
108
|
+
@options.pull_request_assignees = v
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def add_repository_option
|
113
|
+
@options.repository = 'github'
|
114
|
+
msg = 'Set repository host (default: github)'
|
115
|
+
opts.on('-g [name] ', '--repository [name]', msg) do |v|
|
116
|
+
@options.repository = v
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def add_continue_option
|
121
|
+
@options.continue = false
|
122
|
+
opts.on('-c', '--continue', 'Continue previous session (default: false)') do |_v|
|
123
|
+
@options.continue = true
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def add_version_option
|
128
|
+
opts.on('-v', '--version', 'Display version') do
|
129
|
+
puts RubocopPr::VERSION
|
130
|
+
exit
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def add_on_tail
|
135
|
+
opts.on_tail('-h', '--help', 'Display help') do
|
136
|
+
puts opts
|
137
|
+
exit
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
module RubocopPr
|
2
|
+
module Repositories
|
3
|
+
# Github repository
|
4
|
+
class Github < RubocopPr::Repository
|
5
|
+
# Base class for working with `hub` utility
|
6
|
+
class Base
|
7
|
+
attr_reader :title, :body, :cop, :number
|
8
|
+
|
9
|
+
def initialize(cop:, **options)
|
10
|
+
@cop = cop
|
11
|
+
@options = options
|
12
|
+
@title = options.delete(:title) || default_title
|
13
|
+
@body = options.delete(:body) || default_body
|
14
|
+
end
|
15
|
+
|
16
|
+
def create
|
17
|
+
@number = `#{build_command}`.split('/').last.to_i
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
def assignees
|
22
|
+
@assignees ||= Array options[:assignees]
|
23
|
+
end
|
24
|
+
|
25
|
+
def labels
|
26
|
+
@labels ||= Array options[:labels]
|
27
|
+
end
|
28
|
+
|
29
|
+
def build_command
|
30
|
+
[command, cli_options].join ' '
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
attr_reader :options
|
36
|
+
|
37
|
+
def command
|
38
|
+
raise NotImplemented
|
39
|
+
end
|
40
|
+
|
41
|
+
def cli_options
|
42
|
+
[].tap do |opt|
|
43
|
+
opt << "-m '#{title}'"
|
44
|
+
opt << "-m '#{body}'" unless body.blank?
|
45
|
+
opt << "-a '#{assignees.join(',')}'" unless assignees.blank?
|
46
|
+
opt << "-l '#{labels.join(',')}'" unless labels.blank?
|
47
|
+
end.join(' ')
|
48
|
+
end
|
49
|
+
|
50
|
+
def default_title
|
51
|
+
"Fix Rubocop #{cop} warnings"
|
52
|
+
end
|
53
|
+
|
54
|
+
def default_body
|
55
|
+
''
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# The representation of the Issue
|
60
|
+
class Issue < Base
|
61
|
+
def initialize(cop:, **opt)
|
62
|
+
super
|
63
|
+
@assignees = Array opt[:issue_assignees]
|
64
|
+
@labels = Array opt[:issue_labels]
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def command
|
70
|
+
'hub issue create'
|
71
|
+
end
|
72
|
+
|
73
|
+
def default_body
|
74
|
+
'This issue was created by [rubocop_pr](https://github.com/kvokka/rubocop_pr) for ' \
|
75
|
+
'[rubocop](https://github.com/rubocop-hq/rubocop)'
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# The representation of the PR
|
80
|
+
class PullRequest < Base
|
81
|
+
def initialize(cop:, **opt)
|
82
|
+
super
|
83
|
+
@assignees = Array opt[:pull_request_assignees]
|
84
|
+
@labels = Array opt[:pull_request_labels]
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def command
|
90
|
+
'hub pull-request create'
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class << self
|
95
|
+
def checks
|
96
|
+
super + [RubocopPr::Repositories::Github::Checks::VerifyHubVersion]
|
97
|
+
end
|
98
|
+
|
99
|
+
def issue(*args)
|
100
|
+
Issue.new(*args)
|
101
|
+
end
|
102
|
+
|
103
|
+
def pull_request(*args)
|
104
|
+
PullRequest.new(*args)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module RubocopPr
|
2
|
+
module Repositories
|
3
|
+
class Github < RubocopPr::Repository
|
4
|
+
module Checks
|
5
|
+
# Check, if `hub` installed and have right version
|
6
|
+
module VerifyHubVersion
|
7
|
+
module_function
|
8
|
+
|
9
|
+
def call(options)
|
10
|
+
return true if system_hub_version >= Gem::Version.new(options.hub_version)
|
11
|
+
warn "Script was tested with hub version #{HUB_VERSION}, while you are using #{system_hub_version}"
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
15
|
+
def system_hub_version
|
16
|
+
matches = hub_version.match(/hub version (?<hub_version>(.*))/)
|
17
|
+
Gem::Version.new matches.captures.last
|
18
|
+
rescue StandardError
|
19
|
+
raise "Robopop requires https://github.com/github/hub version >= #{RubocopPr::HUB_VERSION}"
|
20
|
+
end
|
21
|
+
|
22
|
+
def hub_version
|
23
|
+
`hub --version`
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module RubocopPr
|
2
|
+
# abstract repository class
|
3
|
+
class Repository
|
4
|
+
class << self
|
5
|
+
def all
|
6
|
+
@all ||= ::ActiveSupport::HashWithIndifferentAccess.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def inherited(base)
|
10
|
+
all[base.name.demodulize.underscore] = base
|
11
|
+
end
|
12
|
+
|
13
|
+
# Array of Class which respond_to ::call and raise if check do not pass
|
14
|
+
def checks
|
15
|
+
[]
|
16
|
+
end
|
17
|
+
|
18
|
+
# return Integer issue number
|
19
|
+
def create_issue(*)
|
20
|
+
raise NotImplemented, 'should be implemented on sub-class'
|
21
|
+
end
|
22
|
+
|
23
|
+
# return Integer pull_request number
|
24
|
+
def create_pull_request(*)
|
25
|
+
raise NotImplemented, 'should be implemented on sub-class'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module RubocopPr
|
2
|
+
# small helper for rubocop commands, everything should be stubbed in tests
|
3
|
+
class Rubocop
|
4
|
+
include Enumerable
|
5
|
+
|
6
|
+
TODO_FILENAME = '.rubocop_todo.yml'.freeze
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def generate_todo
|
10
|
+
system 'bundle exec rubocop --auto-gen-config'
|
11
|
+
end
|
12
|
+
|
13
|
+
def correct!
|
14
|
+
system 'bundle exec rubocop -a'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_reader :branch, :git
|
19
|
+
|
20
|
+
def initialize(**options)
|
21
|
+
@branch = options.delete(:branch)
|
22
|
+
@git = options.delete(:git)
|
23
|
+
end
|
24
|
+
|
25
|
+
def todo
|
26
|
+
@todo ||= YAML.safe_load(read_or_generate_todo)
|
27
|
+
end
|
28
|
+
|
29
|
+
def each
|
30
|
+
todo.keys.sort.reverse_each do |cop|
|
31
|
+
git.checkout(branch)
|
32
|
+
File.open(TODO_FILENAME, 'w') do |f|
|
33
|
+
f.write todo.except(cop.to_s).blank? ? '' : YAML.dump(todo.except(cop.to_s))
|
34
|
+
end
|
35
|
+
yield Cop.new(name: cop)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def read_or_generate_todo
|
40
|
+
git.checkout(branch)
|
41
|
+
return File.read(TODO_FILENAME) if File.exist?(TODO_FILENAME)
|
42
|
+
self.class.generate_todo
|
43
|
+
git.commit_all('Generate initial Rubocop todo file')
|
44
|
+
File.read(TODO_FILENAME)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/rubocop_pr/version.rb
CHANGED
data/rubocop_pr.gemspec
CHANGED
@@ -1,32 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
|
2
|
-
lib = File.expand_path(
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require
|
5
|
+
require 'rubocop_pr/version'
|
5
6
|
|
6
7
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
8
|
+
spec.name = 'rubocop_pr'
|
8
9
|
spec.version = RubocopPr::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
10
|
+
spec.authors = ['kvokka']
|
11
|
+
spec.email = ['kvokka@yahoo.com']
|
11
12
|
|
12
|
-
spec.summary =
|
13
|
-
spec.description =
|
14
|
-
spec.homepage =
|
15
|
-
spec.license =
|
13
|
+
spec.summary = 'Quick & clean Rubocop introduction.'
|
14
|
+
spec.description = 'Create 1 PR per 1 Rubocop linter, which allow to do review rubocop changes smoothly.'
|
15
|
+
spec.homepage = 'https://github.com/kvokka/rubocop_pr'
|
16
|
+
spec.license = 'MIT'
|
16
17
|
|
17
|
-
|
18
|
-
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
18
|
+
spec.required_ruby_version = '~> 2.5'
|
19
19
|
|
20
20
|
# Specify which files should be added to the gem when it is released.
|
21
21
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
22
|
-
spec.files
|
22
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
23
23
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
24
24
|
end
|
25
|
-
spec.bindir =
|
25
|
+
spec.bindir = 'exe'
|
26
26
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
27
|
-
spec.require_paths = [
|
27
|
+
spec.require_paths = ['lib']
|
28
28
|
|
29
|
-
spec.
|
30
|
-
spec.
|
31
|
-
|
29
|
+
spec.add_dependency 'activesupport', '>= 4.2.0', '< 7.0'
|
30
|
+
spec.add_dependency 'rubocop', '>= 1.0.0'
|
31
|
+
|
32
|
+
spec.add_development_dependency 'overcommit', '~> 0.57'
|
33
|
+
spec.add_development_dependency 'pry', '~> 0.13'
|
34
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
35
|
+
spec.add_development_dependency 'rspec', '>= 3.0'
|
36
|
+
spec.add_development_dependency 'rubocop-rspec', '~> 2.1.0'
|
32
37
|
end
|
metadata
CHANGED
@@ -1,66 +1,132 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubocop_pr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- kvokka
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-02-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: activesupport
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 4.2.0
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '7.0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 4.2.0
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '7.0'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: rubocop
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: 1.0.0
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 1.0.0
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: overcommit
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0.57'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
16
57
|
requirements:
|
17
58
|
- - "~>"
|
18
59
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
60
|
+
version: '0.57'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: pry
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0.13'
|
20
68
|
type: :development
|
21
69
|
prerelease: false
|
22
70
|
version_requirements: !ruby/object:Gem::Requirement
|
23
71
|
requirements:
|
24
72
|
- - "~>"
|
25
73
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
74
|
+
version: '0.13'
|
27
75
|
- !ruby/object:Gem::Dependency
|
28
76
|
name: rake
|
29
77
|
requirement: !ruby/object:Gem::Requirement
|
30
78
|
requirements:
|
31
79
|
- - "~>"
|
32
80
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
81
|
+
version: '13.0'
|
34
82
|
type: :development
|
35
83
|
prerelease: false
|
36
84
|
version_requirements: !ruby/object:Gem::Requirement
|
37
85
|
requirements:
|
38
86
|
- - "~>"
|
39
87
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
88
|
+
version: '13.0'
|
41
89
|
- !ruby/object:Gem::Dependency
|
42
90
|
name: rspec
|
43
91
|
requirement: !ruby/object:Gem::Requirement
|
44
92
|
requirements:
|
45
|
-
- - "
|
93
|
+
- - ">="
|
46
94
|
- !ruby/object:Gem::Version
|
47
95
|
version: '3.0'
|
48
96
|
type: :development
|
49
97
|
prerelease: false
|
50
98
|
version_requirements: !ruby/object:Gem::Requirement
|
51
99
|
requirements:
|
52
|
-
- - "
|
100
|
+
- - ">="
|
53
101
|
- !ruby/object:Gem::Version
|
54
102
|
version: '3.0'
|
55
|
-
|
103
|
+
- !ruby/object:Gem::Dependency
|
104
|
+
name: rubocop-rspec
|
105
|
+
requirement: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - "~>"
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 2.1.0
|
110
|
+
type: :development
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - "~>"
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: 2.1.0
|
117
|
+
description: Create 1 PR per 1 Rubocop linter, which allow to do review rubocop changes
|
118
|
+
smoothly.
|
56
119
|
email:
|
57
120
|
- kvokka@yahoo.com
|
58
|
-
executables:
|
121
|
+
executables:
|
122
|
+
- rubocop_pr
|
59
123
|
extensions: []
|
60
124
|
extra_rdoc_files: []
|
61
125
|
files:
|
62
126
|
- ".gitignore"
|
127
|
+
- ".overcommit.yml"
|
63
128
|
- ".rspec"
|
129
|
+
- ".rubocop.yml"
|
64
130
|
- ".travis.yml"
|
65
131
|
- CODE_OF_CONDUCT.md
|
66
132
|
- Gemfile
|
@@ -69,30 +135,41 @@ files:
|
|
69
135
|
- Rakefile
|
70
136
|
- bin/console
|
71
137
|
- bin/setup
|
138
|
+
- exe/rubocop_pr
|
72
139
|
- lib/rubocop_pr.rb
|
140
|
+
- lib/rubocop_pr/cli.rb
|
141
|
+
- lib/rubocop_pr/cli/process_cop.rb
|
142
|
+
- lib/rubocop_pr/cop.rb
|
143
|
+
- lib/rubocop_pr/environment_checker.rb
|
144
|
+
- lib/rubocop_pr/git.rb
|
145
|
+
- lib/rubocop_pr/options.rb
|
146
|
+
- lib/rubocop_pr/repositories/github.rb
|
147
|
+
- lib/rubocop_pr/repositories/github/checks/verify_hub_version.rb
|
148
|
+
- lib/rubocop_pr/repository.rb
|
149
|
+
- lib/rubocop_pr/rubocop.rb
|
73
150
|
- lib/rubocop_pr/version.rb
|
74
151
|
- rubocop_pr.gemspec
|
75
|
-
homepage:
|
152
|
+
homepage: https://github.com/kvokka/rubocop_pr
|
76
153
|
licenses:
|
77
154
|
- MIT
|
78
155
|
metadata: {}
|
79
|
-
post_install_message:
|
156
|
+
post_install_message:
|
80
157
|
rdoc_options: []
|
81
158
|
require_paths:
|
82
159
|
- lib
|
83
160
|
required_ruby_version: !ruby/object:Gem::Requirement
|
84
161
|
requirements:
|
85
|
-
- - "
|
162
|
+
- - "~>"
|
86
163
|
- !ruby/object:Gem::Version
|
87
|
-
version: '
|
164
|
+
version: '2.5'
|
88
165
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
166
|
requirements:
|
90
167
|
- - ">="
|
91
168
|
- !ruby/object:Gem::Version
|
92
169
|
version: '0'
|
93
170
|
requirements: []
|
94
|
-
rubygems_version: 3.
|
95
|
-
signing_key:
|
171
|
+
rubygems_version: 3.1.4
|
172
|
+
signing_key:
|
96
173
|
specification_version: 4
|
97
|
-
summary:
|
174
|
+
summary: Quick & clean Rubocop introduction.
|
98
175
|
test_files: []
|