gergich 0.1.3 → 0.1.4
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 +4 -4
- data/README.md +6 -0
- data/bin/gergich +1 -1
- data/bin/master_bouncer +1 -1
- data/bin/run_tests.sh +4 -0
- data/lib/gergich.rb +46 -18
- data/lib/gergich/capture/androidlint_capture.rb +40 -0
- data/lib/gergich/capture/swiftlint_capture.rb +29 -0
- data/spec/gergich/capture_spec.rb +82 -0
- data/spec/gergich_spec.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9d8fc46682dc58246a154bd7f4d9861c90ae7e75
|
4
|
+
data.tar.gz: 06842c81c83193794006287f4453cc51a32ad126
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 96245df392240a42e96f860d2541c8388d86b1a325dbc9193a1f491796de21d1df097e1ef4fe6a185950570a919b6ebe803ee068e6418ee4310cac847ff9580d
|
7
|
+
data.tar.gz: c47545b246cfb3416b4fecec3341d993f3a1bf4622270a2e0ede3b03338deb80765a0e52b51ec3c2119ec1be6d97c662b649d88a0b31966d8b0af9a6cfcef696
|
data/README.md
CHANGED
@@ -45,6 +45,12 @@ Additionally, Gergich needs to know where your Gerrit installation
|
|
45
45
|
lives, so be sure to set `GERRIT_BASE_URL` (e.g.
|
46
46
|
`https://gerrit.example.com`) or `GERRIT_HOST` (e.g. `gerrit.example.com`).
|
47
47
|
|
48
|
+
Lastly, if you have no .git directory in CI land (say if you are building
|
49
|
+
in docker and want to keep your images small), you also need to set
|
50
|
+
`GERRIT_CHANGE_ID` and `GERRIT_PATCHSET_REVISION`. If you use Jenkins and
|
51
|
+
the gerrit-trigger plugin, typcially all `GERRIT_*` vars will already be
|
52
|
+
set, it's just a matter of plumbing them down to docker.
|
53
|
+
|
48
54
|
## Usage
|
49
55
|
|
50
56
|
Run `gergich help` for detailed information about all supported commands.
|
data/bin/gergich
CHANGED
data/bin/master_bouncer
CHANGED
data/bin/run_tests.sh
CHANGED
@@ -39,6 +39,10 @@ run_command bin/gergich citest
|
|
39
39
|
run_command bin/master_bouncer check
|
40
40
|
DRY_RUN=1 run_command bin/master_bouncer check_all
|
41
41
|
|
42
|
+
# ensure gergich works without .git directories
|
43
|
+
rm -rf .git
|
44
|
+
run_command bin/gergich status
|
45
|
+
|
42
46
|
run_command bin/check_coverage
|
43
47
|
|
44
48
|
if [[ $GEMNASIUM_TOKEN && $GEMNASIUM_ENABLED ]]; then
|
data/lib/gergich.rb
CHANGED
@@ -2,6 +2,7 @@ require "sqlite3"
|
|
2
2
|
require "json"
|
3
3
|
require "fileutils"
|
4
4
|
require "httparty"
|
5
|
+
require "base64"
|
5
6
|
|
6
7
|
GERGICH_REVIEW_LABEL = ENV.fetch("GERGICH_REVIEW_LABEL", "Code-Review")
|
7
8
|
GERGICH_USER = ENV.fetch("GERGICH_USER", "gergich")
|
@@ -10,6 +11,12 @@ GERGICH_GIT_PATH = ENV.fetch("GERGICH_GIT_PATH", ".")
|
|
10
11
|
GergichError = Class.new(StandardError)
|
11
12
|
|
12
13
|
module Gergich
|
14
|
+
def self.use_git?
|
15
|
+
Dir.chdir(GERGICH_GIT_PATH) do
|
16
|
+
system "git rev-parse --show-toplevel >/dev/null 2>&1"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
13
20
|
def self.git(args)
|
14
21
|
Dir.chdir(GERGICH_GIT_PATH) do
|
15
22
|
`git #{args} 2>/dev/null`
|
@@ -26,14 +33,30 @@ module Gergich
|
|
26
33
|
|
27
34
|
def info
|
28
35
|
@info ||= begin
|
29
|
-
|
30
|
-
|
36
|
+
if Gergich.use_git?
|
37
|
+
output = Gergich.git("log -1 #{ref}")
|
38
|
+
/\Acommit (?<revision_id>[0-9a-f]+).*^\s*Change-Id: (?<change_id>\w+)/m =~ output
|
39
|
+
else
|
40
|
+
revision_id = ENV["GERRIT_PATCHSET_REVISION"] \
|
41
|
+
|| raise(GergichError, "No .git directory, and GERRIT_PATCHSET_REVISION not set")
|
42
|
+
change_id = ENV["GERRIT_CHANGE_ID"] \
|
43
|
+
|| raise(GergichError, "No .git directory, and GERRIT_CHANGE_ID not set")
|
44
|
+
end
|
31
45
|
{ revision_id: revision_id, change_id: change_id }
|
32
46
|
end
|
33
47
|
end
|
34
48
|
|
35
49
|
def files
|
36
|
-
@files ||=
|
50
|
+
@files ||= begin
|
51
|
+
if Gergich.use_git?
|
52
|
+
Gergich.git("diff-tree --no-commit-id --name-only -r #{ref}").split
|
53
|
+
else
|
54
|
+
raw = API.get("/changes/#{change_id}/revisions/#{revision_id}/patch", { raw: true })
|
55
|
+
Base64.decode64(raw)
|
56
|
+
.scan(%r{^diff --git a/.*? b/(.*?)$})
|
57
|
+
.flatten
|
58
|
+
end
|
59
|
+
end
|
37
60
|
end
|
38
61
|
|
39
62
|
def revision_id
|
@@ -100,6 +123,8 @@ module Gergich
|
|
100
123
|
|
101
124
|
puts "ChangeId: #{commit.change_id}"
|
102
125
|
puts "Revision: #{commit.revision_id}"
|
126
|
+
puts "Files:"
|
127
|
+
puts " #{commit.files.join("\n ")}"
|
103
128
|
|
104
129
|
puts
|
105
130
|
review_info[:labels].each do |name, score|
|
@@ -174,27 +199,25 @@ module Gergich
|
|
174
199
|
|
175
200
|
class API
|
176
201
|
class << self
|
177
|
-
def get(url)
|
178
|
-
perform(:get, url)
|
202
|
+
def get(url, options = {})
|
203
|
+
perform(:get, url, options)
|
179
204
|
end
|
180
205
|
|
181
|
-
def post(url, body)
|
182
|
-
perform(:post, url, body)
|
206
|
+
def post(url, body, options = {})
|
207
|
+
perform(:post, url, options.merge({ body: body }))
|
183
208
|
end
|
184
209
|
|
185
|
-
def put(url, body)
|
186
|
-
perform(:put, url, body)
|
210
|
+
def put(url, body, options = {})
|
211
|
+
perform(:put, url, options.merge({ body: body }))
|
187
212
|
end
|
188
213
|
|
189
214
|
private
|
190
215
|
|
191
|
-
def perform(method, url,
|
192
|
-
options =
|
193
|
-
if body
|
194
|
-
options[:headers] = { "Content-Type" => "application/json" }
|
195
|
-
options[:body] = body
|
196
|
-
end
|
216
|
+
def perform(method, url, options)
|
217
|
+
options = prepare_options(options)
|
197
218
|
ret = HTTParty.send(method, url, options).body
|
219
|
+
return ret if options[:raw]
|
220
|
+
|
198
221
|
if ret.sub!(/\A\)\]\}'\n/, "") && ret =~ /\A("|\[|\{)/
|
199
222
|
JSON.parse("[#{ret}]")[0] # array hack so we can parse a string literal
|
200
223
|
elsif ret =~ /Not Found: (?<change_id>.*)/
|
@@ -216,14 +239,19 @@ module Gergich
|
|
216
239
|
raise(GergichError, "need to set GERRIT_BASE_URL or GERRIT_HOST")
|
217
240
|
end
|
218
241
|
|
219
|
-
def
|
220
|
-
{
|
242
|
+
def prepare_options(options)
|
243
|
+
options = {
|
221
244
|
base_uri: base_uri + "/a",
|
222
245
|
digest_auth: {
|
223
246
|
username: GERGICH_USER,
|
224
247
|
password: ENV.fetch("GERGICH_KEY")
|
225
248
|
}
|
226
|
-
}
|
249
|
+
}.merge(options)
|
250
|
+
if options[:body]
|
251
|
+
options[:headers] ||= {}
|
252
|
+
options[:headers]["Content-Type"] ||= "application/json"
|
253
|
+
end
|
254
|
+
options
|
227
255
|
end
|
228
256
|
end
|
229
257
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Gergich
|
2
|
+
module Capture
|
3
|
+
class AndroidlintCapture < BaseCapture
|
4
|
+
# See http://tools.android.com/tips/lint-checks
|
5
|
+
SEVERITY_MAP = {
|
6
|
+
"Warning" => "warn",
|
7
|
+
"Error" => "error",
|
8
|
+
"Fatal" => "error"
|
9
|
+
}.freeze
|
10
|
+
|
11
|
+
def run(output)
|
12
|
+
# rubocop:disable Metrics/LineLength
|
13
|
+
#
|
14
|
+
# Example:
|
15
|
+
# /path/to/some.xml:27: Warning: Consider adding android:drawableStart="@drawable/a_media" to better support right-to-left layouts [RtlHardcoded]
|
16
|
+
# android:drawableLeft="@drawable/ic_cv_media"/>
|
17
|
+
# ~~~~~~~~~~~~~~~~~~~~
|
18
|
+
#
|
19
|
+
# /path/to/AndroidManifest.xml: Warning: The project references RTL attributes, but does not explicitly enable or disable RTL support with android:supportsRtl in the manifest [RtlEnabled]
|
20
|
+
#
|
21
|
+
# /path/to/library/0.0.2: Error: No .class files were found in project "0.0.2", so none of the classfile based checks could be run. Does the project need to be built first? [LintError]
|
22
|
+
#
|
23
|
+
# /path/to/values.xml:5: Warning: For language "fr" (French) the following quantities are not relevant: few, zero [UnusedQuantity]
|
24
|
+
# <plurals name="number">
|
25
|
+
# ^
|
26
|
+
pattern = /
|
27
|
+
^([^:\n]+):(\d+)?:?\s(\w+):\s(.*?)\n
|
28
|
+
([^\n]+\n
|
29
|
+
[\s~\^]+\n)?
|
30
|
+
/mx
|
31
|
+
|
32
|
+
output.scan(pattern).map { |file, line, severity, error, context|
|
33
|
+
context = "\n\n" + context if context
|
34
|
+
{ path: file, message: "[androidlint] #{error}#{context}".strip,
|
35
|
+
position: (line || 0).to_i, severity: SEVERITY_MAP[severity] }
|
36
|
+
}.compact
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Gergich
|
2
|
+
module Capture
|
3
|
+
class SwiftlintCapture < BaseCapture
|
4
|
+
# See SeverityLevelsConfiguration.swift
|
5
|
+
SEVERITY_MAP = {
|
6
|
+
"error" => "error", # console description
|
7
|
+
"warning" => "warn",
|
8
|
+
"w" => "warn", # short console description
|
9
|
+
"w/e" => "error"
|
10
|
+
}.freeze
|
11
|
+
|
12
|
+
def run(output)
|
13
|
+
# rubocop:disable Metrics/LineLength
|
14
|
+
#
|
15
|
+
# Example:
|
16
|
+
# /path/to/My.swift:13:22: warning: Colon Violation: Colons should be next to the identifier when specifying a type. (colon)
|
17
|
+
# /path/to/Fail.swift:80: warning: Line Length Violation: Line should be 100 characters or less: currently 108 characters (line_length)
|
18
|
+
pattern = /
|
19
|
+
^([^:\n]+):(\d+)(?::\d+)?:\s(\w+):\s(.*?)\n
|
20
|
+
/mx
|
21
|
+
|
22
|
+
output.scan(pattern).map { |file, line, severity, error, _context|
|
23
|
+
{ path: file, message: "[swiftlint] #{error}",
|
24
|
+
position: line.to_i, severity: SEVERITY_MAP[severity] }
|
25
|
+
}.compact
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require_relative "../../lib/gergich/capture"
|
2
|
+
require_relative "../../lib/gergich"
|
2
3
|
|
3
4
|
RSpec.describe Gergich::Capture do
|
4
5
|
let!(:draft) { double }
|
@@ -39,6 +40,87 @@ OUTPUT
|
|
39
40
|
end
|
40
41
|
end
|
41
42
|
|
43
|
+
# rubocop:disable Metrics/LineLength
|
44
|
+
context "swiftlint" do
|
45
|
+
it "should catch errors" do
|
46
|
+
colon_violation = "Colon Violation: Colons should be next to the identifier when specifying a type. (colon)"
|
47
|
+
line_length_violation = "Line Length Violation: Line should be 100 characters or less: currently 129 characters (line_length)"
|
48
|
+
force_cast_violation = "Force Cast Violation: Force casts should be avoided. (force_cast)"
|
49
|
+
allow(described_class).to receive(:run_command).and_return([0, <<-OUTPUT])
|
50
|
+
/path/to/My.swift:13:22: warning: #{colon_violation}
|
51
|
+
/path/to/Fail.swift:76: warning: #{line_length_violation}
|
52
|
+
/path/to/Cast.swift:15:9: error: #{force_cast_violation}
|
53
|
+
OUTPUT
|
54
|
+
expect(draft).to receive(:add_comment).with(
|
55
|
+
"/path/to/My.swift",
|
56
|
+
13,
|
57
|
+
"[swiftlint] #{colon_violation}",
|
58
|
+
"warn"
|
59
|
+
)
|
60
|
+
expect(draft).to receive(:add_comment).with(
|
61
|
+
"/path/to/Fail.swift",
|
62
|
+
76,
|
63
|
+
"[swiftlint] #{line_length_violation}",
|
64
|
+
"warn"
|
65
|
+
)
|
66
|
+
expect(draft).to receive(:add_comment).with(
|
67
|
+
"/path/to/Cast.swift",
|
68
|
+
15,
|
69
|
+
"[swiftlint] #{force_cast_violation}",
|
70
|
+
"error"
|
71
|
+
)
|
72
|
+
described_class.run("swiftlint", "false")
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context "androidlint" do
|
77
|
+
it "should catch errors" do
|
78
|
+
rtl_hardcoded = 'Consider adding android:drawableStart="@drawable/a_media" to better support right-to-left layouts [RtlHardcoded]'
|
79
|
+
rtl_enabled = "The project references RTL attributes, but does not explicitly enable or disable RTL support with android:supportsRtl in the manifest [RtlEnabled]"
|
80
|
+
lint_error = 'No .class files were found in project "0.0.2", so none of the classfile based checks could be run. Does the project need to be built first? [LintError]'
|
81
|
+
unused_quantity = 'For language "fr" (French) the following quantities are not relevant: few, zero [UnusedQuantity]'
|
82
|
+
allow(described_class).to receive(:run_command).and_return([0, <<-OUTPUT])
|
83
|
+
/path/to/some.xml:27: Warning: #{rtl_hardcoded}
|
84
|
+
android:drawableLeft="@drawable/ic_cv_media"/>
|
85
|
+
~~~~~~~~~~~~~~~~~~~~
|
86
|
+
|
87
|
+
/path/to/AndroidManifest.xml: Warning: #{rtl_enabled}
|
88
|
+
|
89
|
+
/path/to/library/0.0.2: Error: #{lint_error}
|
90
|
+
|
91
|
+
/path/to/values.xml:5: Warning: #{unused_quantity}
|
92
|
+
<plurals name="number">
|
93
|
+
^
|
94
|
+
|
95
|
+
OUTPUT
|
96
|
+
expect(draft).to receive(:add_comment).with(
|
97
|
+
"/path/to/some.xml",
|
98
|
+
27,
|
99
|
+
"[androidlint] #{rtl_hardcoded}\n\n android:drawableLeft=\"@drawable/ic_cv_media\"/>\n ~~~~~~~~~~~~~~~~~~~~",
|
100
|
+
"warn"
|
101
|
+
)
|
102
|
+
expect(draft).to receive(:add_comment).with(
|
103
|
+
"/path/to/AndroidManifest.xml",
|
104
|
+
0,
|
105
|
+
"[androidlint] #{rtl_enabled}",
|
106
|
+
"warn"
|
107
|
+
)
|
108
|
+
expect(draft).to receive(:add_comment).with(
|
109
|
+
"/path/to/library/0.0.2",
|
110
|
+
0,
|
111
|
+
"[androidlint] #{lint_error}",
|
112
|
+
"error"
|
113
|
+
)
|
114
|
+
expect(draft).to receive(:add_comment).with(
|
115
|
+
"/path/to/values.xml",
|
116
|
+
5,
|
117
|
+
"[androidlint] #{unused_quantity}\n\n <plurals name=\"number\">\n ^",
|
118
|
+
"warn"
|
119
|
+
)
|
120
|
+
described_class.run("androidlint", "false")
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
42
124
|
context "eslint" do
|
43
125
|
it "should catch errors" do
|
44
126
|
allow(described_class).to receive(:run_command).and_return([0, <<-OUTPUT])
|
data/spec/gergich_spec.rb
CHANGED
@@ -5,7 +5,7 @@ RSpec.describe Gergich::API do
|
|
5
5
|
|
6
6
|
before :each do
|
7
7
|
allow(HTTParty).to receive(:send).and_return(result)
|
8
|
-
allow(described_class).to receive(:
|
8
|
+
allow(described_class).to receive(:prepare_options).and_return({})
|
9
9
|
end
|
10
10
|
|
11
11
|
it "provides helpful error when Change-Id not found" do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gergich
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jon Jensen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-07-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sqlite3
|
@@ -55,9 +55,11 @@ files:
|
|
55
55
|
- bin/run_tests.sh
|
56
56
|
- lib/gergich.rb
|
57
57
|
- lib/gergich/capture.rb
|
58
|
+
- lib/gergich/capture/androidlint_capture.rb
|
58
59
|
- lib/gergich/capture/eslint_capture.rb
|
59
60
|
- lib/gergich/capture/i18nliner_capture.rb
|
60
61
|
- lib/gergich/capture/rubocop_capture.rb
|
62
|
+
- lib/gergich/capture/swiftlint_capture.rb
|
61
63
|
- lib/gergich/cli.rb
|
62
64
|
- lib/gergich/cli/gergich.rb
|
63
65
|
- lib/gergich/cli/master_bouncer.rb
|