gergich 0.0.3 → 0.1.0

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: fbb586bf1a73532571ecb8cf4b34679a8f1f3e71
4
- data.tar.gz: 02530fba1d33d28ca675a7c63273949f9ee88030
3
+ metadata.gz: 0f0688286ddfbfdcc686368378288bfb25914eb4
4
+ data.tar.gz: 3343039cccc137106652aed7061be6ecd6096995
5
5
  SHA512:
6
- metadata.gz: 8b8371b9cc0109757c2e83fe9e9bdf89cbc20730352fd72b761002258cce61501bdb81d56f2707d266cdfcf465b3e148653ea9f12cbe68c80f3cc072c3f3ef13
7
- data.tar.gz: 51b2ed7c6a62ddfaa72062dfb039f8b2d5f21a23647c6d68557b1380e255bbe050836302c37dde74f57aa572ec58a9a8cf912f0a7f0e8e91dcc7e8fa9f9577de
6
+ metadata.gz: 10294cd73ad93b2e289aa7f68b5bc08bed49fb3b6aaa30d6912ad1b61fd0e7f2dc550a335e0487da9149582a29bbb14754f9e7e28d21f4ec5fe88e0d86a6e308
7
+ data.tar.gz: 29b71a28a0ca12b710cbd00bb232fa9100d516d16c4d0a8883783c0476016beb8cb04c7d8e5784e7881edcae5ca32e7a90b202ea9b15f0066c56a4643b797882
data/README.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Gergich
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/gergich.svg)](https://rubygems.org/gems/gergich)
4
+ [![Dependency Status](https://gemnasium.com/badges/a2946a7849cd94f5ec0f4c3173a968f4.svg)](https://gemnasium.com/cc6fb44edee9fcf855cec82d3b6aed0f)
5
+ [![Build Status](https://travis-ci.org/instructure/gergich.svg?branch=master)](https://travis-ci.org/instructure/gergich)
6
+
3
7
  Gergich is a command-line tool (and ruby lib) for easily posting comments
4
8
  on a [Gerrit](https://www.gerritcodereview.com/) review from a CI
5
9
  environment. It can be wired up to linters (rubocop, eslint, etc.) so that
data/bin/master_bouncer CHANGED
@@ -1,4 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
2
  # encoding=utf-8
3
3
 
4
+ if ENV["COVERAGE"]
5
+ require "simplecov"
6
+ SimpleCov.command_name "master_bouncer:#{ARGV.join(' ')}"
7
+ end
8
+
4
9
  require_relative "../lib/gergich/cli/master_bouncer"
data/bin/run_tests.sh ADDED
@@ -0,0 +1,49 @@
1
+ #!/bin/bash
2
+
3
+ set -e
4
+
5
+ function run_command {
6
+ echo -e "\n[$@] STARTING $(date)"
7
+ last_status=0
8
+ "$@" || last_status=$?
9
+ if [[ $last_status == 0 ]]; then
10
+ echo -e "[$@] \033[32mOK\033[0m"
11
+ else
12
+ echo -e "[$@] \033[31mFAILED!\033[0m"
13
+ fi
14
+ echo -e "[$@] FINISHED $(date)\n"
15
+
16
+ [[ $last_status == 0 ]] || clean_up_and_exit
17
+ }
18
+
19
+ function clean_up_and_exit {
20
+ end_timestamp=$(date +%s)
21
+ duration=$((end_timestamp-start_timestamp))
22
+
23
+ if [[ $last_status != 0 ]]; then
24
+ echo -e "\033[31mBUILD FAILED\033[0m in $duration seconds\n"
25
+ else
26
+ echo "BUILD PASSED in $duration seconds"
27
+ fi
28
+ exit $last_status
29
+ }
30
+
31
+ start_timestamp=$(date +%s)
32
+
33
+ run_command bundle exec rubocop
34
+
35
+ export COVERAGE=1
36
+
37
+ run_command bundle exec rspec
38
+ run_command bin/gergich citest
39
+ run_command bin/master_bouncer check
40
+ DRY_RUN=1 run_command bin/master_bouncer check_all
41
+
42
+ run_command bin/check_coverage
43
+
44
+ if [[ $GEMNASIUM_TOKEN && $GEMNASIUM_ENABLED ]]; then
45
+ # Push our dependency specification files to gemnasium for analysis
46
+ run_command gemnasium dependency_files push -f=gergich.gemspec
47
+ fi
48
+
49
+ clean_up_and_exit
data/lib/gergich.rb CHANGED
@@ -73,13 +73,17 @@ module Gergich
73
73
  API.post(generate_url, generate_payload)
74
74
 
75
75
  # because why not
76
- if rand < 0.01 && GERGICH_USER == "gergich"
76
+ if change_name?
77
77
  API.put("/accounts/self/name", { name: whats_his_face }.to_json)
78
78
  end
79
79
 
80
80
  review_info
81
81
  end
82
82
 
83
+ def change_name?
84
+ ENV["GERGICH_CHANGE_NAME"] != "0" && rand < 0.01 && GERGICH_USER == "gergich"
85
+ end
86
+
83
87
  def anything_to_publish?
84
88
  !review_info[:comments].empty? ||
85
89
  !review_info[:cover_message].empty? ||
@@ -202,7 +206,7 @@ module Gergich
202
206
  @base_url ||= \
203
207
  ENV["GERRIT_BASE_URL"] ||
204
208
  ENV.key?("GERRIT_HOST") && "https://#{ENV['GERRIT_HOST']}" ||
205
- raise("need to set GERRIT_BASE_URL or GERRIT_HOST")
209
+ raise(GergichError, "need to set GERRIT_BASE_URL or GERRIT_HOST")
206
210
  end
207
211
 
208
212
  def base_options
@@ -281,8 +285,8 @@ module Gergich
281
285
  # a higher score set here.
282
286
  def add_label(name, score)
283
287
  score = score.to_i
284
- raise "invalid score" if score < -2 || score > 1
285
- raise "can't set #{name}" if %w[Verified].include?(name)
288
+ raise GergichError, "invalid score" if score < -2 || score > 1
289
+ raise GergichError, "can't set #{name}" if %w[Verified].include?(name)
286
290
 
287
291
  db.execute "INSERT INTO labels (name, score) VALUES (?, ?)",
288
292
  [name, score]
@@ -311,10 +315,10 @@ module Gergich
311
315
  # severe comment will be used to determine the overall
312
316
  # Code-Review score (0, -1, or -2 respectively)
313
317
  def add_comment(path, position, message, severity)
314
- raise "invalid position `#{position}`" unless valid_position?(position)
318
+ raise GergichError, "invalid position `#{position}`" unless valid_position?(position)
315
319
  position = position.to_json if position.is_a?(Hash)
316
- raise "invalid severity `#{severity}`" unless SEVERITY_MAP.key?(severity)
317
- raise "no message specified" unless message.is_a?(String) && !message.empty?
320
+ raise GergichError, "invalid severity `#{severity}`" unless SEVERITY_MAP.key?(severity)
321
+ raise GergichError, "no message specified" unless message.is_a?(String) && !message.empty?
318
322
 
319
323
  db.execute "INSERT INTO comments (path, position, message, severity) VALUES (?, ?, ?, ?)",
320
324
  [path, position, message, severity]
@@ -49,7 +49,7 @@ module Gergich
49
49
  def wiretap(io)
50
50
  output = ""
51
51
  io.each do |line|
52
- puts line
52
+ $stdout.puts line
53
53
  output << line
54
54
  end
55
55
  output
@@ -1,17 +1,20 @@
1
1
  module Gergich
2
2
  module Capture
3
3
  class EslintCapture < BaseCapture
4
+ SEVERITY_MAP = { "error" => "error", "warning" => "warn" }.freeze
5
+
4
6
  def run(output)
5
7
  # e.g. " 4:21 error Missing semicolon semi"
6
- error_pattern = /\s\s+(\d+):\d+\s+\w+\s+(.*?)\s+[\w-]+\n/
8
+ error_pattern = /\s\s+(\d+):\d+\s+(\w+)\s+(.*?)\s+[\w-]+\n/
7
9
  pattern = %r{ # Example:
8
10
  ^([^\n]+)\n # jsapp/models/user.js
9
11
  ((#{error_pattern})+) # 4:21 error Missing semicolon semi
10
12
  }mx
11
13
 
12
14
  output.scan(pattern).map { |file, errors|
13
- errors.scan(error_pattern).map { |line, error|
14
- { path: file, message: "[eslint] #{error}", position: line.to_i, severity: "error" }
15
+ errors.scan(error_pattern).map { |line, severity, error|
16
+ severity = SEVERITY_MAP[severity]
17
+ { path: file, message: "[eslint] #{error}", position: line.to_i, severity: severity }
15
18
  }
16
19
  }.compact.flatten
17
20
  end
@@ -22,6 +22,7 @@ OUTPUT
22
22
  }.freeze
23
23
 
24
24
  def run_ci_test!(all_commands)
25
+ ENV["GERGICH_CHANGE_NAME"] = "0"
25
26
  commands_to_test = all_commands - %w[citest reset publish status]
26
27
  commands_to_test << "status" # put it at the end, so we maximize the stuff it tests
27
28
 
@@ -66,7 +66,7 @@ commands = {}
66
66
 
67
67
  commands["check"] = {
68
68
  summary: "Check the current commit's age",
69
- action: ->(_args) {
69
+ action: ->() {
70
70
  maybe_bounce_commit! Gergich::Commit.new
71
71
  },
72
72
  help: ->() {
@@ -81,17 +81,21 @@ TEXT
81
81
 
82
82
  commands["check_all"] = {
83
83
  summary: "Check the age of all potentially mergeable changes",
84
- action: ->(_args) {
84
+ action: ->() {
85
85
  Gergich.git("fetch")
86
+ gerrit_host = ENV["GERRIT_HOST"] || error("No GERRIT_HOST set")
86
87
 
87
- potentially_mergeable_changes.each do |change|
88
- print "Checking g/#{change['_number']}... "
88
+ changes = potentially_mergeable_changes
89
+ next if ENV["DRY_RUN"]
89
90
 
91
+ changes.each do |change|
90
92
  sha = change["current_revision"]
91
93
  revinfo = change["revisions"][sha]
92
94
  refspec = revinfo["ref"]
93
95
  number = revinfo["_number"]
94
- Gergich.git("fetch ssh://gerrit.instructure.com:29418/#{PROJECT} #{refspec}")
96
+
97
+ print "Checking g/#{change['_number']}... "
98
+ Gergich.git("fetch ssh://#{gerrit_host}:29418/#{PROJECT} #{refspec}")
95
99
 
96
100
  maybe_bounce_commit! Gergich::Commit.new(sha, number)
97
101
  sleep 1
@@ -5,6 +5,11 @@ RSpec.describe Gergich::Capture do
5
5
 
6
6
  before do
7
7
  allow(Gergich::Draft).to receive(:new).and_return(draft)
8
+ $stdout = StringIO.new
9
+ end
10
+
11
+ after do
12
+ $stdout = STDOUT
8
13
  end
9
14
 
10
15
  context "rubocop" do
@@ -28,7 +33,8 @@ OUTPUT
28
33
  it "should catch errors" do
29
34
  allow(described_class).to receive(:run_command).and_return([0, <<-OUTPUT])
30
35
  jsapp/models/user.js
31
- 4:21 error Missing semicolon semi
36
+ 4:21 error Missing semicolon semi
37
+ 5:1 warning Too much cowbell cowbell-overload
32
38
  OUTPUT
33
39
  expect(draft).to receive(:add_comment).with(
34
40
  "jsapp/models/user.js",
@@ -36,6 +42,13 @@ OUTPUT
36
42
  "[eslint] Missing semicolon",
37
43
  "error"
38
44
  )
45
+
46
+ expect(draft).to receive(:add_comment).with(
47
+ "jsapp/models/user.js",
48
+ 5,
49
+ "[eslint] Too much cowbell",
50
+ "warn"
51
+ )
39
52
  described_class.run("eslint", "false")
40
53
  end
41
54
  end
@@ -56,4 +69,61 @@ OUTPUT
56
69
  described_class.run("i18nliner", "false")
57
70
  end
58
71
  end
72
+
73
+ context "custom" do
74
+ class CustomCaptor
75
+ def run(output)
76
+ puts output
77
+ output.scan(/^(.+?):(\d+): (.*)$/).map do |file, line, error|
78
+ { path: file, message: error, position: line.to_i, severity: "error" }
79
+ end
80
+ end
81
+ end
82
+
83
+ it "should catch errors" do
84
+ allow(described_class).to receive(:run_command).and_return([0, <<-OUTPUT])
85
+ foo.rb:1: you done screwed up
86
+ OUTPUT
87
+ expect(draft).to receive(:add_comment).with(
88
+ "foo.rb",
89
+ 1,
90
+ "you done screwed up",
91
+ "error"
92
+ )
93
+ described_class.run("custom:sqlite3:CustomCaptor", "false")
94
+ end
95
+ end
96
+
97
+ context "stdin" do
98
+ let :output do
99
+ <<-OUTPUT
100
+ jsapp/models/user.js
101
+ 4:21 error Missing semicolon semi
102
+ OUTPUT
103
+ end
104
+
105
+ before do
106
+ $stdin = StringIO.new(output)
107
+ end
108
+
109
+ after do
110
+ $stdin = STDIN
111
+ end
112
+
113
+ it "should catch errors" do
114
+ expect(draft).to receive(:add_comment).with(
115
+ "jsapp/models/user.js",
116
+ 4,
117
+ "[eslint] Missing semicolon",
118
+ "error"
119
+ )
120
+ described_class.run("eslint", "-")
121
+ end
122
+
123
+ it "shouldn't eat stdin" do
124
+ allow(draft).to receive(:add_comment)
125
+ expect($stdout).to receive(:puts).exactly(output.lines.size).times
126
+ described_class.run("eslint", "-")
127
+ end
128
+ end
59
129
  end
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.0.3
4
+ version: 0.1.0
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-04-06 00:00:00.000000000 Z
11
+ date: 2016-04-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sqlite3
@@ -52,6 +52,7 @@ files:
52
52
  - bin/check_coverage
53
53
  - bin/gergich
54
54
  - bin/master_bouncer
55
+ - bin/run_tests.sh
55
56
  - lib/gergich.rb
56
57
  - lib/gergich/capture.rb
57
58
  - lib/gergich/capture/eslint_capture.rb