rubocop_pr 0.1.0 → 1.0.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 +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: []
|