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 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: []