shiba 0.6.4 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +2 -0
- data/Gemfile.lock +1 -1
- data/README.md +3 -3
- data/Rakefile +15 -5
- data/bin/explain +0 -2
- data/bin/review +1 -65
- data/bin/shiba +3 -2
- data/bin/web +43 -0
- data/lib/shiba.rb +2 -8
- data/lib/shiba/activerecord_integration.rb +9 -6
- data/lib/shiba/explain/checks.rb +6 -0
- data/lib/shiba/output.rb +5 -1
- data/lib/shiba/parsers/mysql_select_fields.rb +4 -1
- data/lib/shiba/review/cli.rb +130 -21
- data/lib/shiba/version.rb +1 -1
- data/package.json +6 -0
- data/shiba.gemspec +1 -1
- metadata +8 -7
- data/Users/ben/src/shiba/web/dist/example_data.json.no +0 -1
- data/Users/ben/src/shiba/web/dist/index.html +0 -1
- data/Users/ben/src/shiba/web/dist/js/app.4765e0d6.js +0 -16
- data/Users/ben/src/shiba/web/dist/js/app.4765e0d6.js.map +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f6dbcdad59562d6337cf6357012a6d7e9e08b1c1
|
4
|
+
data.tar.gz: 6583e1f52e1d3ba5f28ed41202b03e9bf6f92124
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4612ff6c2cdb56c0ab24ed6bd0c938bbb035de7b881b68cf12ef71fd0507152c26cb60600cd5c7e1a039419a5e83a0af65fdea8f57a0695ecaa88287d079091e
|
7
|
+
data.tar.gz: 3aa4f8e1d74ae4c50e62fd604678ef1b25db1d4007519c9e4708a442039a913bd775d37a49f43db236fc7de44ae906f9b036d0fdd7967704e7113d4cc202e414
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -12,7 +12,7 @@ Install using bundler. Note: this gem is not designed to be run on production.
|
|
12
12
|
|
13
13
|
```ruby
|
14
14
|
# Gemfile
|
15
|
-
gem 'shiba', :group => :test
|
15
|
+
gem 'shiba', :group => :test, :require => 'shiba/setup'
|
16
16
|
```
|
17
17
|
|
18
18
|
If your application lazy loads gems, you will to manually require it.
|
@@ -110,7 +110,7 @@ after_script:
|
|
110
110
|
- bundle exec shiba review --submit
|
111
111
|
```
|
112
112
|
|
113
|
-
Add the Github API token you've generated as an environment variable named `
|
113
|
+
Add the Github API token you've generated as an environment variable named `SHIBA_GITHUB_TOKEN` at https://travis-ci.com/{organization}/{repo}/settings.
|
114
114
|
|
115
115
|
#### CircleCI Integration
|
116
116
|
|
@@ -123,7 +123,7 @@ To integrate with CircleCI, add this after the the test run step in `.circleci/c
|
|
123
123
|
command: bundle exec shiba review --submit
|
124
124
|
```
|
125
125
|
|
126
|
-
An environment variable named `
|
126
|
+
An environment variable named `SHIBA_GITHUB_TOKEN` will need to be configured on CircleCI under *Project settings > Environment Variables*
|
127
127
|
|
128
128
|
#### Custom CI Integration
|
129
129
|
|
data/Rakefile
CHANGED
@@ -2,10 +2,12 @@ require "bundler/gem_tasks"
|
|
2
2
|
require 'rake/testtask'
|
3
3
|
|
4
4
|
Rake::TestTask.new do |t|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
end
|
5
|
+
t.libs << "test"
|
6
|
+
t.test_files = FileList['test/*_test.rb']
|
7
|
+
t.verbose = true
|
8
|
+
end
|
9
|
+
|
10
|
+
task :default => :test
|
9
11
|
|
10
12
|
task :build_web do
|
11
13
|
Dir.chdir(File.join(File.dirname(__FILE__), "web"))
|
@@ -13,6 +15,14 @@ task :build_web do
|
|
13
15
|
sh("npm run build")
|
14
16
|
end
|
15
17
|
|
18
|
+
task :check_master do
|
19
|
+
current_branch = `git rev-parse --abbrev-ref HEAD`.chomp
|
20
|
+
if "master" != current_branch
|
21
|
+
$stderr.puts "\n===== Warning: Not on master. running on branch #{current_branch} =====\n\n"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
Rake::Task[:release].prerequisites.unshift(:check_master)
|
16
26
|
Rake::Task[:release].prerequisites.unshift(:build_web)
|
17
27
|
|
18
|
-
task :default => :test
|
28
|
+
task :default => :test
|
data/bin/explain
CHANGED
data/bin/review
CHANGED
@@ -1,71 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
$LOAD_PATH << File.expand_path("../lib", File.dirname(__FILE__))
|
4
|
-
require 'optionparser'
|
5
|
-
require 'shiba/configure'
|
6
|
-
require 'shiba/reviewer'
|
7
|
-
require 'shiba/review/explain_diff'
|
8
4
|
require 'shiba/review/cli'
|
9
|
-
require 'json'
|
10
5
|
|
11
6
|
cli = Shiba::Review::CLI.new
|
12
|
-
cli.
|
13
|
-
|
14
|
-
if !cli.valid?
|
15
|
-
$stderr.puts cli.failure
|
16
|
-
exit 1
|
17
|
-
end
|
18
|
-
|
19
|
-
explain_diff = Shiba::Review::ExplainDiff.new(cli.options["file"], cli.options)
|
20
|
-
|
21
|
-
problems = if explain_diff.diff_requested_by_user?
|
22
|
-
result = explain_diff.result
|
23
|
-
|
24
|
-
if result.message
|
25
|
-
$stderr.puts result.message
|
26
|
-
end
|
27
|
-
|
28
|
-
if result.status == :pass
|
29
|
-
exit
|
30
|
-
end
|
31
|
-
|
32
|
-
explain_diff.problems
|
33
|
-
else
|
34
|
-
explains = File.open(cli.options["file"]).each_line.map { |json| JSON.parse(json) }
|
35
|
-
bad = explains.select { |explain| explain["severity"] && explain["severity"] != 'none' }
|
36
|
-
bad.map { |explain| [ "#{explain["sql"]}:-2", explain ] }
|
37
|
-
end
|
38
|
-
|
39
|
-
repo_cmd = "git config --get remote.origin.url"
|
40
|
-
repo_url = `#{repo_cmd}`.chomp
|
41
|
-
|
42
|
-
if cli.options["verbose"]
|
43
|
-
$stderr.puts "#{repo_cmd}\t#{repo_url}"
|
44
|
-
end
|
45
|
-
|
46
|
-
if repo_url.empty?
|
47
|
-
$stderr.puts "'#{Dir.pwd}' does not appear to be a git repo"
|
48
|
-
exit 1
|
49
|
-
end
|
50
|
-
|
51
|
-
# Generate comments for the problem queries
|
52
|
-
reviewer = Shiba::Reviewer.new(repo_url, problems, cli.options)
|
53
|
-
|
54
|
-
if !cli.options["submit"] || cli.options["verbose"]
|
55
|
-
reviewer.comments.each do |c|
|
56
|
-
puts "#{c[:path]}:#{c[:line]} (#{c[:position]})"
|
57
|
-
puts c[:body]
|
58
|
-
puts ""
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
if cli.options["submit"]
|
63
|
-
if reviewer.repo_host.empty? || reviewer.repo_path.empty?
|
64
|
-
$stderr.puts "Invalid repo url '#{repo_url}' from git config --get remote.origin.url"
|
65
|
-
exit 1
|
66
|
-
end
|
67
|
-
|
68
|
-
reviewer.submit
|
69
|
-
end
|
70
|
-
|
71
|
-
exit 2
|
7
|
+
exit cli.run
|
data/bin/shiba
CHANGED
@@ -7,7 +7,8 @@ APP = File.basename(__FILE__)
|
|
7
7
|
commands = {
|
8
8
|
"explain" => "Generate a report from logged SQL queries",
|
9
9
|
"review" => "Review changed files for query problems",
|
10
|
-
"dump_stats" => "Collect database statistics for more accurate analysis"
|
10
|
+
"dump_stats" => "Collect database statistics for more accurate analysis",
|
11
|
+
"web" => "Generate a report from JSON-explain"
|
11
12
|
}
|
12
13
|
|
13
14
|
global = OptionParser.new do |opts|
|
@@ -38,4 +39,4 @@ end
|
|
38
39
|
|
39
40
|
path = File.join(File.dirname(__FILE__), command)
|
40
41
|
|
41
|
-
Kernel.exec(path, *ARGV)
|
42
|
+
Kernel.exec(path, *ARGV)
|
data/bin/web
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'shiba/output'
|
5
|
+
require 'json'
|
6
|
+
require 'optionparser'
|
7
|
+
require 'set'
|
8
|
+
|
9
|
+
options = {}
|
10
|
+
|
11
|
+
parser = OptionParser.new do |opts|
|
12
|
+
opts.on("-h", "--html FILE", "write html report here.") do |h|
|
13
|
+
options["html"] = h
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
parser.banner = "Shiba web: accept JSON-explain on stdin, write out an HTML report"
|
18
|
+
parser.parse!
|
19
|
+
|
20
|
+
if !options['html']
|
21
|
+
$stderr.puts parser.help
|
22
|
+
$stderr.puts "required option: --html"
|
23
|
+
exit 2
|
24
|
+
end
|
25
|
+
|
26
|
+
queries = []
|
27
|
+
query_md5s = Set.new
|
28
|
+
|
29
|
+
while line = $stdin.gets
|
30
|
+
query = JSON.parse(line)
|
31
|
+
next if query_md5s.include?(query['md5'])
|
32
|
+
queries << JSON.parse(line)
|
33
|
+
query_md5s << query['md5']
|
34
|
+
end
|
35
|
+
|
36
|
+
page = Shiba::Output.new(queries, { 'output' => options['html'] }).make_web!
|
37
|
+
if !File.exist?(page)
|
38
|
+
$stderr.puts("Failed to generate #{page}")
|
39
|
+
exit 2
|
40
|
+
end
|
41
|
+
|
42
|
+
$stderr.puts "Report available at #{page}"
|
43
|
+
|
data/lib/shiba.rb
CHANGED
@@ -75,7 +75,7 @@ module Shiba
|
|
75
75
|
end
|
76
76
|
|
77
77
|
def self.path
|
78
|
-
@log_path ||= ENV['
|
78
|
+
@log_path ||= ENV['SHIBA_DIR'] || try_tmp || use_tmpdir
|
79
79
|
end
|
80
80
|
|
81
81
|
private
|
@@ -94,10 +94,4 @@ module Shiba
|
|
94
94
|
Dir.mkdir(path) if !Dir.exist?(path)
|
95
95
|
path
|
96
96
|
end
|
97
|
-
end
|
98
|
-
|
99
|
-
# This goes at the end so that Shiba.root is defined.
|
100
|
-
if defined?(ActiveSupport.on_load)
|
101
|
-
require 'shiba/activerecord_integration'
|
102
|
-
Shiba::ActiveRecordIntegration.install!
|
103
|
-
end
|
97
|
+
end
|
@@ -7,13 +7,17 @@ module Shiba
|
|
7
7
|
# Integrates ActiveRecord with the Query Watcher by setting up the query log path, and the
|
8
8
|
# connection options for the explain command, which it runs when the process exits.
|
9
9
|
#
|
10
|
-
#
|
10
|
+
# SHIBA_DIR, SHIBA_QUERY_LOG_NAME and SHIBA_DEBUG=true environment variables may be set.
|
11
11
|
class ActiveRecordIntegration
|
12
12
|
|
13
13
|
attr_reader :path, :watcher
|
14
14
|
|
15
15
|
def self.install!
|
16
16
|
return false if @installed
|
17
|
+
if defined?(Rails.env) && Rails.env.production?
|
18
|
+
Rails.logger.error("Shiba watcher is not intended to run in production, stopping install.")
|
19
|
+
return false
|
20
|
+
end
|
17
21
|
|
18
22
|
ActiveSupport.on_load(:active_record) do
|
19
23
|
Shiba::ActiveRecordIntegration.start_watcher
|
@@ -32,7 +36,7 @@ module Shiba
|
|
32
36
|
c = { host: cx.host, database: cx.db, username: cx.user, password: cx.pass, port: cx.port, server: 'postgres' }
|
33
37
|
end
|
34
38
|
|
35
|
-
|
39
|
+
{
|
36
40
|
'host' => c[:host],
|
37
41
|
'database' => c[:database],
|
38
42
|
'user' => c[:username],
|
@@ -61,17 +65,16 @@ module Shiba
|
|
61
65
|
end
|
62
66
|
|
63
67
|
def self.log_path
|
64
|
-
name = ENV["
|
68
|
+
name = ENV["SHIBA_QUERY_LOG_NAME"] || "query.log-#{Time.now.to_i}"
|
65
69
|
File.join(Shiba.path, name)
|
66
70
|
end
|
67
71
|
|
68
72
|
def self.run_explain(file, path)
|
69
73
|
file.close
|
70
|
-
puts ""
|
71
74
|
|
72
75
|
cmd = "shiba explain #{database_args} --file #{path}"
|
73
|
-
if ENV['
|
74
|
-
cmd << " --json #{File.join(Shiba.path, "#{ENV["
|
76
|
+
if ENV['SHIBA_QUERY_LOG_NAME']
|
77
|
+
cmd << " --json #{File.join(Shiba.path, "#{ENV["SHIBA_QUERY_LOG_NAME"]}.json")}"
|
75
78
|
elsif Shiba::Configure.ci?
|
76
79
|
cmd << " --json #{File.join(Shiba.path, 'ci.json')}"
|
77
80
|
end
|
data/lib/shiba/explain/checks.rb
CHANGED
@@ -129,6 +129,12 @@ module Shiba
|
|
129
129
|
end
|
130
130
|
|
131
131
|
@cost = Shiba::Explain::COST_PER_ROW_READ * rows_read
|
132
|
+
|
133
|
+
# pin fully missed indexes to a 'low' threshold
|
134
|
+
if @access_type == 'access_type_tablescan'
|
135
|
+
@cost = [0.01, @cost].max
|
136
|
+
end
|
137
|
+
|
132
138
|
@result.cost += @cost
|
133
139
|
|
134
140
|
@tbl_message['cost'] = @cost
|
data/lib/shiba/output.rb
CHANGED
@@ -61,7 +61,11 @@ module Shiba
|
|
61
61
|
def make_web!
|
62
62
|
data = as_json
|
63
63
|
|
64
|
-
|
64
|
+
index_path = File.join(WEB_PATH, "dist", "index.html")
|
65
|
+
if !File.exist?(index_path)
|
66
|
+
raise Shiba::Error.new("dist/index.html not found. Try running 'rake build_web'")
|
67
|
+
end
|
68
|
+
index = File.read(index_path)
|
65
69
|
data_block = "var shibaData = #{JSON.dump(as_json)};\n"
|
66
70
|
|
67
71
|
index.sub!(%r{<script src=(.*?)>}) do |match|
|
@@ -52,7 +52,10 @@ module Shiba
|
|
52
52
|
tables[table] << col
|
53
53
|
elsif sc.scan(/(\d+|NULL|'.*?') AS `(.*?)`/m)
|
54
54
|
else
|
55
|
-
|
55
|
+
if ENV['SHIBA_DEBUG']
|
56
|
+
raise Shiba::Error.new("unknown stuff: in #{@sql}: #{@sc.rest}")
|
57
|
+
end
|
58
|
+
return {}
|
56
59
|
end
|
57
60
|
|
58
61
|
sc.scan(/,/)
|
data/lib/shiba/review/cli.rb
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
require 'optionparser'
|
2
|
+
require 'shiba/configure'
|
3
|
+
require 'shiba/reviewer'
|
4
|
+
require 'shiba/review/explain_diff'
|
5
|
+
require 'json'
|
6
|
+
|
1
7
|
module Shiba
|
2
8
|
module Review
|
3
9
|
# Builds options for interacting with the reviewer via the command line.
|
@@ -18,13 +24,108 @@ module Shiba
|
|
18
24
|
# => "An error message with command line help."
|
19
25
|
class CLI
|
20
26
|
|
21
|
-
attr_reader :
|
27
|
+
attr_reader :out, :err, :input
|
22
28
|
|
23
|
-
|
24
|
-
|
29
|
+
# Options may be provided for testing, in which case the option parser is skipped.
|
30
|
+
# When this happens, default options are also skipped.
|
31
|
+
def initialize(out: $stdout, err: $stderr, input: $stdin, options: nil)
|
32
|
+
@out = out
|
33
|
+
@err = err
|
34
|
+
@input = input
|
35
|
+
@user_options = options || {}
|
25
36
|
@errors = []
|
26
|
-
parser.parse!
|
27
|
-
@options = default_options.merge(@user_options)
|
37
|
+
parser.parse! if options.nil?
|
38
|
+
@options = options || default_options.merge(@user_options)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Generates the review, returning an exit status code.
|
42
|
+
# Prints to @out / @err, which default to STDOUT/STDERR.
|
43
|
+
def run
|
44
|
+
report_options("diff", "branch", "pull_request")
|
45
|
+
|
46
|
+
if !valid?
|
47
|
+
err.puts failure
|
48
|
+
return 1
|
49
|
+
end
|
50
|
+
|
51
|
+
explain_diff = Shiba::Review::ExplainDiff.new(options["file"], options)
|
52
|
+
|
53
|
+
problems = if explain_diff.diff_requested_by_user?
|
54
|
+
result = explain_diff.result
|
55
|
+
|
56
|
+
if result.message
|
57
|
+
@err.puts result.message
|
58
|
+
end
|
59
|
+
|
60
|
+
if result.status == :pass
|
61
|
+
return 0
|
62
|
+
end
|
63
|
+
|
64
|
+
explain_diff.problems
|
65
|
+
else
|
66
|
+
# Find all problem explains
|
67
|
+
begin
|
68
|
+
explains = explain_file.each_line.map { |json| JSON.parse(json) }
|
69
|
+
bad = explains.select { |explain| explain["severity"] && explain["severity"] != 'none' }
|
70
|
+
bad.map { |explain| [ "#{explain["sql"]}:-2", explain ] }
|
71
|
+
rescue Interrupt
|
72
|
+
@err.puts "SIGINT: Canceled reading from STDIN. To read from an explain log, provide the --file option."
|
73
|
+
exit 1
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
if problems.empty?
|
78
|
+
return 0
|
79
|
+
end
|
80
|
+
|
81
|
+
# Dedup
|
82
|
+
problems.uniq! { |_,p| p["md5"] }
|
83
|
+
|
84
|
+
# Output problem explains, this can be provided as a file to shiba review for comments.
|
85
|
+
if options["raw"]
|
86
|
+
pr = options["pull_request"]
|
87
|
+
if pr
|
88
|
+
problems.each { |_,problem| problem["pull_request"] = pr }
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
problems.each { |_,problem| @out.puts JSON.dump(problem) }
|
93
|
+
return 2
|
94
|
+
end
|
95
|
+
|
96
|
+
# Generate comments for the problem queries
|
97
|
+
repo_cmd = "git config --get remote.origin.url"
|
98
|
+
repo_url = `#{repo_cmd}`.chomp
|
99
|
+
|
100
|
+
if options["verbose"]
|
101
|
+
@err.puts "#{repo_cmd}\t#{repo_url}"
|
102
|
+
end
|
103
|
+
|
104
|
+
if repo_url.empty?
|
105
|
+
@err.puts "'#{Dir.pwd}' does not appear to be a git repo"
|
106
|
+
return 1
|
107
|
+
end
|
108
|
+
|
109
|
+
reviewer = Shiba::Reviewer.new(repo_url, problems, options)
|
110
|
+
|
111
|
+
if !options["submit"] || options["verbose"]
|
112
|
+
reviewer.comments.each do |c|
|
113
|
+
@out.puts "#{c[:path]}:#{c[:line]} (#{c[:position]})"
|
114
|
+
@out.puts c[:body]
|
115
|
+
@out.puts ""
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
if options["submit"]
|
120
|
+
if reviewer.repo_host.empty? || reviewer.repo_path.empty?
|
121
|
+
@err.puts "Invalid repo url '#{repo_url}' from git config --get remote.origin.url"
|
122
|
+
return 1
|
123
|
+
end
|
124
|
+
|
125
|
+
reviewer.submit
|
126
|
+
end
|
127
|
+
|
128
|
+
return 2
|
28
129
|
end
|
29
130
|
|
30
131
|
def options
|
@@ -36,14 +137,12 @@ module Shiba
|
|
36
137
|
|
37
138
|
validate_log_path
|
38
139
|
#validate_git_repo if branch || options["submit"]
|
39
|
-
description = "Provide an explain log, or run 'shiba explain' to generate one."
|
40
|
-
|
41
|
-
require_option("file", description: description)
|
42
140
|
|
43
141
|
if options["submit"]
|
44
142
|
require_option("branch") if options["diff"].nil?
|
45
|
-
require_option("token")
|
143
|
+
require_option("token", description: "This can be read from the $SHIBA_GITHUB_TOKEN environment variable.")
|
46
144
|
require_option("pull_request")
|
145
|
+
error("Must specify either 'submit' or 'raw' output option, not both") if options["raw"]
|
47
146
|
end
|
48
147
|
|
49
148
|
@errors.empty?
|
@@ -69,16 +168,25 @@ module Shiba
|
|
69
168
|
|
70
169
|
protected
|
71
170
|
|
171
|
+
def explain_file
|
172
|
+
options.key?('file') ? File.open(options['file']) : @input
|
173
|
+
end
|
174
|
+
|
72
175
|
def parser
|
73
176
|
@parser ||= OptionParser.new do |opts|
|
74
|
-
opts.banner = "
|
177
|
+
opts.banner = "Reads from a file or stdin to review changes for query problems. Optionally submit the comments to a Github pull request."
|
75
178
|
|
76
|
-
opts.separator "
|
179
|
+
opts.separator ""
|
180
|
+
opts.separator "IO options:"
|
77
181
|
|
78
|
-
opts.on("-f","--file FILE", "The explain
|
182
|
+
opts.on("-f","--file FILE", "The JSON explain log to compare with. Automatically configured when $CI environment variable is set") do |f|
|
79
183
|
@user_options["file"] = f
|
80
184
|
end
|
81
185
|
|
186
|
+
opts.on("--raw", "Print the raw JSON with the pull request id") do |r|
|
187
|
+
@user_options["raw"] = r
|
188
|
+
end
|
189
|
+
|
82
190
|
opts.separator ""
|
83
191
|
opts.separator "Git diff options:"
|
84
192
|
|
@@ -105,7 +213,7 @@ module Shiba
|
|
105
213
|
@user_options["pull_request"] = p
|
106
214
|
end
|
107
215
|
|
108
|
-
opts.on("-t", "--token TOKEN", "The Github API token to use for commenting. Defaults to $
|
216
|
+
opts.on("-t", "--token TOKEN", "The Github API token to use for commenting. Defaults to $SHIBA_GITHUB_TOKEN.") do |t|
|
109
217
|
@user_options["token"] = t
|
110
218
|
end
|
111
219
|
|
@@ -117,13 +225,13 @@ module Shiba
|
|
117
225
|
end
|
118
226
|
|
119
227
|
opts.on_tail("-h", "--help", "Show this message") do
|
120
|
-
puts opts
|
228
|
+
@out.puts opts
|
121
229
|
exit
|
122
230
|
end
|
123
231
|
|
124
232
|
opts.on_tail("--version", "Show version") do
|
125
233
|
require 'shiba/version'
|
126
|
-
puts Shiba::VERSION
|
234
|
+
@out.puts Shiba::VERSION
|
127
235
|
exit
|
128
236
|
end
|
129
237
|
end
|
@@ -139,12 +247,12 @@ module Shiba
|
|
139
247
|
if Shiba::Configure.ci?
|
140
248
|
report("Finding default options from CI environment.")
|
141
249
|
|
142
|
-
defaults["file"] = ci_explain_log_path
|
143
|
-
defaults["pull_request"] = ci_pull_request
|
144
|
-
defaults["branch"] = ci_branch
|
250
|
+
defaults["file"] = ci_explain_log_path if ci_explain_log_path
|
251
|
+
defaults["pull_request"] = ci_pull_request if ci_pull_request
|
252
|
+
defaults["branch"] = ci_branch if !defaults['diff'] && ci_branch
|
145
253
|
end
|
146
254
|
|
147
|
-
defaults["token"] = ENV['
|
255
|
+
defaults["token"] = ENV['SHIBA_GITHUB_TOKEN'] if ENV['SHIBA_GITHUB_TOKEN']
|
148
256
|
|
149
257
|
defaults
|
150
258
|
end
|
@@ -157,7 +265,8 @@ module Shiba
|
|
157
265
|
end
|
158
266
|
|
159
267
|
def ci_explain_log_path
|
160
|
-
|
268
|
+
name = ENV['SHIBA_QUERY_LOG_NAME'] || 'ci'
|
269
|
+
File.join(Shiba.path, "#{name}.json")
|
161
270
|
end
|
162
271
|
|
163
272
|
def ci_branch
|
@@ -184,7 +293,7 @@ module Shiba
|
|
184
293
|
end
|
185
294
|
|
186
295
|
def report(message)
|
187
|
-
|
296
|
+
@err.puts message if @user_options["verbose"]
|
188
297
|
end
|
189
298
|
|
190
299
|
def error(message, help: false)
|