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 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