brightpearl-cli 1.1.0 → 1.2.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 +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
|