gergich 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b8af2aab61e1b5c93269e3d9e2e6d4fb5dd01201
4
- data.tar.gz: 88a33e274c6a36ec65be8e32a05c151ef747f4d1
3
+ metadata.gz: 9d8fc46682dc58246a154bd7f4d9861c90ae7e75
4
+ data.tar.gz: 06842c81c83193794006287f4453cc51a32ad126
5
5
  SHA512:
6
- metadata.gz: dc12a8e5761990be3b1de20fa15dfd9392e83dcdb2c6a72553d859b9e88787550129fe48006674e4f4594f3170fd39037dfa8cb17440860d766634556a0a576f
7
- data.tar.gz: 9da9a59b35a715a688d7e9f3e700a011ccfa4ee027b8454c60fb70ef694faa9a80d5834e83458392947f38b26a322e0e7f99805c93e0ae642cdfcfd8261349a8
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
@@ -2,7 +2,7 @@
2
2
 
3
3
  if ENV["COVERAGE"]
4
4
  require "simplecov"
5
- SimpleCov.command_name "cli:#{ARGV.join(' ')}"
5
+ SimpleCov.command_name "cli:#{ARGV[0, 2].join(':')}:#{rand(1_000_000_000)}"
6
6
  end
7
7
 
8
8
  require_relative "../lib/gergich/cli/gergich"
data/bin/master_bouncer CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  if ENV["COVERAGE"]
5
5
  require "simplecov"
6
- SimpleCov.command_name "master_bouncer:#{ARGV.join(' ')}"
6
+ SimpleCov.command_name "master_bouncer:#{ARGV[0, 2].join(':')}:#{rand(1_000_000_000)}"
7
7
  end
8
8
 
9
9
  require_relative "../lib/gergich/cli/master_bouncer"
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
- output = Gergich.git("log -1 #{ref}")
30
- /\Acommit (?<revision_id>[0-9a-f]+).*^\s*Change-Id: (?<change_id>\w+)/m =~ output
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 ||= Gergich.git("diff-tree --no-commit-id --name-only -r #{ref}").split
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, body = nil)
192
- options = base_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 base_options
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(:base_options).and_return({})
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.3
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-06-22 00:00:00.000000000 Z
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