policial 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +79 -0
- data/Rakefile +8 -0
- data/lib/policial.rb +28 -0
- data/lib/policial/accusation_policy.rb +34 -0
- data/lib/policial/commenter.rb +25 -0
- data/lib/policial/commit.rb +23 -0
- data/lib/policial/commit_file.rb +40 -0
- data/lib/policial/investigation.rb +35 -0
- data/lib/policial/line.rb +16 -0
- data/lib/policial/patch.rb +35 -0
- data/lib/policial/pull_request.rb +60 -0
- data/lib/policial/pull_request_event.rb +29 -0
- data/lib/policial/repo_config.rb +36 -0
- data/lib/policial/style_checker.rb +48 -0
- data/lib/policial/style_guides/base.rb +18 -0
- data/lib/policial/style_guides/ruby.rb +67 -0
- data/lib/policial/style_guides/unsupported.rb +10 -0
- data/lib/policial/unchanged_line.rb +15 -0
- data/lib/policial/version.rb +4 -0
- data/lib/policial/violation.rb +30 -0
- metadata +93 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f9ea96661ceb59f07846827daf7ccf1d9f1ed2c6
|
4
|
+
data.tar.gz: 26d33c00ee9d4dfa3e65196f3faa6d8c4bfad416
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 59ea217f976c38a00fb0a80bac2fd23c73f592622efcef1e8689db454ced0e54365da3e9a459f0b0a1a26d6e34ae5c4e5a4105d748f90ccb16e98a20b7e1bf8e
|
7
|
+
data.tar.gz: 58be1670722255f6886aae39685cf7357406e4b1e74d97b752752faa682574b8d5914bd233ad9c32f8683197e33e79e38220062faf4144deb34a85ccd729ddd0
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Volmer Soares
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
# Policial
|
2
|
+
|
3
|
+
[![Build Status](https://travis-ci.org/volmer/policial.svg)](https://travis-ci.org/volmer/policial)
|
4
|
+
|
5
|
+
*Policial* is a gem that investigates pull requests and accuses style guide
|
6
|
+
violations. It is based on thoughtbot's
|
7
|
+
[Hound project](https://github.com/thoughtbot/hound).
|
8
|
+
Currently it only investigates ruby code. You can setup your ruby code style
|
9
|
+
rules by defining a `.rubocop.yml` file in you repo. Please see
|
10
|
+
[RuboCop's README](https://github.com/bbatsov/rubocop).
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
Add this line to your application's Gemfile:
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
gem 'policial'
|
18
|
+
```
|
19
|
+
|
20
|
+
And then execute:
|
21
|
+
|
22
|
+
$ bundle
|
23
|
+
|
24
|
+
Or install it yourself as:
|
25
|
+
|
26
|
+
$ gem install policial
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
First, you need to set your GitHub credentials. For more information on
|
31
|
+
this, please check [Octokit README](https://github.com/octokit/octokit.rb).
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
Octokit.configure do |c|
|
35
|
+
c.access_tokein = 'mygithubtoken666'
|
36
|
+
end
|
37
|
+
```
|
38
|
+
|
39
|
+
You start with a pull request which Policial will run an investigation
|
40
|
+
against. You can setup a pull request manually:
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
pull_request = Policial::PullRequest.new(
|
44
|
+
repo: 'volmer/my_repo',
|
45
|
+
number: 3,
|
46
|
+
head_sha: 'headsha'
|
47
|
+
)
|
48
|
+
```
|
49
|
+
|
50
|
+
Or you can extract a pull request from a
|
51
|
+
[GitHub `pull_request` webhook](https://developer.github.com/webhooks):
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
event = Policial::PullRequestEvent.new(webhook_payload)
|
55
|
+
pull_request = event.pull_request
|
56
|
+
```
|
57
|
+
|
58
|
+
Now you can start an investigation:
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
investigation = Policial::Investigation.new(pull_request)
|
62
|
+
|
63
|
+
# Let's investigate this pull request...
|
64
|
+
investigation.run
|
65
|
+
|
66
|
+
# Want to know the violations found?
|
67
|
+
investigation.violations
|
68
|
+
|
69
|
+
# Hurry, post comments about those violations on the pull request!
|
70
|
+
investigation.accuse
|
71
|
+
```
|
72
|
+
|
73
|
+
## Contributing
|
74
|
+
|
75
|
+
1. Fork it ( https://github.com/volmer/policial/fork )
|
76
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
77
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
78
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
79
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/lib/policial.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'octokit'
|
2
|
+
|
3
|
+
require 'policial/accusation_policy'
|
4
|
+
require 'policial/commenter'
|
5
|
+
require 'policial/commit'
|
6
|
+
require 'policial/commit_file'
|
7
|
+
require 'policial/investigation'
|
8
|
+
require 'policial/line'
|
9
|
+
require 'policial/patch'
|
10
|
+
require 'policial/pull_request'
|
11
|
+
require 'policial/pull_request_event'
|
12
|
+
require 'policial/repo_config'
|
13
|
+
require 'policial/style_checker'
|
14
|
+
require 'policial/style_guides/base'
|
15
|
+
require 'policial/style_guides/ruby'
|
16
|
+
require 'policial/style_guides/unsupported'
|
17
|
+
require 'policial/unchanged_line'
|
18
|
+
require 'policial/version'
|
19
|
+
require 'policial/violation'
|
20
|
+
|
21
|
+
# Public: The global gem module. It exposes some module attribute accessors
|
22
|
+
# so you can configure GitHub credentials, enable/disable style guides
|
23
|
+
# and more.
|
24
|
+
module Policial
|
25
|
+
STYLE_GUIDES = [Policial::StyleGuides::Ruby]
|
26
|
+
|
27
|
+
Octokit.auto_paginate = true
|
28
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Policial
|
2
|
+
# Public: Checks if a given pull request should be investigated or not.
|
3
|
+
class AccusationPolicy
|
4
|
+
def initialize(pull_request)
|
5
|
+
@pull_request = pull_request
|
6
|
+
end
|
7
|
+
|
8
|
+
def allowed_for?(violation)
|
9
|
+
unreported_violation_messages(violation).any?
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def unreported_violation_messages(violation)
|
15
|
+
violation.messages - existing_violation_messages(violation)
|
16
|
+
end
|
17
|
+
|
18
|
+
def existing_violation_messages(violation)
|
19
|
+
previous_comments_on_line(violation).map(&:body)
|
20
|
+
.flat_map { |body| body.split('<br>') }
|
21
|
+
end
|
22
|
+
|
23
|
+
def previous_comments_on_line(violation)
|
24
|
+
existing_comments.select do |comment|
|
25
|
+
comment.path == violation.filename &&
|
26
|
+
comment.original_position == violation.patch_position
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def existing_comments
|
31
|
+
@existing_comments ||= @pull_request.comments
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Policial
|
2
|
+
# Public: Comment violations on pull request.
|
3
|
+
class Commenter
|
4
|
+
def initialize(pull_request)
|
5
|
+
@pull_request = pull_request
|
6
|
+
end
|
7
|
+
|
8
|
+
def comment_violation(violation)
|
9
|
+
Octokit.create_pull_request_comment(
|
10
|
+
@pull_request.repo,
|
11
|
+
@pull_request.number,
|
12
|
+
comment_body(violation),
|
13
|
+
@pull_request.head_commit.sha,
|
14
|
+
violation.filename,
|
15
|
+
violation.line_number
|
16
|
+
)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def comment_body(violation)
|
22
|
+
violation.messages.join('<br/>')
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Policial
|
2
|
+
# Public: A Commit in a GitHub repo.
|
3
|
+
class Commit
|
4
|
+
attr_reader :repo, :sha
|
5
|
+
|
6
|
+
def initialize(repo, sha)
|
7
|
+
@repo = repo
|
8
|
+
@sha = sha
|
9
|
+
end
|
10
|
+
|
11
|
+
def file_content(filename)
|
12
|
+
contents = Octokit.contents(@repo, path: filename, ref: @sha)
|
13
|
+
|
14
|
+
if contents && contents.content
|
15
|
+
Base64.decode64(contents.content).force_encoding('UTF-8')
|
16
|
+
else
|
17
|
+
''
|
18
|
+
end
|
19
|
+
rescue Octokit::NotFound
|
20
|
+
''
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Policial
|
2
|
+
# Public: A file in a commit.
|
3
|
+
class CommitFile
|
4
|
+
attr_reader :commit
|
5
|
+
|
6
|
+
def initialize(file, commit)
|
7
|
+
@file = file
|
8
|
+
@commit = commit
|
9
|
+
end
|
10
|
+
|
11
|
+
def filename
|
12
|
+
@file.filename
|
13
|
+
end
|
14
|
+
|
15
|
+
def content
|
16
|
+
@content ||= begin
|
17
|
+
@commit.file_content(filename) unless removed?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def removed?
|
22
|
+
@file.status == 'removed'
|
23
|
+
end
|
24
|
+
|
25
|
+
def line_at(line_number)
|
26
|
+
changed_lines.detect { |line| line.number == line_number } ||
|
27
|
+
UnchangedLine.new
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def changed_lines
|
33
|
+
@changed_lines ||= patch.changed_lines
|
34
|
+
end
|
35
|
+
|
36
|
+
def patch
|
37
|
+
Patch.new(@file.patch)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Policial
|
2
|
+
# Public: Starting with unparsed data coming from a pull request event,
|
3
|
+
# it checks all changes introduced looking for style guide violations. It
|
4
|
+
# also accuse all present violations through comments on all relevant lines
|
5
|
+
# in the pull request.
|
6
|
+
class Investigation
|
7
|
+
attr_accessor :violations, :pull_request
|
8
|
+
|
9
|
+
def initialize(pull_request)
|
10
|
+
@pull_request = pull_request
|
11
|
+
end
|
12
|
+
|
13
|
+
def run
|
14
|
+
@violations ||= StyleChecker.new(@pull_request).violations
|
15
|
+
end
|
16
|
+
|
17
|
+
def accuse
|
18
|
+
return if @violations.blank?
|
19
|
+
|
20
|
+
commenter = Commenter.new(@pull_request)
|
21
|
+
|
22
|
+
@violations.each do |violation|
|
23
|
+
if accusation_policy.allowed_for?(violation)
|
24
|
+
commenter.comment_violation(violation)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def accusation_policy
|
32
|
+
@accusation_policy ||= AccusationPolicy.new(@pull_request)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Policial
|
2
|
+
# Public: a changed line in a commit file.
|
3
|
+
class Line
|
4
|
+
attr_reader :number, :patch_position
|
5
|
+
|
6
|
+
def initialize(number, content, patch_position)
|
7
|
+
@number = number
|
8
|
+
@content = content
|
9
|
+
@patch_position = patch_position
|
10
|
+
end
|
11
|
+
|
12
|
+
def changed?
|
13
|
+
true
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Policial
|
2
|
+
# Public: a chunk of changed code in a commit file.
|
3
|
+
class Patch
|
4
|
+
RANGE_INFORMATION_LINE = /^@@ .+\+(?<line_number>\d+),/
|
5
|
+
MODIFIED_LINE = /^\+(?!\+|\+)/
|
6
|
+
NOT_REMOVED_LINE = /^[^-]/
|
7
|
+
|
8
|
+
def initialize(body)
|
9
|
+
@body = body || ''
|
10
|
+
end
|
11
|
+
|
12
|
+
def changed_lines
|
13
|
+
line_number = 0
|
14
|
+
|
15
|
+
@body.lines.each_with_index.with_object([]) do |(line, patch_pos), lines|
|
16
|
+
line_number =
|
17
|
+
parse_line(line, line_number, patch_pos, lines) || line_number
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def parse_line(line_content, line_number, patch_position, lines)
|
24
|
+
case line_content
|
25
|
+
when RANGE_INFORMATION_LINE
|
26
|
+
Regexp.last_match[:line_number].to_i
|
27
|
+
when MODIFIED_LINE
|
28
|
+
lines << Line.new(line_number, line_content, patch_position)
|
29
|
+
line_number + 1
|
30
|
+
when NOT_REMOVED_LINE
|
31
|
+
line_number + 1
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Policial
|
2
|
+
# Public: A GibHub Pull Request.
|
3
|
+
class PullRequest
|
4
|
+
attr_reader :repo, :number, :user
|
5
|
+
|
6
|
+
def initialize(repo:, number:, head_sha:, user: nil)
|
7
|
+
@repo = repo
|
8
|
+
@number = number
|
9
|
+
@head_sha = head_sha
|
10
|
+
@user = user
|
11
|
+
end
|
12
|
+
|
13
|
+
def comments
|
14
|
+
@comments ||= fetch_comments
|
15
|
+
end
|
16
|
+
|
17
|
+
def files
|
18
|
+
@files ||= Octokit.pull_request_files(@repo, @number).map do |file|
|
19
|
+
build_commit_file(file)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def head_commit
|
24
|
+
@head_commit ||= Commit.new(@repo, @head_sha)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def build_commit_file(file)
|
30
|
+
CommitFile.new(file, head_commit)
|
31
|
+
end
|
32
|
+
|
33
|
+
def fetch_comments
|
34
|
+
paginate do |page|
|
35
|
+
Octokit.pull_request_comments(
|
36
|
+
@repo,
|
37
|
+
@number,
|
38
|
+
page: page
|
39
|
+
)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def paginate
|
46
|
+
page, results, all_pages_fetched = 1, [], false
|
47
|
+
|
48
|
+
until all_pages_fetched
|
49
|
+
if (page_results = yield(page)).empty?
|
50
|
+
all_pages_fetched = true
|
51
|
+
else
|
52
|
+
results += page_results
|
53
|
+
page += 1
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
results
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Policial
|
4
|
+
# Public: Parses a pull request event payload.
|
5
|
+
class PullRequestEvent
|
6
|
+
attr_reader :payload
|
7
|
+
|
8
|
+
def initialize(payload)
|
9
|
+
@payload = payload
|
10
|
+
end
|
11
|
+
|
12
|
+
def pull_request
|
13
|
+
@pull_request ||= PullRequest.new(
|
14
|
+
repo: @payload['repository']['full_name'],
|
15
|
+
number: @payload['number'],
|
16
|
+
head_sha: @payload['pull_request']['head']['sha'],
|
17
|
+
user: @payload['pull_request']['user']['login']
|
18
|
+
)
|
19
|
+
rescue NoMethodError
|
20
|
+
nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def should_investigate?
|
24
|
+
!pull_request.nil? && (
|
25
|
+
@payload['action'] == 'opened' || @payload['action'] == 'synchronize'
|
26
|
+
)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Policial
|
2
|
+
# Public: Load and parse config files from GitHub repo.
|
3
|
+
class RepoConfig
|
4
|
+
def initialize(commit)
|
5
|
+
@commit = commit
|
6
|
+
end
|
7
|
+
|
8
|
+
def enabled_for?(style_guide_class)
|
9
|
+
Policial::STYLE_GUIDES.include?(style_guide_class)
|
10
|
+
end
|
11
|
+
|
12
|
+
def for(style_guide_class)
|
13
|
+
config_file = style_guide_class.config_file
|
14
|
+
|
15
|
+
if config_file
|
16
|
+
load_file(config_file)
|
17
|
+
else
|
18
|
+
{}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def load_file(file)
|
25
|
+
config_file_content = @commit.file_content(file)
|
26
|
+
|
27
|
+
parse_yaml(config_file_content) || {}
|
28
|
+
end
|
29
|
+
|
30
|
+
def parse_yaml(content)
|
31
|
+
YAML.load(content)
|
32
|
+
rescue Psych::SyntaxError
|
33
|
+
{}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Policial
|
2
|
+
# Public: Filters files to reviewable subset, builds style guide based on file
|
3
|
+
# extension and delegates to style guide for line violations.
|
4
|
+
class StyleChecker
|
5
|
+
def initialize(pull_request)
|
6
|
+
@pull_request = pull_request
|
7
|
+
@style_guides = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def violations
|
11
|
+
@violations ||= violations_in_checked_files.select(&:on_changed_line?)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
attr_reader :pull_request, :style_guides
|
17
|
+
|
18
|
+
def violations_in_checked_files
|
19
|
+
files_to_check.flat_map do |file|
|
20
|
+
style_guide(file.filename).violations_in_file(file)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def files_to_check
|
25
|
+
pull_request.files.reject(&:removed?).select do |file|
|
26
|
+
style_guide(file.filename).enabled?
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def style_guide(filename)
|
31
|
+
style_guide_class = style_guide_class(filename)
|
32
|
+
style_guides[style_guide_class] ||= style_guide_class.new(config)
|
33
|
+
end
|
34
|
+
|
35
|
+
def style_guide_class(filename)
|
36
|
+
case filename
|
37
|
+
when /.+\.rb\z/
|
38
|
+
StyleGuides::Ruby
|
39
|
+
else
|
40
|
+
StyleGuides::Unsupported
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def config
|
45
|
+
@config ||= RepoConfig.new(pull_request.head_commit)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Policial
|
2
|
+
module StyleGuides
|
3
|
+
# Public: Base to contain common style guide logic.
|
4
|
+
class Base
|
5
|
+
def initialize(repo_config)
|
6
|
+
@repo_config = repo_config
|
7
|
+
end
|
8
|
+
|
9
|
+
def enabled?
|
10
|
+
@repo_config.enabled_for?(self.class)
|
11
|
+
end
|
12
|
+
|
13
|
+
def violations_in_file(_file)
|
14
|
+
fail NotImplementedError, "must implement ##{__method__}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'rubocop'
|
2
|
+
|
3
|
+
module Policial
|
4
|
+
module StyleGuides
|
5
|
+
# Public: Determine Ruby style guide violations per-line.
|
6
|
+
class Ruby < Base
|
7
|
+
class << self
|
8
|
+
attr_writer :config_file
|
9
|
+
|
10
|
+
def config_file
|
11
|
+
@config_file || RuboCop::ConfigLoader::DOTFILE
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def violations_in_file(file)
|
16
|
+
if config.file_to_exclude?(file.filename)
|
17
|
+
[]
|
18
|
+
else
|
19
|
+
offenses = team.inspect_file(parsed_source(file))
|
20
|
+
build_violations(offenses, file)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def team
|
27
|
+
RuboCop::Cop::Team.new(RuboCop::Cop::Cop.all, config, rubocop_options)
|
28
|
+
end
|
29
|
+
|
30
|
+
def parsed_source(file)
|
31
|
+
RuboCop::ProcessedSource.new(file.content, file.filename)
|
32
|
+
end
|
33
|
+
|
34
|
+
def config
|
35
|
+
@config ||= RuboCop::ConfigLoader.merge_with_default(custom_config, '')
|
36
|
+
end
|
37
|
+
|
38
|
+
def custom_config
|
39
|
+
custom = @repo_config.for(self.class)
|
40
|
+
|
41
|
+
if custom.is_a?(Hash)
|
42
|
+
RuboCop::Config.new(custom, '').tap do |config|
|
43
|
+
config.add_missing_namespaces
|
44
|
+
config.make_excludes_absolute
|
45
|
+
end
|
46
|
+
else
|
47
|
+
RuboCop::Config.new
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def rubocop_options
|
52
|
+
{ debug: true } if config['ShowCopNames']
|
53
|
+
end
|
54
|
+
|
55
|
+
def build_violations(offenses, file)
|
56
|
+
offenses.each_with_object({}) do |offense, violations|
|
57
|
+
if violations[offense.line]
|
58
|
+
violations[offense.line].add_messages([offense.message])
|
59
|
+
else
|
60
|
+
violations[offense.line] =
|
61
|
+
Violation.new(file, offense.line, offense.message)
|
62
|
+
end
|
63
|
+
end.values
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Policial
|
2
|
+
# Public: Hold file, line, and violation message values. Built by style
|
3
|
+
# guides.
|
4
|
+
class Violation
|
5
|
+
attr_reader :line_number, :filename
|
6
|
+
|
7
|
+
def initialize(file, line_number, message)
|
8
|
+
@filename = file.filename
|
9
|
+
@line = file.line_at(line_number)
|
10
|
+
@line_number = line_number
|
11
|
+
@messages = [message]
|
12
|
+
end
|
13
|
+
|
14
|
+
def add_messages(messages)
|
15
|
+
@messages += messages
|
16
|
+
end
|
17
|
+
|
18
|
+
def messages
|
19
|
+
@messages.uniq
|
20
|
+
end
|
21
|
+
|
22
|
+
def patch_position
|
23
|
+
@line.patch_position
|
24
|
+
end
|
25
|
+
|
26
|
+
def on_changed_line?
|
27
|
+
@line.changed?
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
metadata
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: policial
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Volmer Soares
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-12-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: octokit
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.7'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rubocop
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.2'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.2'
|
41
|
+
description: Review pull requests for style guide violations.
|
42
|
+
email:
|
43
|
+
- volmerius@gmail.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- LICENSE.txt
|
49
|
+
- README.md
|
50
|
+
- Rakefile
|
51
|
+
- lib/policial.rb
|
52
|
+
- lib/policial/accusation_policy.rb
|
53
|
+
- lib/policial/commenter.rb
|
54
|
+
- lib/policial/commit.rb
|
55
|
+
- lib/policial/commit_file.rb
|
56
|
+
- lib/policial/investigation.rb
|
57
|
+
- lib/policial/line.rb
|
58
|
+
- lib/policial/patch.rb
|
59
|
+
- lib/policial/pull_request.rb
|
60
|
+
- lib/policial/pull_request_event.rb
|
61
|
+
- lib/policial/repo_config.rb
|
62
|
+
- lib/policial/style_checker.rb
|
63
|
+
- lib/policial/style_guides/base.rb
|
64
|
+
- lib/policial/style_guides/ruby.rb
|
65
|
+
- lib/policial/style_guides/unsupported.rb
|
66
|
+
- lib/policial/unchanged_line.rb
|
67
|
+
- lib/policial/version.rb
|
68
|
+
- lib/policial/violation.rb
|
69
|
+
homepage: https://github.com/volmer/policial
|
70
|
+
licenses:
|
71
|
+
- MIT
|
72
|
+
metadata: {}
|
73
|
+
post_install_message:
|
74
|
+
rdoc_options: []
|
75
|
+
require_paths:
|
76
|
+
- lib
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
requirements: []
|
88
|
+
rubyforge_project:
|
89
|
+
rubygems_version: 2.4.5
|
90
|
+
signing_key:
|
91
|
+
specification_version: 4
|
92
|
+
summary: Review pull requests for style guide violations
|
93
|
+
test_files: []
|