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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c3a96d6d64a42663f02991fcebdc005ec36ec3a9ea79e40d862842d657461cf1
4
- data.tar.gz: da47ce8f606b3a5e6a8777b645cd782a525876de45a1ea113db218a653e6054f
3
+ metadata.gz: 8a991a0a8cb80ef2954672a3437172cd1a7bc84d4d3e95fc53cdff0a89c6c252
4
+ data.tar.gz: c834cbddaec6aeb63dc8d1d60adfa36ac9c07c7a010bdfad112fb3652c5eb2e6
5
5
  SHA512:
6
- metadata.gz: 5febfb8ac1b8e32068c656da27f8ecbe742b6b5a6cd7f0806ede01a74528f4b2ef3629b425fd3ed7b144b4dea9bdfe4163e7732d17fe8fa174acf10e4133bd79
7
- data.tar.gz: 8284fdd08bb79621a6fafa7dec967ba1ea55f6ce1ba0250a8187dcede4ac61d28b59a1f8951ce40dbcfcdcb2e4e6536812aef5bdfa7eccc3ddca3dce580b740a
6
+ metadata.gz: e59a54556c98590dae490a3c468060cb38b4469db01145e8696c7bf9273affc76924ee1e79972127624dc8bb2a0f5d70b2ed8815d571eba40c615cc761d46493
7
+ data.tar.gz: 5840cc106f27f682e74530c84182f6b75c2cd6ebc1b18a873bb6d8d3bca841842c743aa6c6c398469ca5445dcc00f35a8defb4612a550a73c2af52c22e7eb4cc
data/.gitignore CHANGED
@@ -9,3 +9,5 @@
9
9
 
10
10
  # rspec failure tracking
11
11
  .rspec_status
12
+ Gemfile.lock
13
+ *.gem
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
@@ -0,0 +1,14 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.5
3
+
4
+ Metrics/LineLength:
5
+ Max: 120
6
+
7
+ Metrics/BlockLength:
8
+ ExcludedMethods: ['describe', 'context']
9
+
10
+ Metrics/AbcSize:
11
+ Max: 20
12
+
13
+ Metrics/ClassLength:
14
+ Max: 150
data/.travis.yml CHANGED
@@ -3,5 +3,10 @@ sudo: false
3
3
  language: ruby
4
4
  cache: bundler
5
5
  rvm:
6
- - 2.6.3
7
- before_install: gem install bundler -v 1.17.3
6
+ - 2.5
7
+ - 2.6
8
+ - 2.7
9
+ before_install:
10
+ - sudo add-apt-repository ppa:cpick/hub -y
11
+ - sudo apt-get update
12
+ - sudo apt-get install hub
data/Gemfile CHANGED
@@ -1,6 +1,8 @@
1
- source "https://rubygems.org"
1
+ # frozen_string_literal: true
2
2
 
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
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
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/rubocop_pr`. To experiment with that code, run `bin/console` for an interactive prompt.
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
- TODO: Delete this and the text above, and describe your gem
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
- TODO: Write usage instructions here
26
-
27
- ## Development
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
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
59
+ #### Notes
30
60
 
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
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/[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](http://contributor-covenant.org) code of conduct.
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](https://opensource.org/licenses/MIT).
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](https://github.com/[USERNAME]/rubocop_pr/blob/master/CODE_OF_CONDUCT.md).
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
@@ -1,6 +1,8 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
3
5
 
4
6
  RSpec::Core::RakeTask.new(:spec)
5
7
 
6
- task :default => :spec
8
+ task default: :spec
data/bin/console CHANGED
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- require "bundler/setup"
4
- require "rubocop_pr"
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 "irb"
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
- require "rubocop_pr/version"
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
- # Your code goes here...
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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RubocopPr
2
- VERSION = "0.1.0"
4
+ VERSION = '1.0.0'.freeze
3
5
  end
data/rubocop_pr.gemspec CHANGED
@@ -1,32 +1,37 @@
1
+ # frozen_string_literal: true
1
2
 
2
- lib = File.expand_path("../lib", __FILE__)
3
+ lib = File.expand_path('lib', __dir__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require "rubocop_pr/version"
5
+ require 'rubocop_pr/version'
5
6
 
6
7
  Gem::Specification.new do |spec|
7
- spec.name = "rubocop_pr"
8
+ spec.name = 'rubocop_pr'
8
9
  spec.version = RubocopPr::VERSION
9
- spec.authors = ["kvokka"]
10
- spec.email = ["kvokka@yahoo.com"]
10
+ spec.authors = ['kvokka']
11
+ spec.email = ['kvokka@yahoo.com']
11
12
 
12
- spec.summary = %q{ e a short summary, because RubyGems requires one.}
13
- spec.description = %q{ e a longer description or delete this line.}
14
- spec.homepage = "http://valid.url"
15
- spec.license = "MIT"
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
- # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
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 = Dir.chdir(File.expand_path('..', __FILE__)) do
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 = "exe"
25
+ spec.bindir = 'exe'
26
26
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
- spec.require_paths = ["lib"]
27
+ spec.require_paths = ['lib']
28
28
 
29
- spec.add_development_dependency "bundler", "~> 1.17"
30
- spec.add_development_dependency "rake", "~> 10.0"
31
- spec.add_development_dependency "rspec", "~> 3.0"
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: 0.1.0
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: 2019-08-08 00:00:00.000000000 Z
11
+ date: 2021-02-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: bundler
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: '1.17'
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: '1.17'
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: '10.0'
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: '10.0'
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
- description: " e a longer description or delete this line."
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: http://valid.url
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: '0'
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.0.4
95
- signing_key:
171
+ rubygems_version: 3.1.4
172
+ signing_key:
96
173
  specification_version: 4
97
- summary: e a short summary, because RubyGems requires one.
174
+ summary: Quick & clean Rubocop introduction.
98
175
  test_files: []