rubocop_pr 0.1.0 → 0.2.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 +11 -0
- data/.travis.yml +11 -2
- data/Gemfile +4 -2
- data/README.md +48 -11
- data/Rakefile +5 -3
- data/bin/console +4 -3
- data/exe/rubocop_pr +17 -0
- data/lib/rubocop_pr/cli.rb +49 -0
- data/lib/rubocop_pr/environment_checker.rb +29 -0
- data/lib/rubocop_pr/git.rb +52 -0
- data/lib/rubocop_pr/options.rb +114 -0
- data/lib/rubocop_pr/repositories/github/checks/verify_hub_version.rb +29 -0
- data/lib/rubocop_pr/repositories/github.rb +55 -0
- data/lib/rubocop_pr/repository.rb +29 -0
- data/lib/rubocop_pr/rubocop.rb +48 -0
- data/lib/rubocop_pr/version.rb +3 -1
- data/lib/rubocop_pr.rb +21 -2
- data/rubocop_pr.gemspec +23 -17
- metadata +98 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 41140375dff6c844311e1bf2eea32974bdb78df0a703a117b0341eac7cb55928
|
4
|
+
data.tar.gz: b0bbd0edc7b6f6e9f084442630fa4dcc78e8212789207770fd83904241e08eb8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 01dfc86addb40874e9620b21233082cb093c6dca661accd2a451833730a78659e7bb147b2bc05afbccd1d742bdc301a95f126da010167ca9ff3fc1dfdee7b6c6
|
7
|
+
data.tar.gz: 5bf1b5cfbda7db9805638583b6260124e846b1cd8b948eee499801b13bf9f0bf3ba1fba8a3fb6f7f2ba8bbeb927e9dd3a006a2371aa88cd423f81b63b9e1c31c
|
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
@@ -3,5 +3,14 @@ sudo: false
|
|
3
3
|
language: ruby
|
4
4
|
cache: bundler
|
5
5
|
rvm:
|
6
|
-
- 2.
|
7
|
-
|
6
|
+
- 2.1
|
7
|
+
- 2.2
|
8
|
+
- 2.3
|
9
|
+
- 2.4
|
10
|
+
- 2.5
|
11
|
+
- 2.6
|
12
|
+
before_install:
|
13
|
+
- gem install bundler -v 1.17.3
|
14
|
+
- sudo add-apt-repository ppa:cpick/hub -y
|
15
|
+
- sudo apt-get update
|
16
|
+
- sudo apt-get install hub
|
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,26 @@
|
|
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
|
+
With RubocopPr you can apply [Rubocop][rubocop_repo] clean and in a few minutes.
|
11
|
+
|
12
|
+
## Requirements
|
13
|
+
|
14
|
+
* Ruby 2.1+
|
15
|
+
* Hub 2.12.3 (tested with this version only, but should work with older versions)
|
16
|
+
* Github
|
6
17
|
|
7
18
|
## Installation
|
8
19
|
|
9
20
|
Add this line to your application's Gemfile:
|
10
21
|
|
11
22
|
```ruby
|
12
|
-
gem 'rubocop_pr'
|
23
|
+
gem 'rubocop_pr', require: false
|
13
24
|
```
|
14
25
|
|
15
26
|
And then execute:
|
@@ -22,22 +33,48 @@ Or install it yourself as:
|
|
22
33
|
|
23
34
|
## Usage
|
24
35
|
|
25
|
-
|
26
|
-
|
27
|
-
|
36
|
+
```bash
|
37
|
+
Usage: rubocop_pr [options]
|
38
|
+
-u, --hub-version [version] Set manually minimum required version of 'hub' utility for github (default: 2.12.3)
|
39
|
+
-b, --branch [branch] internal branch with '.rubocop_todo.yml' (default: 'rubocop_todo_branch')
|
40
|
+
-m, --master [branch] branch which will be the base for all PR's (default: 'master')
|
41
|
+
-r, --post-checkout [command] Running after each git checkout (default: "")
|
42
|
+
-l, --limit [limit] Limit the PS's for one run (default: 10)
|
43
|
+
-g, --repository [name] Set repository host (default: github)
|
44
|
+
-o, --origin [origin] origin option for 'git push' (default: 'origin')
|
45
|
+
-c, --continue Continue previous session (default: false)
|
46
|
+
-v, --version Display version
|
47
|
+
-h, --help Display help
|
48
|
+
```
|
28
49
|
|
29
|
-
|
50
|
+
#### Notes
|
30
51
|
|
31
|
-
|
52
|
+
* `brach` option is useful, if you want to prepare the `.rubocop-todo.yml` manually and feed it to `rubocop_pr`
|
53
|
+
* `post-checkout` handy for old Ruby versions, when shell may "forget" Ruby version.
|
32
54
|
|
33
55
|
## Contributing
|
34
56
|
|
35
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/rubocop_pr. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant]
|
57
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/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
58
|
|
37
59
|
## License
|
38
60
|
|
39
|
-
The gem is available as open source under the terms of the [MIT License]
|
61
|
+
The gem is available as open source under the terms of the [MIT License][mit_link].
|
40
62
|
|
41
63
|
## Code of Conduct
|
42
64
|
|
43
|
-
Everyone interacting in the RubocopPr project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct]
|
65
|
+
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].
|
66
|
+
|
67
|
+
|
68
|
+
[rubocop_repo]: https://github.com/rubocop-hq/rubocop
|
69
|
+
[contributor_covenant_link]: http://contributor-covenant.org
|
70
|
+
[mit_link]: https://opensource.org/licenses/MIT
|
71
|
+
[code_of_conduct_link]: https://github.com/[USERNAME]/rubocop_pr/blob/master/CODE_OF_CONDUCT.md
|
72
|
+
|
73
|
+
[travisci_badge]: https://travis-ci.org/kvokka/rubocop_pr.svg?branch=master
|
74
|
+
[travisci]: https://travis-ci.org/kvokka/rubocop_pr
|
75
|
+
[rubygems]: https://rubygems.org/gems/rubocop_pr
|
76
|
+
[rubygems_badge]: http://img.shields.io/gem/v/rubocop_pr.svg
|
77
|
+
[codacy_badge]: https://api.codacy.com/project/badge/Grade/8be41ff90d294d7bb4c01fb3c98ebac9
|
78
|
+
[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
|
79
|
+
[hound_badge]: https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg
|
80
|
+
[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
|
@@ -0,0 +1,49 @@
|
|
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(options.master_branch)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def run
|
24
|
+
rubocop.inject(0) do |counter, cop|
|
25
|
+
next counter if git.status.blank?
|
26
|
+
next counter if options.continue && git.branch =~ /#{branch_suffix(cop)}\s/
|
27
|
+
next counter unless rubocop.corrected?
|
28
|
+
process_cop(cop)
|
29
|
+
|
30
|
+
break if counter >= options.limit - 1
|
31
|
+
counter + 1
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def process_cop(cop)
|
36
|
+
git.checkout(options.master_branch)
|
37
|
+
title = "Fix Rubocop #{cop} warnings"
|
38
|
+
issue_number = repository.create_issue(title: title)
|
39
|
+
git.checkout("#{issue_number}-#{branch_suffix(cop)}")
|
40
|
+
git.commit_all(title)
|
41
|
+
git.push
|
42
|
+
repository.create_pull_request(title: title, body: "Closes ##{issue_number}")
|
43
|
+
end
|
44
|
+
|
45
|
+
def branch_suffix(cop)
|
46
|
+
"rubocop-fix-#{cop.underscore.tr('/_', '-')}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
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,114 @@
|
|
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
|
+
def build_parser # rubocop:disable Metrics/MethodLength
|
21
|
+
@parser = OptionParser.new do |opts|
|
22
|
+
opts.banner = 'Usage: rubocop_pr [options]'
|
23
|
+
|
24
|
+
add_hub_version_option(opts)
|
25
|
+
add_rubocop_todo_branch_option(opts)
|
26
|
+
add_master_branch_option(opts)
|
27
|
+
add_post_checkout_option(opts)
|
28
|
+
add_limit_option(opts)
|
29
|
+
add_repository_option(opts)
|
30
|
+
add_git_origin_option(opts)
|
31
|
+
add_continue_option(opts)
|
32
|
+
add_version_option(opts)
|
33
|
+
add_on_tail(opts)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def add_limit_option(opts)
|
38
|
+
@options.limit = 10
|
39
|
+
msg = "Limit the PS's for one run (default: 10)"
|
40
|
+
opts.on('-l [limit]', '--limit [limit]', Integer, msg) do |v|
|
41
|
+
@options.limit = v
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def add_post_checkout_option(opts)
|
46
|
+
@options.post_checkout = ''
|
47
|
+
msg = 'Running after each git checkout (default: "")'
|
48
|
+
opts.on('-r [command]', '--post-checkout [command]', String, msg) do |v|
|
49
|
+
@options.post_checkout = v
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def add_rubocop_todo_branch_option(opts)
|
54
|
+
@options.rubocop_todo_branch = 'rubocop_todo_branch'
|
55
|
+
msg = "internal branch with '.rubocop_todo.yml' (default: 'rubocop_todo_branch')"
|
56
|
+
opts.on('-b [branch]', '--branch [branch]', String, msg) do |v|
|
57
|
+
@options.rubocop_todo_branch = v
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def add_master_branch_option(opts)
|
62
|
+
@options.master_branch = 'master'
|
63
|
+
msg = "branch which will be the base for all PR's (default: 'master')"
|
64
|
+
opts.on('-m [branch]', '--master [branch]', String, msg) do |v|
|
65
|
+
@options.master_branch = v
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def add_git_origin_option(opts)
|
70
|
+
@options.git_origin = 'origin'
|
71
|
+
msg = "origin option for 'git push' (default: 'origin')"
|
72
|
+
opts.on('-o [origin]', '--origin [origin]', String, msg) do |v|
|
73
|
+
@options.git_origin = v
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def add_hub_version_option(opts)
|
78
|
+
@options.hub_version = HUB_VERSION
|
79
|
+
msg = "Set manually minimum required version of 'hub' utility for github (default: #{HUB_VERSION})"
|
80
|
+
opts.on('-u [version] ', '--hub-version [version]', msg) do |v|
|
81
|
+
@options.hub_version = v
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def add_repository_option(opts)
|
86
|
+
@options.repository = 'github'
|
87
|
+
msg = 'Set repository host (default: github)'
|
88
|
+
opts.on('-g [name] ', '--repository [name]', msg) do |v|
|
89
|
+
@options.repository = v
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def add_continue_option(opts)
|
94
|
+
@options.continue = false
|
95
|
+
opts.on('-c', '--continue', 'Continue previous session (default: false)') do |_v|
|
96
|
+
@options.continue = true
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def add_version_option(opts)
|
101
|
+
opts.on('-v', '--version', 'Display version') do
|
102
|
+
puts RubocopPr::VERSION
|
103
|
+
exit
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def add_on_tail(opts)
|
108
|
+
opts.on_tail('-h', '--help', 'Display help') do
|
109
|
+
puts opts
|
110
|
+
exit
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
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,55 @@
|
|
1
|
+
module RubocopPr
|
2
|
+
module Repositories
|
3
|
+
# Github repository
|
4
|
+
class Github < RubocopPr::Repository
|
5
|
+
# The representation of the Issue
|
6
|
+
class Issue
|
7
|
+
attr_reader :title, :body
|
8
|
+
|
9
|
+
def initialize(title:, **other)
|
10
|
+
@title = title
|
11
|
+
@body = other[:body] || default_body
|
12
|
+
end
|
13
|
+
|
14
|
+
def create
|
15
|
+
link = `hub issue create -m '#{title}' -m '#{body}'`
|
16
|
+
link.split('/').last.to_i
|
17
|
+
end
|
18
|
+
|
19
|
+
def default_body
|
20
|
+
'This issue was created by [rubocop_pr](https://github.com/kvokka/rubocop_pr) for ' \
|
21
|
+
'[rubocop](https://github.com/rubocop-hq/rubocop)'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# The representation of the PR
|
26
|
+
class PullRequest
|
27
|
+
attr_reader :title, :body
|
28
|
+
|
29
|
+
def initialize(title:, **other)
|
30
|
+
@title = title
|
31
|
+
@body = other[:body] || ''
|
32
|
+
end
|
33
|
+
|
34
|
+
def create
|
35
|
+
link = `hub pull-request create -m '#{title}' -m '#{body}'`
|
36
|
+
link.split('/').last.to_i
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class << self
|
41
|
+
def checks
|
42
|
+
super + [RubocopPr::Repositories::Github::Checks::VerifyHubVersion]
|
43
|
+
end
|
44
|
+
|
45
|
+
def create_issue(*args)
|
46
|
+
Issue.new(*args).create
|
47
|
+
end
|
48
|
+
|
49
|
+
def create_pull_request(*args)
|
50
|
+
PullRequest.new(*args).create
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
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,48 @@
|
|
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
|
+
attr_reader :branch, :git
|
9
|
+
|
10
|
+
def initialize(**options)
|
11
|
+
@branch = options.delete(:branch)
|
12
|
+
@git = options.delete(:git)
|
13
|
+
end
|
14
|
+
|
15
|
+
def todo
|
16
|
+
YAML.safe_load(read_or_generate_todo)
|
17
|
+
end
|
18
|
+
|
19
|
+
def each
|
20
|
+
git.checkout(branch)
|
21
|
+
todos_backup = todo
|
22
|
+
todos_backup.each_key do |cop|
|
23
|
+
git.checkout(branch)
|
24
|
+
todos = todos_backup.dup
|
25
|
+
todos.delete cop
|
26
|
+
File.open(TODO_FILENAME, 'w') { |f| f.write todos.blank? ? '' : YAML.dump(todos) }
|
27
|
+
yield cop
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def read_or_generate_todo
|
32
|
+
return File.read(TODO_FILENAME) if File.exist?(TODO_FILENAME)
|
33
|
+
generate_todo
|
34
|
+
git.commit_all('Generate initial Rubocop todo file')
|
35
|
+
File.read(TODO_FILENAME)
|
36
|
+
end
|
37
|
+
|
38
|
+
def generate_todo
|
39
|
+
`bundle exec rubocop --auto-gen-config`
|
40
|
+
end
|
41
|
+
|
42
|
+
def corrected?
|
43
|
+
`bundle exec rubocop -a`
|
44
|
+
git.checkout TODO_FILENAME
|
45
|
+
!git.status.blank?
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/rubocop_pr/version.rb
CHANGED
data/lib/rubocop_pr.rb
CHANGED
@@ -1,6 +1,25 @@
|
|
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/rubocop'
|
14
|
+
require 'rubocop_pr/git'
|
15
|
+
require 'rubocop_pr/repository'
|
16
|
+
require 'rubocop_pr/repositories/github'
|
17
|
+
require 'rubocop_pr/repositories/github/checks/verify_hub_version'
|
18
|
+
require 'rubocop_pr/cli'
|
19
|
+
|
20
|
+
# The entry point
|
3
21
|
module RubocopPr
|
4
22
|
class Error < StandardError; end
|
5
|
-
|
23
|
+
|
24
|
+
HUB_VERSION = '2.12.3'.freeze
|
6
25
|
end
|
data/rubocop_pr.gemspec
CHANGED
@@ -1,32 +1,38 @@
|
|
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.1'
|
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', '< 6.0'
|
30
|
+
spec.add_dependency 'rubocop', '~> 0.57.0'
|
31
|
+
|
32
|
+
spec.add_development_dependency 'bundler', '~> 1.16'
|
33
|
+
spec.add_development_dependency 'overcommit', '~> 0.44'
|
34
|
+
spec.add_development_dependency 'pry', '~> 0.12'
|
35
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
36
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
37
|
+
spec.add_development_dependency 'rubocop-rspec', '~> 1.27'
|
32
38
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubocop_pr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- kvokka
|
@@ -10,20 +10,82 @@ bindir: exe
|
|
10
10
|
cert_chain: []
|
11
11
|
date: 2019-08-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
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: '6.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: '6.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: 0.57.0
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 0.57.0
|
13
47
|
- !ruby/object:Gem::Dependency
|
14
48
|
name: bundler
|
15
49
|
requirement: !ruby/object:Gem::Requirement
|
16
50
|
requirements:
|
17
51
|
- - "~>"
|
18
52
|
- !ruby/object:Gem::Version
|
19
|
-
version: '1.
|
53
|
+
version: '1.16'
|
20
54
|
type: :development
|
21
55
|
prerelease: false
|
22
56
|
version_requirements: !ruby/object:Gem::Requirement
|
23
57
|
requirements:
|
24
58
|
- - "~>"
|
25
59
|
- !ruby/object:Gem::Version
|
26
|
-
version: '1.
|
60
|
+
version: '1.16'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: overcommit
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0.44'
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0.44'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: pry
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0.12'
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0.12'
|
27
89
|
- !ruby/object:Gem::Dependency
|
28
90
|
name: rake
|
29
91
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,15 +114,33 @@ dependencies:
|
|
52
114
|
- - "~>"
|
53
115
|
- !ruby/object:Gem::Version
|
54
116
|
version: '3.0'
|
55
|
-
|
117
|
+
- !ruby/object:Gem::Dependency
|
118
|
+
name: rubocop-rspec
|
119
|
+
requirement: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - "~>"
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '1.27'
|
124
|
+
type: :development
|
125
|
+
prerelease: false
|
126
|
+
version_requirements: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - "~>"
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: '1.27'
|
131
|
+
description: Create 1 PR per 1 Rubocop linter, which allow to do review rubocop changes
|
132
|
+
smoothly.
|
56
133
|
email:
|
57
134
|
- kvokka@yahoo.com
|
58
|
-
executables:
|
135
|
+
executables:
|
136
|
+
- rubocop_pr
|
59
137
|
extensions: []
|
60
138
|
extra_rdoc_files: []
|
61
139
|
files:
|
62
140
|
- ".gitignore"
|
141
|
+
- ".overcommit.yml"
|
63
142
|
- ".rspec"
|
143
|
+
- ".rubocop.yml"
|
64
144
|
- ".travis.yml"
|
65
145
|
- CODE_OF_CONDUCT.md
|
66
146
|
- Gemfile
|
@@ -69,10 +149,19 @@ files:
|
|
69
149
|
- Rakefile
|
70
150
|
- bin/console
|
71
151
|
- bin/setup
|
152
|
+
- exe/rubocop_pr
|
72
153
|
- lib/rubocop_pr.rb
|
154
|
+
- lib/rubocop_pr/cli.rb
|
155
|
+
- lib/rubocop_pr/environment_checker.rb
|
156
|
+
- lib/rubocop_pr/git.rb
|
157
|
+
- lib/rubocop_pr/options.rb
|
158
|
+
- lib/rubocop_pr/repositories/github.rb
|
159
|
+
- lib/rubocop_pr/repositories/github/checks/verify_hub_version.rb
|
160
|
+
- lib/rubocop_pr/repository.rb
|
161
|
+
- lib/rubocop_pr/rubocop.rb
|
73
162
|
- lib/rubocop_pr/version.rb
|
74
163
|
- rubocop_pr.gemspec
|
75
|
-
homepage:
|
164
|
+
homepage: https://github.com/kvokka/rubocop_pr
|
76
165
|
licenses:
|
77
166
|
- MIT
|
78
167
|
metadata: {}
|
@@ -82,9 +171,9 @@ require_paths:
|
|
82
171
|
- lib
|
83
172
|
required_ruby_version: !ruby/object:Gem::Requirement
|
84
173
|
requirements:
|
85
|
-
- - "
|
174
|
+
- - "~>"
|
86
175
|
- !ruby/object:Gem::Version
|
87
|
-
version: '
|
176
|
+
version: '2.1'
|
88
177
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
178
|
requirements:
|
90
179
|
- - ">="
|
@@ -94,5 +183,5 @@ requirements: []
|
|
94
183
|
rubygems_version: 3.0.4
|
95
184
|
signing_key:
|
96
185
|
specification_version: 4
|
97
|
-
summary:
|
186
|
+
summary: Quick & clean Rubocop introduction.
|
98
187
|
test_files: []
|