brightpearl-cli 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +4 -2
- data/lib/brightpearl_cli.rb +151 -76
- data/lib/core/config.rb +67 -17
- data/lib/core/encrypter.rb +55 -0
- data/lib/core/enums.rb +2 -0
- data/lib/core/git.rb +82 -37
- data/lib/core/mysql.rb +34 -8
- data/lib/core/terminal.rb +74 -165
- data/lib/core/tools.rb +33 -13
- data/lib/routes/build.rb +92 -19
- data/lib/routes/git_checkout.rb +13 -19
- data/lib/routes/git_delete.rb +18 -33
- data/lib/routes/git_merge.rb +148 -70
- data/lib/routes/git_pull.rb +40 -4
- data/lib/routes/git_push.rb +40 -4
- data/lib/routes/git_stash.rb +19 -2
- data/lib/routes/git_update.rb +13 -73
- data/lib/routes/jira.rb +1 -0
- data/lib/routes/production_logs.rb +356 -0
- data/lib/routes/review.rb +30 -4
- data/lib/routes/scripts_api_docs.rb +41 -0
- data/lib/routes/scripts_branch_cleaner.rb +196 -0
- data/lib/routes/scripts_pom_fixer.rb +94 -0
- data/lib/routes/setup.rb +11 -3
- data/lib/routes/tail.rb +46 -0
- metadata +15 -10
- data/lib/routes/less.rb +0 -37
- /data/lib/routes/{tests.rb → test.rb} +0 -0
@@ -0,0 +1,356 @@
|
|
1
|
+
require 'columnist'
|
2
|
+
require 'rest-client'
|
3
|
+
|
4
|
+
module BrightpearlCommand
|
5
|
+
|
6
|
+
class ProductionLogs < ::Convoy::ActionCommand::Base
|
7
|
+
|
8
|
+
include Columnist
|
9
|
+
|
10
|
+
LOG_URI_EUW1 = 'http://ec2-54-73-66-114.eu-west-1.compute.amazonaws.com:7777/php/php.log'
|
11
|
+
LOG_URI_EUW2 = 'http://ec2-54-73-26-152.eu-west-1.compute.amazonaws.com:7777/php/php.log'
|
12
|
+
LOG_URI_USE1 = 'http://ec2-174-129-36-164.compute-1.amazonaws.com:7777/php/php.log'
|
13
|
+
LOG_URI_USE2 = 'http://54.235.155.6:7777/php/php.log'
|
14
|
+
LOG_URI_USW1 = 'http://ec2-184-72-46-73.us-west-1.compute.amazonaws.com:7777/php/php.log'
|
15
|
+
LOG_URI_USW2 = 'http://ec2-184-72-49-68.us-west-1.compute.amazonaws.com:7777/php/php.log'
|
16
|
+
LOG_URI_STG1 = 'http://ec2-54-185-160-108.us-west-2.compute.amazonaws.com:7777/php/php.log'
|
17
|
+
LOG_URI_STG2 = 'http://ec2-54-190-109-53.us-west-2.compute.amazonaws.com:7777/php/php.log'
|
18
|
+
|
19
|
+
def execute
|
20
|
+
|
21
|
+
@opts = command_options
|
22
|
+
@args = arguments
|
23
|
+
|
24
|
+
@ec2_connection = Brightpearl::MySQL::ec2
|
25
|
+
@terminal_width = Brightpearl::Terminal::get_terminal_width
|
26
|
+
|
27
|
+
opts_validate
|
28
|
+
opts_routing
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
def opts_validate
|
33
|
+
|
34
|
+
watch = 0
|
35
|
+
watch = watch + 1 if @opts[:watchPHP]
|
36
|
+
watch = watch + 1 if @opts[:watchJava]
|
37
|
+
|
38
|
+
if watch >= 2
|
39
|
+
Brightpearl::Terminal::error('You can only watch one set of logs at a time', "Please set only 1 one of the following flags: #{Brightpearl::Terminal::format_flag('p', false)} #{Brightpearl::Terminal::format_flag('j', false)}", true)
|
40
|
+
elsif watch == 0
|
41
|
+
@opts[:watchPHP] = true
|
42
|
+
end
|
43
|
+
|
44
|
+
if @opts[:compare]
|
45
|
+
[@args[0], @args[1]].each do |version_number|
|
46
|
+
if version_number.nil?
|
47
|
+
Brightpearl::Terminal::error('Missing arguments', ["When using the #{Brightpearl::Terminal::format_flag('c')} the system expects #{Brightpearl::Terminal::format_highlight('2 arguments ')} \xe2\x80\x94 application version numbers.", "An example of a valid command would be: #{Brightpearl::Terminal::format_command('bp p l -c 4.76.6 4.78.4')}"], true)
|
48
|
+
end
|
49
|
+
validate_version_number(version_number)
|
50
|
+
end
|
51
|
+
else
|
52
|
+
unless @args[0].nil?
|
53
|
+
validate_version_number(@args[0])
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
def opts_routing
|
60
|
+
|
61
|
+
if @opts[:watchPHP]
|
62
|
+
watch_php
|
63
|
+
elsif @opts[:watchJava]
|
64
|
+
watch_java
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
def watch_php
|
70
|
+
|
71
|
+
unless @opts[:skipFetch]
|
72
|
+
fetch_php_logs
|
73
|
+
end
|
74
|
+
|
75
|
+
begin
|
76
|
+
|
77
|
+
data_previous = nil
|
78
|
+
if @opts[:compare]
|
79
|
+
data_previous = []
|
80
|
+
sql_1 = "SELECT COUNT(*) AS frequency, account_version, error_message, error_file, error_line FROM brightpearl.php_logs WHERE account_version='#{@args[0]}' GROUP BY error_message, error_file, error_line ORDER BY frequency DESC"
|
81
|
+
data_previous_result = @ec2_connection.query(sql_1)
|
82
|
+
data_previous_result.each_hash do |result|
|
83
|
+
data_previous << result
|
84
|
+
end
|
85
|
+
sql_2 = "SELECT COUNT(*) AS frequency, account_version, error_message, error_file, error_line FROM brightpearl.php_logs WHERE account_version='#{@args[1]}' GROUP BY error_message, error_file, error_line HAVING frequency > 1 ORDER BY frequency DESC"
|
86
|
+
data = @ec2_connection.query(sql_2)
|
87
|
+
else
|
88
|
+
if @args[0].nil?
|
89
|
+
sql = 'SELECT COUNT(*) AS frequency, account_version, error_message, error_file, error_line FROM brightpearl.php_logs GROUP BY error_file, error_line ORDER BY frequency DESC'
|
90
|
+
else
|
91
|
+
sql = "SELECT COUNT(*) AS frequency, account_version, error_message, error_file, error_line FROM brightpearl.php_logs WHERE account_version='#{@args[0]}' GROUP BY error_file, error_line ORDER BY frequency DESC"
|
92
|
+
end
|
93
|
+
data = @ec2_connection.query(sql)
|
94
|
+
end
|
95
|
+
|
96
|
+
column_width_1 = 5
|
97
|
+
column_width_2 = 8
|
98
|
+
column_width_3 = ((@terminal_width - 21).to_f * 0.7).round
|
99
|
+
column_width_4 = (@terminal_width - (column_width_1 + column_width_2 + column_width_3 + 5)) - 5
|
100
|
+
column_width_5 = 5
|
101
|
+
|
102
|
+
puts # PUTS SPACE BEFORE TABLE
|
103
|
+
table(:border => false) do
|
104
|
+
row do
|
105
|
+
column('', :width => column_width_1, :color => 255, :align => 'right')
|
106
|
+
column('Version', :width => column_width_2, :color => 255, :align => 'right')
|
107
|
+
column('Error', :width => column_width_3, :color => 255)
|
108
|
+
column('', :width => column_width_4, :color => 255, :align => 'right')
|
109
|
+
column('', :width => column_width_5, :color => 255, :align => 'left')
|
110
|
+
end
|
111
|
+
row do
|
112
|
+
column('')
|
113
|
+
column('')
|
114
|
+
column('')
|
115
|
+
column('')
|
116
|
+
column('')
|
117
|
+
end
|
118
|
+
data.each_hash do |row_data|
|
119
|
+
row_color = get_color_php_logs(data_previous, row_data)
|
120
|
+
error_file = row_data['error_file'].split('/')
|
121
|
+
error_file = "#{error_file[error_file.count - 2]}/#{error_file[error_file.count - 1]}"
|
122
|
+
row do
|
123
|
+
column(row_data['frequency'], :color => row_color)
|
124
|
+
column(row_data['account_version'], :color => row_color)
|
125
|
+
column(row_data['error_message'][0..(column_width_3 - 1)], :color => row_color)
|
126
|
+
column(error_file[0..(column_width_4 - 1)], :color => row_color)
|
127
|
+
column(row_data['error_line'], :color => row_color)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
puts # PUTS SPACE AFTER TABLE
|
132
|
+
|
133
|
+
rescue Exception => e
|
134
|
+
Brightpearl::Terminal::error('Something went wrong', "#{e.message}", true)
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
def watch_java
|
140
|
+
|
141
|
+
Brightpearl::Terminal::info('Not yet implemented', 'Please wait for Albert to program this and try again later.')
|
142
|
+
exit
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
private
|
147
|
+
|
148
|
+
# Goes off to the BP UI Server logs and fetches data.
|
149
|
+
# @return void
|
150
|
+
def fetch_php_logs
|
151
|
+
|
152
|
+
php_log_data.split("\n").each do |log|
|
153
|
+
log_message = log.force_encoding('utf-8')
|
154
|
+
if log_message =~ /\[(.*)\] (\S)+ (\d)+.(\d)+.(\d)+ (\S)+ - /
|
155
|
+
error_message, error_file, error_line, account_version, account_name, ruid = extract_php_log_components(log_message)
|
156
|
+
unless error_message.nil? || error_file.nil? || error_line.nil? || account_version.nil? || account_name.nil? || ruid.nil?
|
157
|
+
error_color = 248
|
158
|
+
result = @ec2_connection.query("SELECT id FROM php_logs WHERE ruid='#{ruid}' AND error_file='#{error_file.gsub("'",) { "\\'" }}' AND error_line='#{error_line.gsub("'", '')}'")
|
159
|
+
if result.num_rows == 0
|
160
|
+
error_color = 198
|
161
|
+
sql = "INSERT INTO php_logs (
|
162
|
+
ruid,
|
163
|
+
account_version,
|
164
|
+
account_name,
|
165
|
+
error_message,
|
166
|
+
error_message_raw,
|
167
|
+
error_file,
|
168
|
+
error_line,
|
169
|
+
date_fetched
|
170
|
+
) VALUES (
|
171
|
+
'#{ruid}',
|
172
|
+
'#{account_version}',
|
173
|
+
'#{account_name.gsub("'",) { "\\'" }}',
|
174
|
+
'#{error_message.gsub("'",) { "\\'" }}',
|
175
|
+
'#{log_message.gsub("'",) { "\\'" }}',
|
176
|
+
'#{error_file.gsub("'", '')}',
|
177
|
+
'#{error_line}',
|
178
|
+
'#{Time.now}'
|
179
|
+
)"
|
180
|
+
begin
|
181
|
+
@ec2_connection.query(sql)
|
182
|
+
rescue
|
183
|
+
error_output = []
|
184
|
+
error_output << log_message
|
185
|
+
error_output << nil
|
186
|
+
error_output << sql
|
187
|
+
Brightpearl::Terminal::warning('Query Failed', error_output)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
error_parsed = " \x1B[38;5;34m#{account_version}\x1B[0m \xe2\x86\x92 \x1B[38;5;81m#{account_name}\x1B[0m \xe2\x80\x94 \x1B[38;5;#{error_color}m#{error_message} \xe2\x80\x94 #{error_file} \xe2\x80\x94 Line #{error_line}"
|
191
|
+
puts "#{error_parsed[0..(@terminal_width - 2)]}\x1B[0m"
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
end
|
197
|
+
|
198
|
+
# Gets PHP Log data from EC2
|
199
|
+
# @return String
|
200
|
+
def php_log_data
|
201
|
+
|
202
|
+
raw_log_data = ''
|
203
|
+
raw_log_uris = [
|
204
|
+
LOG_URI_EUW1,
|
205
|
+
LOG_URI_EUW2,
|
206
|
+
LOG_URI_USE1,
|
207
|
+
LOG_URI_USE2,
|
208
|
+
LOG_URI_USW1,
|
209
|
+
LOG_URI_USW2,
|
210
|
+
LOG_URI_STG1,
|
211
|
+
LOG_URI_STG2,
|
212
|
+
]
|
213
|
+
raw_log_uris.each do |log_uri|
|
214
|
+
Brightpearl::Terminal::output("Retrieving data from: #{log_uri}")
|
215
|
+
raw_log_data << RestClient.get(log_uri)
|
216
|
+
end
|
217
|
+
|
218
|
+
# # Mock Data
|
219
|
+
# file_data_1 = File.open('/Users/Albert/Brightpearl/log_1.txt', 'rb')
|
220
|
+
# file_data_2 = File.open('/Users/Albert/Brightpearl/log_2.txt', 'rb')
|
221
|
+
# raw_log_data << file_data_1.read
|
222
|
+
# raw_log_data << file_data_2.read
|
223
|
+
|
224
|
+
raw_log_data
|
225
|
+
|
226
|
+
end
|
227
|
+
|
228
|
+
# Extracts the warning message + filename as 2 different strings.
|
229
|
+
# @return Array
|
230
|
+
def extract_php_log_components(log_message)
|
231
|
+
# Patterns for the 2 ways FILE & LINE could be displayed.
|
232
|
+
patterns = [
|
233
|
+
[/\(\/php-scripts(.*)(line )(\d)+\)/, /\/php-scripts(.*)\.(\w){3,5}/, /line (\d){1,5}/, 'line '],
|
234
|
+
[/in \/php-scripts(.*):(\d)+\z/, /\/php-scripts(.*)\.(\w){3,5}/, /:(\d){1,5}\z/, ':']
|
235
|
+
]
|
236
|
+
patterns.each do |pattern|
|
237
|
+
filename_part = log_message.match(pattern[0])
|
238
|
+
unless filename_part.nil?
|
239
|
+
account_version = extract_account_version(log_message)
|
240
|
+
account_name = extract_account_name(log_message)
|
241
|
+
ruid = extract_ruid(log_message)
|
242
|
+
message = extract_message(pattern, log_message)
|
243
|
+
line_number = extract_line_number(pattern, filename_part)
|
244
|
+
filename_part = extract_filename(pattern, filename_part)
|
245
|
+
return [message, filename_part, line_number, account_version, account_name, ruid]
|
246
|
+
end
|
247
|
+
end
|
248
|
+
[nil, nil, nil, nil, nil, nil]
|
249
|
+
end
|
250
|
+
|
251
|
+
def extract_account_version(log_message)
|
252
|
+
account_version = log_message.match(/(\d)\.(\d){2,3}\.(\d){1,2}/)
|
253
|
+
account_version[0]
|
254
|
+
end
|
255
|
+
|
256
|
+
def extract_account_name(log_message)
|
257
|
+
account_name = log_message.match(/] (.*) (\d)\.(\d){2,3}\.(\d){1,2}/)
|
258
|
+
account_name = account_name.to_s.sub('] ', '')
|
259
|
+
account_name.to_s.sub(/\s(\d)\.(\d){2,3}\.(\d){1,2}/, '')
|
260
|
+
end
|
261
|
+
|
262
|
+
def extract_ruid(log_message)
|
263
|
+
ruid = log_message.match(/(\d)\.(\d){2,3}\.(\d){1,2} (\S+)-(\S+)-(\S+)-(\S+)-(\S+)\s- /)
|
264
|
+
ruid = ruid.to_s.sub(/(\d)\.(\d){2,3}\.(\d){1,2} /, '')
|
265
|
+
ruid.to_s.sub(' - ', '')
|
266
|
+
end
|
267
|
+
|
268
|
+
def extract_message(pattern, log_message)
|
269
|
+
log_message = log_message.sub(pattern[0], '')
|
270
|
+
log_message = log_message.sub(/\[(.*)(\d)\.(\d){2,3}\.(\d){1,2} (.*)\s-\s/, '').strip
|
271
|
+
|
272
|
+
# Reduce multiple (identical) errors into identical log message(s).
|
273
|
+
log_message = log_message.sub(/WARNING unlink\((.*)\): No such file or directory/, 'WARNING unlink([VARIOUS]): No such file or directory')
|
274
|
+
log_message = log_message.sub(/WARNING file_get_contents\((.*)\): failed to open stream/, 'WARNING file_get_contents: [VARIOUS] failed to open stream')
|
275
|
+
log_message = log_message.sub(/WARNING file_put_contents\((.*)\): failed to open stream/, 'WARNING file_put_contents: [VARIOUS] failed to open stream')
|
276
|
+
log_message = log_message.sub(/'Exception' with message 'Error writing request to server:\shttp:\/\/(.*)-service(.*)\z/, "'Exception' with message 'Error writing request to server: http://[VARIOUS]:9026/[VARIOUS]-service/[VARIOUS]")
|
277
|
+
log_message = log_message.sub(/'Exception' with message 'Unable to read response, or response is empty:\shttp:\/\/(.*)-service(.*)\z/, "Exception' with message 'Unable to read response, or response is empty: http://[VARIOUS]:9026/[VARIOUS]-service/[VARIOUS]")
|
278
|
+
log_message = log_message.sub(/EXCEPTION exception 'Exception' with message 'Read timed out after 60 seconds:\shttp:\/\/(.*)-service(.*)\z/, "EXCEPTION exception 'Exception' with message 'Read timed out after 60 seconds: http://[VARIOUS]:9026/[VARIOUS]-service/[VARIOUS]")
|
279
|
+
|
280
|
+
return log_message
|
281
|
+
end
|
282
|
+
|
283
|
+
def extract_line_number(pattern, filename_part)
|
284
|
+
line = filename_part.to_s.match(pattern[2])
|
285
|
+
line.to_s.sub(pattern[3], '')
|
286
|
+
end
|
287
|
+
|
288
|
+
def extract_filename(pattern, filename_part)
|
289
|
+
filename_part = filename_part.to_s.match(pattern[1])
|
290
|
+
filename_part = filename_part.to_s.sub(/\A\/(.*)(\d)\.(\d){2,3}\.(\d){1,2}\//, '')
|
291
|
+
if filename_part.include?('lib-lib')
|
292
|
+
filename_part = filename_part.to_s.sub('lib-lib', 'private/library')
|
293
|
+
else
|
294
|
+
filename_part = "public/brightpearl/#{filename_part}"
|
295
|
+
end
|
296
|
+
filename_part
|
297
|
+
end
|
298
|
+
|
299
|
+
# For lines which are not 'parseable', this cleans up the return output.
|
300
|
+
# @deprecated
|
301
|
+
# @return String
|
302
|
+
def skipped_output(log_message)
|
303
|
+
skipped_output = log_message.sub(/\A\[(.*)\] /, '')
|
304
|
+
skipped_output = skipped_output.sub(/(\w)+-(\w)+-(\w)+-(\w)+-(\w)+ - /, '')
|
305
|
+
account_name = skipped_output.match(/\A(\S)+/)
|
306
|
+
account_version = skipped_output.match(/(\d)\.(\d){2,3}\.(\d){1,2}/)
|
307
|
+
skipped_output = skipped_output.sub(account_name.to_s, '')
|
308
|
+
skipped_output = skipped_output.sub(account_version.to_s, '')
|
309
|
+
skipped_output = skipped_output.strip
|
310
|
+
"\x1B[38;5;188m Skipping: \x1B[0m \x1B[88m\xe2\x86\x92\x1B[0m \x1B[38;5;255m#{account_version}\x1B[0m \x1B[38;5;111m#{account_name}\x1B[0m \x1B[38;5;240m\xe2\x80\x94\x1B[0m \x1B[38;5;240m#{skipped_output}\x1B[0m"
|
311
|
+
end
|
312
|
+
|
313
|
+
# Checks whether a version number is valid and data exists for it in the Database
|
314
|
+
# @return void
|
315
|
+
def validate_version_number(version_number)
|
316
|
+
unless version_number =~ /\A\d\.\d{1,3}\.\d{1,2}\z/
|
317
|
+
Brightpearl::Terminal::error('Invalid version number', "#{Brightpearl::Terminal::format_highlight(version_number)} is not a valid version number.", true)
|
318
|
+
end
|
319
|
+
sql = "SELECT id FROM php_logs WHERE account_version='#{version_number}' LIMIT 1"
|
320
|
+
begin
|
321
|
+
result = @ec2_connection.query(sql)
|
322
|
+
rescue
|
323
|
+
Brightpearl::Terminal::warning('Query Failed', sql)
|
324
|
+
end
|
325
|
+
unless result.num_rows > 0
|
326
|
+
Brightpearl::Terminal::info('No data', "We currently don't have any data for version: #{Brightpearl::Terminal::format_highlight(version_number)}")
|
327
|
+
exit
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
# Determines color of log message in results table.
|
332
|
+
# If the :compare flag is set, checks if log message exists in previous version and if so, makes it red.
|
333
|
+
# @return Integer
|
334
|
+
def get_color_php_logs(data_previous, row_data)
|
335
|
+
row_color = 240
|
336
|
+
unless data_previous.nil?
|
337
|
+
row_color = 196
|
338
|
+
data_previous.each do |data_previous_row|
|
339
|
+
if data_previous_row['error_message'] == row_data['error_message'] &&
|
340
|
+
data_previous_row['error_file'] == row_data['error_file'] &&
|
341
|
+
data_previous_row['error_line'] == row_data['error_line']
|
342
|
+
row_color = 240
|
343
|
+
elsif data_previous_row['error_message'] == row_data['error_message'] &&
|
344
|
+
data_previous_row['error_file'] == row_data['error_file'] &&
|
345
|
+
data_previous_row['error_line'] != row_data['error_line']
|
346
|
+
row_color = 248
|
347
|
+
end
|
348
|
+
|
349
|
+
end
|
350
|
+
end
|
351
|
+
row_color
|
352
|
+
end
|
353
|
+
|
354
|
+
end
|
355
|
+
|
356
|
+
end
|
data/lib/routes/review.rb
CHANGED
@@ -4,10 +4,36 @@ module BrightpearlCommand
|
|
4
4
|
|
5
5
|
def execute
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
@opts = command_options
|
8
|
+
@args = arguments
|
9
|
+
@git = Brightpearl::Git.new
|
10
|
+
opts_validate
|
11
|
+
opts_routing
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
def opts_validate
|
16
|
+
|
17
|
+
unless @args.any?
|
18
|
+
system('bp r -h')
|
19
|
+
exit
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
def opts_routing
|
25
|
+
|
26
|
+
review
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
def review
|
31
|
+
|
32
|
+
current_branch = @git.current_branch_for_repo(Brightpearl::Config.param(Brightpearl::Config::WORKSTATION_PATH_TO_BP_CODE))
|
33
|
+
|
34
|
+
@git.check_branch_exists_somewhere(@args[0])
|
35
|
+
|
36
|
+
system("BR=#{@args[0]} && bp g co -U ${BR} && bp g d -l ${BR} && bp g co #{current_branch}")
|
11
37
|
|
12
38
|
end
|
13
39
|
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module BrightpearlCommand
|
2
|
+
|
3
|
+
class ScriptsApiDocs < ::Convoy::ActionCommand::Base
|
4
|
+
|
5
|
+
def execute
|
6
|
+
|
7
|
+
@opts = command_options
|
8
|
+
@args = arguments
|
9
|
+
opts_validate
|
10
|
+
opts_routing
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
def opts_validate
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
def opts_routing
|
19
|
+
|
20
|
+
build_api_docs
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
def build_api_docs
|
25
|
+
|
26
|
+
if Brightpearl::Tools::this_is_a_mac
|
27
|
+
|
28
|
+
Brightpearl::Terminal::info('Building API Docs')
|
29
|
+
system("sshpass -p#{Brightpearl::Config.param(Brightpearl::Config::VM_USER_PASSWORD)} ssh #{Brightpearl::Config.param(Brightpearl::Config::VM_USER)}@#{Brightpearl::Config.param(Brightpearl::Config::VM_IP)} -t 'su root && cd /brightpearl-source/dev-vm-control-scripts && ./build-api-docs'")
|
30
|
+
|
31
|
+
else
|
32
|
+
|
33
|
+
Brightpearl::Terminal::info('This functionality has not yet been implemented on your OS', ["Currently only works on #{Brightpearl::Terminal::format_action(Brightpearl::Config.param(Brightpearl::Config::WORKSTATION_OS))}", nil, "You are on #{Brightpearl::Terminal::format_action(Brightpearl::Config.param(Brightpearl::Config::WORKSTATION_OS))}"])
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,196 @@
|
|
1
|
+
module BrightpearlCommand
|
2
|
+
|
3
|
+
class ScriptsBranchCleaner < ::Convoy::ActionCommand::Base
|
4
|
+
|
5
|
+
def execute
|
6
|
+
|
7
|
+
@opts = command_options
|
8
|
+
@args = arguments
|
9
|
+
@git = Brightpearl::Git.new
|
10
|
+
|
11
|
+
opts_validate
|
12
|
+
opts_routing
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
def opts_validate
|
17
|
+
|
18
|
+
if @opts[:scanLocal] && @opts[:scanRemote]
|
19
|
+
Brightpearl::Terminal::error("Cannot scan #{Brightpearl::Terminal::format_action('local')} & #{Brightpearl::Terminal::format_action('remote')} simultaneously", "Must use either the #{Brightpearl::Terminal::format_flag('l')} or the #{Brightpearl::Terminal::format_flag('r')} \xe2\x80\x94 cannot use both.", true)
|
20
|
+
end
|
21
|
+
|
22
|
+
if @opts[:scanLocal] == false && @opts[:scanRemote] == false
|
23
|
+
@opts[:scanLocal] = true
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
def opts_routing
|
29
|
+
|
30
|
+
clean
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
def clean
|
35
|
+
|
36
|
+
local_remote = @opts[:scanRemote] ? 'remote' : 'local'
|
37
|
+
|
38
|
+
Brightpearl::Terminal::info('Running branch cleaner', "Gathering list of #{Brightpearl::Terminal::format_action(local_remote)} branches which are safe to delete.")
|
39
|
+
|
40
|
+
branches_code, branches_db = get_historic_branches
|
41
|
+
umc_branches = get_unsafe_branches(branches_code, branches_db)
|
42
|
+
fnl_branches_cd, fnl_branches_db = get_final_branches(branches_code, branches_db, umc_branches)
|
43
|
+
|
44
|
+
puts "\n"
|
45
|
+
|
46
|
+
atleast_one_error = false
|
47
|
+
|
48
|
+
if umc_branches.any?
|
49
|
+
Brightpearl::Terminal::warning("The following branches have commits which #{Brightpearl::Terminal::format_invalid('have not been merged to', true)} #{Brightpearl::Terminal::format_branch(Brightpearl::Git::MASTER)} \xe2\x80\x94 #{Brightpearl::Terminal::format_directory(@git.get_repo_shorthand(Brightpearl::Config.param(Brightpearl::Config::WORKSTATION_PATH_TO_BP_CODE)))}", umc_branches, false)
|
50
|
+
atleast_one_error = true
|
51
|
+
end
|
52
|
+
|
53
|
+
if atleast_one_error
|
54
|
+
unless Brightpearl::Terminal::prompt_yes_no('Skip these branches?', ["The above branch(es) have unmerged commits and will be #{Brightpearl::Terminal::format_action('skipped')} in the removal process."])
|
55
|
+
Brightpearl::Terminal::abort(nil, nil, true, false)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
unless fnl_branches_cd.any? && fnl_branches_db.any?
|
60
|
+
Brightpearl::Terminal::info('Nothing to delete', nil, false)
|
61
|
+
exit
|
62
|
+
end
|
63
|
+
|
64
|
+
@git.show_branches_draw_table(fnl_branches_cd, fnl_branches_db)
|
65
|
+
|
66
|
+
unless Brightpearl::Terminal::prompt_yes_no('Remove these branches?', ["By continuing, the above branches will be #{Brightpearl::Terminal::format_action('removed permanently')}"], 'Are you absolutely sure you want to continue?', false)
|
67
|
+
Brightpearl::Terminal::abort(nil, nil, true, false)
|
68
|
+
end
|
69
|
+
|
70
|
+
repo_cd = Brightpearl::Config.param(Brightpearl::Config::WORKSTATION_PATH_TO_BP_CODE)
|
71
|
+
repo_db = Brightpearl::Config.param(Brightpearl::Config::WORKSTATION_PATH_TO_BP_DB)
|
72
|
+
|
73
|
+
branch_count = 0
|
74
|
+
|
75
|
+
fnl_branches_cd.each do |branch|
|
76
|
+
branch_name = branch[:"#{Brightpearl::Git::REFNAME}"]
|
77
|
+
commands = []
|
78
|
+
if @opts[:scanLocal]
|
79
|
+
commands << "git branch -D #{branch_name}"
|
80
|
+
else
|
81
|
+
commands << "git branch --unset-upstream #{branch_name}"
|
82
|
+
commands << "git push origin --delete #{branch_name}"
|
83
|
+
end
|
84
|
+
Brightpearl::Terminal::command(commands, repo_cd)
|
85
|
+
branch_count = branch_count + 1
|
86
|
+
end
|
87
|
+
|
88
|
+
fnl_branches_db.each do |branch|
|
89
|
+
branch_name = branch[:"#{Brightpearl::Git::REFNAME}"]
|
90
|
+
commands = []
|
91
|
+
if @opts[:scanLocal]
|
92
|
+
commands << "git branch -D #{branch_name}"
|
93
|
+
else
|
94
|
+
commands << "git branch --unset-upstream #{branch_name}"
|
95
|
+
commands << "git push origin --delete #{branch_name}"
|
96
|
+
end
|
97
|
+
Brightpearl::Terminal::command(commands, repo_db)
|
98
|
+
branch_count = branch_count + 1
|
99
|
+
end
|
100
|
+
|
101
|
+
Brightpearl::Terminal::success("#{Brightpearl::Terminal::format_highlight(branch_count)} branches successfully #{Brightpearl::Terminal::format_action('removed')}")
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
# Gets all (remote) branches where last commit was longer than 1 month ago and committer is CONFIG::GIT_USERNAME
|
108
|
+
# @return Array
|
109
|
+
def get_historic_branches
|
110
|
+
|
111
|
+
committer_name = Brightpearl::Config.param(Brightpearl::Config::GIT_USERNAME)
|
112
|
+
date_1_month_ago = DateTime.now << 1
|
113
|
+
|
114
|
+
fnl_branches_cd = []
|
115
|
+
fnl_branches_db = []
|
116
|
+
|
117
|
+
if @opts[:scanRemote]
|
118
|
+
repos = @git.get_remote_branches(Brightpearl::Git::SORT_DATE)
|
119
|
+
else
|
120
|
+
repos = @git.get_local_branches(Brightpearl::Git::SORT_DATE)
|
121
|
+
end
|
122
|
+
|
123
|
+
repos[0].each do |branch|
|
124
|
+
unless branch[:"#{Brightpearl::Git::REFNAME}"].match(Brightpearl::Git::RELEASE_BRANCH_REGEX) || branch[:"#{Brightpearl::Git::COMMITTER_DATE}"] > date_1_month_ago
|
125
|
+
if branch[:"#{Brightpearl::Git::COMMITTER_NAME}"] == committer_name && @opts[:anyName] == false
|
126
|
+
fnl_branches_cd << branch
|
127
|
+
elsif @opts[:anyName] == true
|
128
|
+
fnl_branches_cd << branch
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
repos[1].each do |branch|
|
133
|
+
unless branch[:"#{Brightpearl::Git::REFNAME}"].match(Brightpearl::Git::RELEASE_BRANCH_REGEX) || branch[:"#{Brightpearl::Git::COMMITTER_DATE}"] > date_1_month_ago
|
134
|
+
if branch[:"#{Brightpearl::Git::COMMITTER_NAME}"] == committer_name && @opts[:anyName] == false
|
135
|
+
fnl_branches_db << branch
|
136
|
+
elsif @opts[:anyName] == true
|
137
|
+
fnl_branches_db << branch
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
fnl_branches_cd.uniq!
|
143
|
+
fnl_branches_db.uniq!
|
144
|
+
return fnl_branches_cd, fnl_branches_db
|
145
|
+
end
|
146
|
+
|
147
|
+
# Gets array of branches which still have commits NOT in master.
|
148
|
+
# @return Array
|
149
|
+
def get_unsafe_branches(branches_code, branches_db)
|
150
|
+
branches_unmerged_commits = []
|
151
|
+
origin = @opts[:scanLocal] ? '' : 'origin/'
|
152
|
+
branches_code.each do |code_branch|
|
153
|
+
missing_commits = Brightpearl::Terminal::command_capture("git log #{origin}master..#{origin}#{code_branch[:"#{Brightpearl::Git::REFNAME}"]}", Brightpearl::Config.param(Brightpearl::Config::WORKSTATION_PATH_TO_BP_CODE))
|
154
|
+
if missing_commits[0] != ''
|
155
|
+
puts missing_commits
|
156
|
+
branches_unmerged_commits << code_branch[:"#{Brightpearl::Git::REFNAME}"]
|
157
|
+
end
|
158
|
+
end
|
159
|
+
branches_db.each do |db_branch|
|
160
|
+
missing_commits = Brightpearl::Terminal::command_capture("git log #{origin}master..#{origin}#{db_branch[:"#{Brightpearl::Git::REFNAME}"]}", Brightpearl::Config.param(Brightpearl::Config::WORKSTATION_PATH_TO_BP_DB))
|
161
|
+
if missing_commits[0] != ''
|
162
|
+
puts missing_commits
|
163
|
+
branches_unmerged_commits << db_branch[:"#{Brightpearl::Git::REFNAME}"]
|
164
|
+
end
|
165
|
+
end
|
166
|
+
branches_unmerged_commits.uniq!
|
167
|
+
branches_unmerged_commits.sort_by! { |m| m.downcase }
|
168
|
+
branches_unmerged_commits
|
169
|
+
end
|
170
|
+
|
171
|
+
# Gets final array of branches which are safe to delete.
|
172
|
+
# @return Array
|
173
|
+
def get_final_branches(branches_code, branches_db, umc_branches)
|
174
|
+
|
175
|
+
puts branches_code
|
176
|
+
puts umc_branches
|
177
|
+
exit
|
178
|
+
|
179
|
+
fnl_branches_cd = []
|
180
|
+
fnl_branches_db = []
|
181
|
+
branches_code.each do |branch|
|
182
|
+
unless umc_branches.include?(branch[:"#{Brightpearl::Git::REFNAME}"])
|
183
|
+
fnl_branches_cd << branch
|
184
|
+
end
|
185
|
+
end
|
186
|
+
branches_db.each do |branch|
|
187
|
+
unless umc_branches.include?(branch[:"#{Brightpearl::Git::REFNAME}"])
|
188
|
+
fnl_branches_db << branch
|
189
|
+
end
|
190
|
+
end
|
191
|
+
return fnl_branches_cd, fnl_branches_db
|
192
|
+
end
|
193
|
+
|
194
|
+
end
|
195
|
+
|
196
|
+
end
|