policial 0.0.1
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 +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
|
+
[](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: []
|