gergich 0.0.3 → 0.1.0

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