gergich 0.2.2 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +5 -5
  2. data/LICENSE +2 -2
  3. data/README.md +0 -1
  4. data/bin/check_coverage +2 -1
  5. data/bin/gergich +1 -0
  6. data/bin/master_bouncer +1 -1
  7. data/bin/run_tests.sh +8 -43
  8. data/lib/gergich.rb +20 -24
  9. data/lib/gergich/capture.rb +8 -4
  10. data/lib/gergich/capture/androidlint_capture.rb +5 -1
  11. data/lib/gergich/capture/brakeman_capture.rb +4 -2
  12. data/lib/gergich/capture/eslint_capture.rb +2 -0
  13. data/lib/gergich/capture/flake8_capture.rb +2 -0
  14. data/lib/gergich/capture/i18nliner_capture.rb +2 -0
  15. data/lib/gergich/capture/rubocop_capture.rb +2 -0
  16. data/lib/gergich/capture/shellcheck_capture.rb +2 -0
  17. data/lib/gergich/capture/stylelint_capture.rb +8 -5
  18. data/lib/gergich/capture/swiftlint_capture.rb +5 -1
  19. data/lib/gergich/cli.rb +4 -2
  20. data/lib/gergich/cli/gergich.rb +119 -118
  21. data/lib/gergich/cli/master_bouncer.rb +16 -14
  22. data/spec/gergich/capture/androidlint_capture_spec.rb +15 -10
  23. data/spec/gergich/capture/brakeman_capture_spec.rb +43 -41
  24. data/spec/gergich/capture/custom_capture_spec.rb +4 -2
  25. data/spec/gergich/capture/eslint_capture_spec.rb +6 -4
  26. data/spec/gergich/capture/flake8_capture_spec.rb +4 -2
  27. data/spec/gergich/capture/i18nliner_capture_spec.rb +6 -4
  28. data/spec/gergich/capture/rubocop_capture_spec.rb +24 -22
  29. data/spec/gergich/capture/shellcheck_capture_spec.rb +45 -43
  30. data/spec/gergich/capture/stylelint_capture_spec.rb +16 -7
  31. data/spec/gergich/capture/swiftlint_capture_spec.rb +8 -5
  32. data/spec/gergich/capture_spec.rb +6 -4
  33. data/spec/gergich_spec.rb +58 -4
  34. data/spec/spec_helper.rb +2 -0
  35. data/spec/support/capture_shared_examples.rb +2 -0
  36. metadata +39 -40
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shellwords"
2
4
  require "English"
3
5
 
@@ -38,7 +40,7 @@ def help_command(commands)
38
40
  end
39
41
  },
40
42
  help: -> {
41
- indentation = commands.keys.map(&:size).sort.last
43
+ indentation = commands.keys.map(&:size).max
42
44
  commands_help = commands
43
45
  .to_a
44
46
  .sort_by(&:first)
@@ -73,7 +75,7 @@ def run_app(commands)
73
75
  run_command(action)
74
76
  rescue GergichError
75
77
  error $ERROR_INFO.message
76
- rescue
78
+ rescue StandardError
77
79
  error "Unhandled exception: #{$ERROR_INFO}\n#{$ERROR_INFO.backtrace.join("\n")}"
78
80
  end
79
81
  else
@@ -1,4 +1,4 @@
1
- # encoding=utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  require_relative "../cli"
4
4
  require_relative "../../gergich"
@@ -14,11 +14,11 @@ CI_TEST_ARGS = {
14
14
  ],
15
15
  "label" => ["Code-Review", 1],
16
16
  "message" => ["this is a test"],
17
- "capture" => ["rubocop", "echo #{Shellwords.escape(<<-OUTPUT)}"]
18
- bin/gergich:47:8: C: Prefer double-quoted strings
19
- if ENV['DEBUG']
20
- ^^^^^^^
21
- OUTPUT
17
+ "capture" => ["rubocop", format("echo %<output>s", output: Shellwords.escape(<<~OUTPUT))]
18
+ bin/gergich:47:8: C: Prefer double-quoted strings
19
+ if ENV['DEBUG']
20
+ ^^^^^^^
21
+ OUTPUT
22
22
  }.freeze
23
23
 
24
24
  def run_ci_test!(all_commands)
@@ -27,13 +27,14 @@ def run_ci_test!(all_commands)
27
27
  commands_to_test << "status" # put it at the end, so we maximize the stuff it tests
28
28
 
29
29
  commands = commands_to_test.map { |command| [command, CI_TEST_ARGS[command] || []] }
30
- commands.concat all_commands.map { |command| ["help", [command]] }
30
+ commands.concat(all_commands.map { |command| ["help", [command]] })
31
31
 
32
32
  # after running our test commands, reset and publish frd:
33
33
  commands << ["reset"]
34
- commands << ["label", ["QA-Review", 1]]
35
- commands << ["label", ["Product-Review", 1]]
36
- commands << ["label", ["Code-Review", 1]]
34
+ # Note that while gergich should always be able to vote on these labels, he may be used to
35
+ # vone on other branches depending on project usage and project-specific permissions
36
+ commands << ["label", ["Lint-Review", 1]]
37
+ commands << ["label", ["Code-Review", 1]] # Not all projects have Lint-Review
37
38
  commands << ["message", ["\`gergich citest\` checks out :thumbsup: :mj:"]]
38
39
  commands << ["publish"]
39
40
 
@@ -50,21 +51,21 @@ commands = {}
50
51
 
51
52
  commands["reset"] = {
52
53
  summary: "Clear out pending comments/labels/messages for this patchset",
53
- action: ->() {
54
+ action: -> {
54
55
  Gergich::Draft.new.reset!
55
56
  },
56
57
  help: -> {
57
- <<-TEXT
58
- gergich reset
58
+ <<~TEXT
59
+ gergich reset
59
60
 
60
- Clear out the draft for this patchset. Useful for testing.
61
- TEXT
61
+ Clear out the draft for this patchset. Useful for testing.
62
+ TEXT
62
63
  }
63
64
  }
64
65
 
65
66
  commands["publish"] = {
66
67
  summary: "Publish the draft for this patchset",
67
- action: ->() {
68
+ action: -> {
68
69
  if (data = Gergich::Review.new.publish!)
69
70
  puts "Published #{data[:total_comments]} comments, set score to #{data[:score]}"
70
71
  else
@@ -72,33 +73,33 @@ commands["publish"] = {
72
73
  end
73
74
  },
74
75
  help: -> {
75
- <<-TEXT
76
- gergich publish
76
+ <<~TEXT
77
+ gergich publish
77
78
 
78
- Publish all draft comments/labels/messages for this patchset. no-op if
79
- there are none.
79
+ Publish all draft comments/labels/messages for this patchset. no-op if
80
+ there are none.
80
81
 
81
- The cover message and Code-Review label (e.g. -2) are inferred from the
82
- comments, but labels and messages may be manually set (via `gergich
83
- message` and `gergich labels`)
84
- TEXT
82
+ The cover message and Code-Review label (e.g. -2) are inferred from the
83
+ comments, but labels and messages may be manually set (via `gergich
84
+ message` and `gergich labels`)
85
+ TEXT
85
86
  }
86
87
  }
87
88
 
88
89
  commands["status"] = {
89
90
  summary: "Show the current draft for this patchset",
90
- action: ->() {
91
+ action: -> {
91
92
  Gergich::Review.new.status
92
93
  },
93
94
  help: -> {
94
- <<-TEXT
95
- gergich status
95
+ <<~TEXT
96
+ gergich status
96
97
 
97
- Show the current draft for this patchset
98
+ Show the current draft for this patchset
98
99
 
99
- Display any labels, cover messages and inline comments that will be set
100
- as part of this review.
101
- TEXT
100
+ Display any labels, cover messages and inline comments that will be set
101
+ as part of this review.
102
+ TEXT
102
103
  }
103
104
  }
104
105
 
@@ -107,8 +108,8 @@ commands["comment"] = {
107
108
  action: ->(comment_data) {
108
109
  comment_data = begin
109
110
  JSON.parse(comment_data)
110
- rescue JSON::ParserError
111
- error("Unable to parse <comment_data> json", "comment")
111
+ rescue JSON::ParserError
112
+ error("Unable to parse <comment_data> json", "comment")
112
113
  end
113
114
  comment_data = [comment_data] unless comment_data.is_a?(Array)
114
115
 
@@ -120,36 +121,36 @@ commands["comment"] = {
120
121
  comment["severity"]
121
122
  end
122
123
  },
123
- help: ->() {
124
- <<-TEXT
125
- gergich comment <comment_data>
126
-
127
- <comment_data> is a JSON object (or array of objects). Each comment object
128
- should have the following properties:
129
- path - the relative file path, e.g. "app/models/user.rb"
130
- position - either a number (line) or an object (range). If an object,
131
- must have the following numeric properties:
132
- * start_line
133
- * start_character
134
- * end_line
135
- * end_character
136
- message - the text of the comment
137
- severity - "info"|"warn"|"error" - this will automatically prefix the
138
- comment (e.g. "[ERROR] message here"), and the most severe
139
- comment will be used to determine the overall Code-Review
140
- score (0, -1, or -2 respectively)
141
-
142
- Note that a cover message and Code-Review score will be inferred from the
143
- most severe comment.
144
-
145
- Examples
146
- gergich comment '{"path":"foo.rb","position":3,"severity":"error",
147
- "message":"ಠ_ಠ"}'
148
- gergich comment '{"path":"bar.rb","severity":"warn",
149
- "position":{"start_line":3,"start_character":5,...},
150
- "message":"¯\\_(ツ)_/¯"}'
151
- gergich comment '[{"path":"baz.rb",...}, {...}, {...}]'
152
- TEXT
124
+ help: -> {
125
+ <<~TEXT
126
+ gergich comment <comment_data>
127
+
128
+ <comment_data> is a JSON object (or array of objects). Each comment object
129
+ should have the following properties:
130
+ path - the relative file path, e.g. "app/models/user.rb"
131
+ position - either a number (line) or an object (range). If an object,
132
+ must have the following numeric properties:
133
+ * start_line
134
+ * start_character
135
+ * end_line
136
+ * end_character
137
+ message - the text of the comment
138
+ severity - "info"|"warn"|"error" - this will automatically prefix the
139
+ comment (e.g. "[ERROR] message here"), and the most severe
140
+ comment will be used to determine the overall Code-Review
141
+ score (0, -1, or -2 respectively)
142
+
143
+ Note that a cover message and Code-Review score will be inferred from the
144
+ most severe comment.
145
+
146
+ Examples
147
+ gergich comment '{"path":"foo.rb","position":3,"severity":"error",
148
+ "message":"ಠ_ಠ"}'
149
+ gergich comment '{"path":"bar.rb","severity":"warn",
150
+ "position":{"start_line":3,"start_character":5,...},
151
+ "message":"¯\\_(ツ)_/¯"}'
152
+ gergich comment '[{"path":"baz.rb",...}, {...}, {...}]'
153
+ TEXT
153
154
  }
154
155
  }
155
156
 
@@ -159,13 +160,13 @@ commands["message"] = {
159
160
  draft = Gergich::Draft.new
160
161
  draft.add_message message
161
162
  },
162
- help: ->() {
163
- <<-TEXT
164
- gergich message <message>
163
+ help: -> {
164
+ <<~TEXT
165
+ gergich message <message>
165
166
 
166
- <message> will be appended to existing cover messages (inferred or manually
167
- added) for this patchset.
168
- TEXT
167
+ <message> will be appended to existing cover messages (inferred or manually
168
+ added) for this patchset.
169
+ TEXT
169
170
  }
170
171
  }
171
172
 
@@ -174,16 +175,16 @@ commands["label"] = {
174
175
  action: ->(label, score) {
175
176
  Gergich::Draft.new.add_label label, score
176
177
  },
177
- help: ->() {
178
- <<-TEXT
179
- gergich label <label> <score>
178
+ help: -> {
179
+ <<~TEXT
180
+ gergich label <label> <score>
180
181
 
181
- Add a draft label to this patchset. If the same label is set multiple
182
- times, the lowest score will win.
182
+ Add a draft label to this patchset. If the same label is set multiple
183
+ times, the lowest score will win.
183
184
 
184
- <label> - a valid label (e.g. "Code-Review")
185
- <score> - a valid score (e.g. -1)
186
- TEXT
185
+ <label> - a valid label (e.g. "Code-Review")
186
+ <score> - a valid score (e.g. -1)
187
+ TEXT
187
188
  }
188
189
  }
189
190
 
@@ -194,63 +195,63 @@ commands["capture"] = {
194
195
  status, = Gergich::Capture.run(format, command)
195
196
  exit status
196
197
  },
197
- help: ->() {
198
- <<-TEXT
199
- gergich capture <format> <command>
198
+ help: -> {
199
+ <<~TEXT
200
+ gergich capture <format> <command>
200
201
 
201
- For common linting formats, `gergich capture` can be used to automatically
202
- do `gergich comment` calls so you don't have to wire it up yourself.
202
+ For common linting formats, `gergich capture` can be used to automatically
203
+ do `gergich comment` calls so you don't have to wire it up yourself.
203
204
 
204
- <format> - One of the following:
205
- * brakeman
206
- * rubocop
207
- * eslint
208
- * i18nliner
209
- * flake8
210
- * stylelint
211
- * custom:<path>:<class_name> - file path and ruby
212
- class_name of a custom formatter.
205
+ <format> - One of the following:
206
+ * brakeman
207
+ * rubocop
208
+ * eslint
209
+ * i18nliner
210
+ * flake8
211
+ * stylelint
212
+ * custom:<path>:<class_name> - file path and ruby
213
+ class_name of a custom formatter.
213
214
 
214
- <command> - The command to run whose output conforms to <format>.
215
- Output from the command will still go to STDOUT, and
216
- Gergich will preserve its exit status.
217
- If command is "-", Gergich will simply read from STDIN
218
- and the exit status will always be 0.
215
+ <command> - The command to run whose output conforms to <format>.
216
+ Output from the command will still go to STDOUT, and
217
+ Gergich will preserve its exit status.
218
+ If command is "-", Gergich will simply read from STDIN
219
+ and the exit status will always be 0.
219
220
 
220
- Examples:
221
- gergich capture rubocop "bundle exec rubocop"
221
+ Examples:
222
+ gergich capture rubocop "bundle exec rubocop"
222
223
 
223
- gergich capture eslint eslint
224
+ gergich capture eslint eslint
224
225
 
225
- gergich capture i18nliner "rake i18nliner:check"
226
+ gergich capture i18nliner "rake i18nliner:check"
226
227
 
227
- gergich capture custom:./gergich/xss:Gergich::XSS "node script/xsslint"
228
+ gergich capture custom:./gergich/xss:Gergich::XSS "node script/xsslint"
228
229
 
229
- docker-compose run --rm web eslint | gergich capture eslint -
230
- # you might be interested in $PIPESTATUS[0]
231
- TEXT
230
+ docker-compose run --rm web eslint | gergich capture eslint -
231
+ # you might be interested in $PIPESTATUS[0]
232
+ TEXT
232
233
  }
233
234
  }
234
235
 
235
236
  commands["citest"] = {
236
237
  summary: "Do a full gergich test based on the current commit",
237
- action: ->() {
238
+ action: -> {
238
239
  # automagically test any new command that comes along
239
240
  run_ci_test!(commands.keys)
240
241
  },
241
- help: ->() {
242
- <<-TEXT
243
- gergich citest
244
-
245
- You shouldn't need to run this locally, it runs on jenkins. It does the
246
- following:
247
-
248
- 1. runs all the gergich commands (w/ dummy data)
249
- 2. ensure all `help` commands work
250
- 3. ensures gergich status is correct
251
- 4. resets
252
- 5. posts an actual +1
253
- 6. publishes
242
+ help: -> {
243
+ <<~TEXT
244
+ gergich citest
245
+
246
+ You shouldn't need to run this locally, it runs on jenkins. It does the
247
+ following:
248
+
249
+ 1. runs all the gergich commands (w/ dummy data)
250
+ 2. ensure all `help` commands work
251
+ 3. ensures gergich status is correct
252
+ 4. resets
253
+ 5. posts an actual +1
254
+ 6. publishes
254
255
  TEXT
255
256
  }
256
257
  }
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative "../cli"
2
4
 
3
5
  ENV["GERGICH_USER"] = ENV.fetch("MASTER_BOUNCER_USER", "master_bouncer")
@@ -19,7 +21,7 @@ def potentially_mergeable_changes
19
21
  "branch:master" \
20
22
  "&o=CURRENT_REVISION"
21
23
  changes = Gergich::API.get(url)
22
- changes.select { |c| c["subject"] !~ /\Awip($|\W)/i }
24
+ changes.reject { |c| c["subject"] =~ /\Awip($|\W)/i }
23
25
  end
24
26
 
25
27
  def maybe_bounce_commit!(commit)
@@ -67,22 +69,22 @@ commands = {}
67
69
 
68
70
  commands["check"] = {
69
71
  summary: "Check the current commit's age",
70
- action: ->() {
72
+ action: -> {
71
73
  maybe_bounce_commit! Gergich::Commit.new
72
74
  },
73
- help: ->() {
74
- <<-TEXT
75
- master_bouncer check
75
+ help: -> {
76
+ <<~TEXT
77
+ master_bouncer check
76
78
 
77
- Check the current commit's age, and bounce it if it's too old (-1 or -2,
78
- depending on the threshold)
79
- TEXT
79
+ Check the current commit's age, and bounce it if it's too old (-1 or -2,
80
+ depending on the threshold)
81
+ TEXT
80
82
  }
81
83
  }
82
84
 
83
85
  commands["check_all"] = {
84
86
  summary: "Check the age of all potentially mergeable changes",
85
- action: ->() {
87
+ action: -> {
86
88
  Gergich.git("fetch")
87
89
  gerrit_host = ENV["GERRIT_HOST"] || error("No GERRIT_HOST set")
88
90
 
@@ -102,12 +104,12 @@ commands["check_all"] = {
102
104
  sleep 1
103
105
  end
104
106
  },
105
- help: ->() {
106
- <<-TEXT
107
- master_bouncer check_all
107
+ help: -> {
108
+ <<~TEXT
109
+ master_bouncer check_all
108
110
 
109
- Check all open Verified+1 patchsets and bounce any that are too old.
110
- TEXT
111
+ Check all open Verified+1 patchsets and bounce any that are too old.
112
+ TEXT
111
113
  }
112
114
  }
113
115
 
@@ -1,24 +1,27 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative "../../support/capture_shared_examples"
2
4
 
3
5
  RSpec.describe Gergich::Capture::AndroidlintCapture do
4
- # rubocop:disable Metrics/LineLength
6
+ # rubocop:disable Layout/LineLength
5
7
  let(:rtl_hardcoded) { 'Consider adding android:drawableStart="@drawable/a_media" to better support right-to-left layouts [RtlHardcoded]' }
6
8
  let(:rtl_enabled) { "The project references RTL attributes, but does not explicitly enable or disable RTL support with android:supportsRtl in the manifest [RtlEnabled]" }
7
9
  let(: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]' }
8
10
  let(:unused_quantity) { 'For language "fr" (French) the following quantities are not relevant: few, zero [UnusedQuantity]' }
11
+ # rubocop:enable Layout/LineLength
9
12
  let(:output) do
10
- <<-OUTPUT
11
- /path/to/some.xml:27: Warning: #{rtl_hardcoded}
12
- android:drawableLeft="@drawable/ic_cv_media"/>
13
- ~~~~~~~~~~~~~~~~~~~~
13
+ <<~OUTPUT
14
+ /path/to/some.xml:27: Warning: #{rtl_hardcoded}
15
+ android:drawableLeft="@drawable/ic_cv_media"/>
16
+ ~~~~~~~~~~~~~~~~~~~~
14
17
 
15
- /path/to/AndroidManifest.xml: Warning: #{rtl_enabled}
18
+ /path/to/AndroidManifest.xml: Warning: #{rtl_enabled}
16
19
 
17
- /path/to/library/0.0.2: Error: #{lint_error}
20
+ /path/to/library/0.0.2: Error: #{lint_error}
18
21
 
19
- /path/to/values.xml:5: Warning: #{unused_quantity}
20
- <plurals name="number">
21
- ^
22
+ /path/to/values.xml:5: Warning: #{unused_quantity}
23
+ <plurals name="number">
24
+ ^
22
25
 
23
26
  OUTPUT
24
27
  end
@@ -28,7 +31,9 @@ RSpec.describe Gergich::Capture::AndroidlintCapture do
28
31
  {
29
32
  path: "/path/to/some.xml",
30
33
  position: 27,
34
+ # rubocop:disable Layout/LineLength
31
35
  message: "[androidlint] #{rtl_hardcoded}\n\n android:drawableLeft=\"@drawable/ic_cv_media\"/>\n ~~~~~~~~~~~~~~~~~~~~",
36
+ # rubocop:enable Layout/LineLength
32
37
  severity: "warn"
33
38
  },
34
39
  {