pindo 5.0.4 → 5.0.6
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/lib/pindo/base/githelper.rb +1 -1
- data/lib/pindo/client/pgyer_feishu_oauth_cli.rb +313 -0
- data/lib/pindo/client/pgyeruploadclient.rb +275 -153
- data/lib/pindo/command/android/autobuild.rb +121 -0
- data/lib/pindo/command/android/build.rb +113 -0
- data/lib/pindo/command/android/debug.rb +60 -14
- data/lib/pindo/command/android.rb +5 -2
- data/lib/pindo/command/ios/autobuild.rb +6 -0
- data/lib/pindo/command/ios/build.rb +7 -1
- data/lib/pindo/command/unity/apk.rb +69 -6
- data/lib/pindo/command/utils/renewcert.rb +2 -2
- data/lib/pindo/module/android/apk_helper.rb +91 -0
- data/lib/pindo/module/android/base_helper.rb +293 -0
- data/lib/pindo/module/android/build_helper.rb +112 -0
- data/lib/pindo/module/android/gradle_helper.rb +48 -0
- data/lib/pindo/module/android/so_helper.rb +18 -0
- data/lib/pindo/module/build/buildhelper.rb +50 -37
- data/lib/pindo/module/build/unityhelper.rb +16 -16
- data/lib/pindo/module/pgyer/pgyerhelper.rb +14 -11
- data/lib/pindo/module/xcode/xcodehelper.rb +73 -73
- data/lib/pindo/version.rb +1 -1
- metadata +71 -11
@@ -1,10 +1,10 @@
|
|
1
|
-
|
2
1
|
require 'uri'
|
3
2
|
require 'json'
|
4
3
|
require 'faraday'
|
5
4
|
require 'securerandom'
|
6
5
|
require 'pindo/base/aeshelper'
|
7
6
|
require 'typhoeus'
|
7
|
+
require 'thread'
|
8
8
|
|
9
9
|
module Pindo
|
10
10
|
|
@@ -44,6 +44,13 @@ module Pindo
|
|
44
44
|
@pgyer_aes_key = config_json["pgyerapps_aes_key"]
|
45
45
|
|
46
46
|
@token = load_token
|
47
|
+
|
48
|
+
# 添加互斥锁用于线程安全
|
49
|
+
@upload_eTags_mutex = Mutex.new
|
50
|
+
@tasks_queue_mutex = Mutex.new
|
51
|
+
@active_tasks_mutex = Mutex.new
|
52
|
+
@upload_failed_mutex = Mutex.new # 为上传失败状态添加互斥锁
|
53
|
+
@upload_failed = false
|
47
54
|
|
48
55
|
rescue => error
|
49
56
|
raise Informative, "PgyerUploadClient 初始化失败!"
|
@@ -72,9 +79,12 @@ module Pindo
|
|
72
79
|
|
73
80
|
def upload_file(binary_file:nil, isAttach:false)
|
74
81
|
|
82
|
+
raise Informative, "上传文件不能为空" if binary_file.nil? || !File.exist?(binary_file)
|
83
|
+
|
75
84
|
@upload_binary_file = binary_file
|
76
85
|
@file_size = File.size(@upload_binary_file)
|
77
86
|
@progress_bar = PgyerUploadProgressBar.new(upload_total_size:@file_size)
|
87
|
+
@upload_failed = false # 重置上传失败标志
|
78
88
|
|
79
89
|
extension = File.extname(@upload_binary_file)
|
80
90
|
filename = File.basename(@upload_binary_file)
|
@@ -104,135 +114,231 @@ module Pindo
|
|
104
114
|
|
105
115
|
upload_result = nil
|
106
116
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
117
|
+
begin
|
118
|
+
file_size_param = 1.00 * @file_size / 1024 /1024
|
119
|
+
result_data = post_upload_url_req(upload_path_key:upload_path_key, file_ceil_size:file_size_param.ceil)
|
120
|
+
|
121
|
+
if result_data.nil? || !result_data.has_key?("data") || !result_data["data"].has_key?("uploadId")
|
122
|
+
raise Informative, "获取上传ID失败,请检查网络或服务器状态"
|
123
|
+
end
|
124
|
+
|
125
|
+
upload_id = result_data["data"]["uploadId"]
|
126
|
+
# 创建统一的任务队列
|
127
|
+
@tasks_queue = Queue.new
|
128
|
+
@worker_threads = []
|
129
|
+
upload_params_list = result_data["data"]["uploadParamsList"]
|
130
|
+
upload_item_num = upload_params_list.length
|
131
|
+
@expected_parts = upload_item_num # 保存预期的分片数量
|
132
|
+
task_num = upload_item_num
|
133
|
+
retry_count = 5
|
134
|
+
|
135
|
+
# 合理限制线程数
|
136
|
+
if task_num < 2
|
137
|
+
task_num = 2
|
138
|
+
end
|
128
139
|
|
129
|
-
|
140
|
+
if task_num > 30
|
141
|
+
task_num = 30
|
142
|
+
end
|
130
143
|
|
144
|
+
# 根据系统CPU核心数自动调整线程数
|
145
|
+
available_cores = Etc.respond_to?(:nprocessors) ? Etc.nprocessors : 4
|
146
|
+
task_num = [task_num, available_cores * 2].min
|
147
|
+
|
148
|
+
# 设置重试次数并将所有任务加入队列
|
149
|
+
upload_params_list.each do |item|
|
150
|
+
item["retryCount"] = retry_count
|
151
|
+
@tasks_queue.push(item)
|
152
|
+
end
|
131
153
|
|
132
|
-
|
154
|
+
puts "切分个数: #{upload_item_num}"
|
155
|
+
puts "线程个数: #{task_num}"
|
156
|
+
puts "重试次数: #{retry_count}"
|
157
|
+
puts
|
158
|
+
|
159
|
+
Funlog.instance.fancyinfo_start("开始上传...")
|
160
|
+
@upload_eTags = []
|
161
|
+
@active_tasks = 0 # 跟踪活动任务数量
|
162
|
+
|
163
|
+
continuous_upload_data_req(concurrency:task_num)
|
164
|
+
|
165
|
+
# 检查上传是否全部成功
|
166
|
+
if upload_failed? || @upload_eTags.length != @expected_parts
|
167
|
+
upload_result = nil
|
168
|
+
Funlog.instance.fancyinfo_error("文件#{@upload_binary_file} 上传失败! 😭😭😭")
|
169
|
+
return upload_result
|
170
|
+
end
|
133
171
|
|
134
|
-
|
172
|
+
result_data = post_upload_finish_req(upload_path_key:upload_path_key, upload_id:upload_id, eTags:@upload_eTags)
|
135
173
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
174
|
+
if result_data && result_data["code"] == 200
|
175
|
+
upload_result = upload_path_key
|
176
|
+
Funlog.instance.fancyinfo_success("文件#{@upload_binary_file} 上传成功! 😎😎😎")
|
177
|
+
else
|
178
|
+
upload_result = nil
|
179
|
+
error_msg = result_data && result_data["msg"] ? result_data["msg"] : "未知错误"
|
180
|
+
Funlog.instance.fancyinfo_error("文件#{@upload_binary_file} 上传失败: #{error_msg} 😭😭😭")
|
181
|
+
end
|
182
|
+
|
183
|
+
rescue => e
|
184
|
+
upload_result = nil
|
185
|
+
Funlog.instance.fancyinfo_error("文件上传过程发生异常: #{e.message} 😭😭😭")
|
186
|
+
ensure
|
187
|
+
# 确保所有工作线程都被清理
|
188
|
+
cleanup_worker_threads
|
142
189
|
end
|
143
190
|
|
144
191
|
return upload_result
|
145
192
|
|
146
193
|
end
|
147
194
|
|
148
|
-
|
149
|
-
def
|
150
|
-
|
151
|
-
for i in 0..@upload_params_list.length-1 do
|
152
|
-
@upload_params_list[i]["retryCount"] = retry_count
|
153
|
-
end
|
154
|
-
|
155
|
-
while @upload_params_list.size > 0
|
156
|
-
upload_params_list_temp = []
|
157
|
-
#每次最大5个线程上传
|
158
|
-
for i in 1..task_num do
|
159
|
-
upload_params_list_temp << @upload_params_list.shift
|
160
|
-
end
|
161
|
-
hydra = Typhoeus::Hydra.new
|
162
|
-
while upload_params_list_temp.size > 0
|
163
|
-
upload_params_item = upload_params_list_temp.shift
|
164
|
-
unless upload_params_item.nil?
|
165
|
-
single_task_upload_part_data_req(upload_params_item:upload_params_item, hydra_handle:hydra)
|
166
|
-
end
|
167
|
-
end
|
168
|
-
hydra.run
|
169
|
-
end
|
170
|
-
|
195
|
+
# 安全地检查上传失败状态
|
196
|
+
def upload_failed?
|
197
|
+
@upload_failed_mutex.synchronize { @upload_failed }
|
171
198
|
end
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
@
|
199
|
+
|
200
|
+
# 安全地设置上传失败状态
|
201
|
+
def set_upload_failed(error_msg = nil)
|
202
|
+
@upload_failed_mutex.synchronize do
|
203
|
+
@upload_failed = true
|
204
|
+
Funlog.instance.fancyinfo_error("上传失败: #{error_msg}") if error_msg
|
177
205
|
end
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
206
|
+
end
|
207
|
+
|
208
|
+
# 清理所有工作线程
|
209
|
+
def cleanup_worker_threads
|
210
|
+
@worker_threads.each do |thread|
|
211
|
+
# 尝试安全终止线程
|
212
|
+
thread.exit if thread.alive?
|
182
213
|
end
|
183
|
-
|
184
|
-
|
185
|
-
return @eTags
|
214
|
+
@worker_threads.clear
|
186
215
|
end
|
187
216
|
|
188
|
-
def
|
189
|
-
|
217
|
+
def continuous_upload_data_req(concurrency:1)
|
218
|
+
# 初始化活动任务计数和条件变量
|
219
|
+
@active_tasks = 0
|
220
|
+
@task_complete_cv = ConditionVariable.new
|
221
|
+
|
222
|
+
# 初始化连续上传,最多启动concurrency个并发任务
|
223
|
+
start_tasks = [concurrency, @tasks_queue.size].min
|
224
|
+
start_tasks.times { schedule_next_task }
|
225
|
+
|
226
|
+
# 设置超时保护
|
227
|
+
timeout_seconds = 300 # 5分钟超时
|
228
|
+
start_time = Time.now
|
229
|
+
|
230
|
+
# 等待所有任务完成
|
231
|
+
@tasks_queue_mutex.synchronize do
|
232
|
+
while (@active_tasks > 0 || !@tasks_queue.empty?) && !upload_failed?
|
233
|
+
# 添加超时保护
|
234
|
+
remaining_time = timeout_seconds - (Time.now - start_time)
|
235
|
+
if remaining_time <= 0
|
236
|
+
set_upload_failed("上传任务超时")
|
237
|
+
break
|
238
|
+
end
|
239
|
+
|
240
|
+
# 等待任务完成通知,最多等待30秒
|
241
|
+
@task_complete_cv.wait(@tasks_queue_mutex, [remaining_time, 30].min)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
# 检查所有分片是否都上传成功
|
246
|
+
if @upload_eTags.length != @expected_parts && !upload_failed?
|
247
|
+
set_upload_failed("部分分片上传失败,已上传#{@upload_eTags.length}/#{@expected_parts}")
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
def schedule_next_task
|
252
|
+
# 检查是否应该停止调度
|
253
|
+
return if upload_failed?
|
254
|
+
|
255
|
+
# 尝试从队列中获取下一个任务
|
256
|
+
@tasks_queue_mutex.synchronize do
|
257
|
+
unless @tasks_queue.empty?
|
258
|
+
upload_params_item = @tasks_queue.pop
|
259
|
+
@active_tasks_mutex.synchronize { @active_tasks += 1 }
|
260
|
+
|
261
|
+
# 异步处理任务,不阻塞主线程
|
262
|
+
worker_thread = Thread.new do
|
263
|
+
begin
|
264
|
+
process_upload_task(upload_params_item)
|
265
|
+
rescue => e
|
266
|
+
# 捕获并记录任务处理过程中的异常
|
267
|
+
set_upload_failed("处理分片#{upload_params_item["partNo"]}时出错: #{e.message}")
|
268
|
+
ensure
|
269
|
+
# 任务完成后,减少活动任务计数并通知等待线程
|
270
|
+
@active_tasks_mutex.synchronize { @active_tasks -= 1 }
|
271
|
+
|
272
|
+
# 如果队列不为空,调度下一个任务
|
273
|
+
schedule_next_task if !upload_failed?
|
274
|
+
|
275
|
+
# 通知等待线程任务已完成
|
276
|
+
@tasks_queue_mutex.synchronize { @task_complete_cv.broadcast }
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
# 保存线程引用以便后续清理
|
281
|
+
@worker_threads << worker_thread
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
def process_upload_task(upload_params_item)
|
190
287
|
upload_url = upload_params_item["signedUrl"]
|
191
288
|
part_no = upload_params_item["partNo"]
|
192
|
-
|
289
|
+
|
193
290
|
file_size_ele = 1024 * 1024 * 5 #5M
|
194
|
-
start_position = file_size_ele * (part_no -1)
|
291
|
+
start_position = file_size_ele * (part_no - 1)
|
195
292
|
if part_no * file_size_ele > @file_size
|
196
|
-
|
293
|
+
read_length = @file_size - start_position
|
197
294
|
else
|
198
|
-
|
295
|
+
read_length = file_size_ele
|
199
296
|
end
|
200
|
-
|
297
|
+
|
201
298
|
file = File.open(@upload_binary_file, "rb")
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
299
|
+
begin
|
300
|
+
file.seek(start_position)
|
301
|
+
put_data = file.read(read_length)
|
302
|
+
|
303
|
+
request = create_req(upload_url:upload_url, body_data:put_data, read_length:read_length)
|
304
|
+
|
305
|
+
# 设置上传进度回调
|
306
|
+
upload_size_last = 0
|
307
|
+
request.on_progress do |dltotal, dlnow, ultotal, ulnow|
|
308
|
+
if ulnow && ulnow > upload_size_last
|
309
|
+
upload_size_last = ulnow
|
310
|
+
@progress_bar.update_upload_index(upload_part:part_no, upload_size:ulnow)
|
311
|
+
@progress_bar.update_upload_progress()
|
312
|
+
end
|
210
313
|
end
|
211
|
-
|
212
|
-
|
213
|
-
|
314
|
+
|
315
|
+
# 设置请求超时
|
316
|
+
request.options[:timeout] = 300 # 5分钟超时
|
317
|
+
|
318
|
+
# 执行请求并等待完成
|
319
|
+
response = request.run
|
320
|
+
|
321
|
+
# 处理响应结果
|
214
322
|
if response.success?
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
323
|
+
@progress_bar.complete_upload_index(upload_part:part_no, complete_size:read_length)
|
324
|
+
etag = response.headers["ETag"]
|
325
|
+
if etag.nil? || etag.empty?
|
326
|
+
raise "服务器返回的ETag为空"
|
327
|
+
end
|
328
|
+
eTag_item = { partNumber: part_no, tag: etag}
|
329
|
+
@upload_eTags_mutex.synchronize { @upload_eTags << eTag_item }
|
219
330
|
else
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
end
|
331
|
+
@progress_bar.delete_upload_index(upload_part:part_no)
|
332
|
+
upload_params_item["retryCount"] = upload_params_item["retryCount"] - 1
|
333
|
+
if upload_params_item["retryCount"] > 0
|
334
|
+
# 重试任务
|
335
|
+
@tasks_queue_mutex.synchronize { @tasks_queue.push(upload_params_item) }
|
336
|
+
else
|
337
|
+
set_upload_failed("文件#{@upload_binary_file} 分片#{part_no}上传失败: HTTP #{response.code}")
|
338
|
+
end
|
229
339
|
end
|
230
|
-
|
231
|
-
|
232
|
-
if hydra_handle.nil?
|
233
|
-
request.run
|
234
|
-
else
|
235
|
-
hydra_handle.queue(request)
|
340
|
+
ensure
|
341
|
+
file.close
|
236
342
|
end
|
237
343
|
end
|
238
344
|
|
@@ -284,26 +390,30 @@ module Pindo
|
|
284
390
|
tags:eTags
|
285
391
|
}
|
286
392
|
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
393
|
+
begin
|
394
|
+
con = HttpClient.create_instance_with_proxy
|
395
|
+
res = con.post do |req|
|
396
|
+
req.url boss_url
|
397
|
+
req.headers['Content-Type'] = 'application/json'
|
398
|
+
req.headers['token'] = @token["token"]
|
399
|
+
req.body = body_params.to_json
|
400
|
+
req.options.timeout = 120 # 设置2分钟超时
|
401
|
+
end
|
294
402
|
|
403
|
+
result_data = nil
|
404
|
+
if !res.body.nil?
|
405
|
+
result_data = JSON.parse(res.body)
|
406
|
+
end
|
295
407
|
|
296
|
-
|
297
|
-
|
298
|
-
|
408
|
+
return result_data
|
409
|
+
rescue => e
|
410
|
+
Funlog.instance.fancyinfo_error("完成上传请求失败: #{e.message}")
|
411
|
+
return nil
|
299
412
|
end
|
300
|
-
|
301
|
-
return result_data
|
302
|
-
|
303
413
|
end
|
304
414
|
|
305
415
|
|
306
|
-
|
416
|
+
def post_upload_url_req(upload_path_key:nil, file_ceil_size:nil)
|
307
417
|
|
308
418
|
boss_url = @baseurl + @request_config["multi_signed_url_upload"]
|
309
419
|
|
@@ -313,22 +423,26 @@ module Pindo
|
|
313
423
|
fileSize:file_ceil_size
|
314
424
|
}
|
315
425
|
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
426
|
+
begin
|
427
|
+
con = HttpClient.create_instance_with_proxy
|
428
|
+
res = con.post do |req|
|
429
|
+
req.url boss_url
|
430
|
+
req.headers['Content-Type'] = 'application/json'
|
431
|
+
req.headers['token'] = @token["token"]
|
432
|
+
req.body = body_params.to_json
|
433
|
+
req.options.timeout = 60 # 设置1分钟超时
|
434
|
+
end
|
323
435
|
|
436
|
+
result_data = nil
|
437
|
+
if !res.body.nil?
|
438
|
+
result_data = JSON.parse(res.body)
|
439
|
+
end
|
324
440
|
|
325
|
-
|
326
|
-
|
327
|
-
|
441
|
+
return result_data
|
442
|
+
rescue => e
|
443
|
+
Funlog.instance.fancyinfo_error("获取上传URL失败: #{e.message}")
|
444
|
+
return nil
|
328
445
|
end
|
329
|
-
|
330
|
-
return result_data
|
331
|
-
|
332
446
|
end
|
333
447
|
|
334
448
|
class PgyerUploadProgressBar
|
@@ -341,50 +455,58 @@ module Pindo
|
|
341
455
|
attr_accessor :is_done
|
342
456
|
|
343
457
|
def initialize(upload_total_size:nil, draw_char:'>')
|
344
|
-
|
345
|
-
|
346
458
|
@upload_total_size = upload_total_size
|
347
459
|
@draw_char = draw_char
|
348
460
|
@last_update_time = (Time.now.to_f * 1000).to_i #毫秒
|
349
461
|
|
350
462
|
@complete_size = 0
|
351
463
|
@update_ing_size = {}
|
352
|
-
|
353
464
|
@is_done = false
|
465
|
+
|
466
|
+
# 添加互斥锁来保护进度条更新
|
467
|
+
@mutex = Mutex.new
|
354
468
|
end
|
355
469
|
|
356
470
|
def update_upload_index(upload_part:nil, upload_size:nil)
|
357
|
-
@
|
471
|
+
@mutex.synchronize do
|
472
|
+
@update_ing_size[upload_part] = upload_size
|
473
|
+
end
|
358
474
|
end
|
359
475
|
|
360
476
|
def delete_upload_index(upload_part:nil)
|
361
|
-
@
|
477
|
+
@mutex.synchronize do
|
478
|
+
@update_ing_size[upload_part] = 0
|
479
|
+
end
|
362
480
|
end
|
363
481
|
|
364
482
|
def complete_upload_index(upload_part:nil, complete_size:nil)
|
365
|
-
@
|
366
|
-
|
483
|
+
@mutex.synchronize do
|
484
|
+
@complete_size = @complete_size + complete_size
|
485
|
+
@update_ing_size[upload_part] = 0
|
486
|
+
end
|
367
487
|
end
|
368
488
|
|
369
489
|
def update_upload_progress()
|
370
490
|
time_now = (Time.now.to_f * 1000).to_i #毫秒
|
371
491
|
if time_now - @last_update_time > 80
|
372
|
-
@
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
492
|
+
@mutex.synchronize do
|
493
|
+
@last_update_time = time_now
|
494
|
+
total_num = @upload_total_size
|
495
|
+
index_num = @complete_size
|
496
|
+
@update_ing_size.each do |key, value|
|
497
|
+
index_num = index_num + value
|
498
|
+
end
|
499
|
+
|
500
|
+
progress_str = sprintf("%.2f", 100.0 * index_num / total_num )
|
501
|
+
total_size = sprintf("%.2f", 1.00 * total_num / 1024 /1024 )
|
502
|
+
upload_size = sprintf("%.2f", 1.00 * index_num / 1024 /1024 )
|
503
|
+
index = 40.0 * index_num / total_num
|
504
|
+
upload_message = "已上传:#{upload_size}MB|#{progress_str}\%【" + (@draw_char * (index/1).floor).ljust(40.0, '_') + "】Total:#{total_size}MB"
|
505
|
+
Funlog.instance.fancyinfo_update(upload_message)
|
506
|
+
if index_num == total_num && !@is_done
|
507
|
+
@is_done = true
|
508
|
+
Funlog.instance.fancyinfo_success(upload_message)
|
509
|
+
end
|
388
510
|
end
|
389
511
|
end
|
390
512
|
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'highline/import'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'pindo/base/executable'
|
4
|
+
require 'pindo/module/build/buildhelper'
|
5
|
+
require 'pindo/module/android/build_helper'
|
6
|
+
|
7
|
+
module Pindo
|
8
|
+
class Command
|
9
|
+
class Android < Command
|
10
|
+
class Autobuild < Android
|
11
|
+
include Appselect
|
12
|
+
|
13
|
+
self.summary = '打包Android工程并发布到蒲公英'
|
14
|
+
self.description = <<-DESC
|
15
|
+
编译Android包并支持上传到测试平台。
|
16
|
+
|
17
|
+
支持功能:
|
18
|
+
* 编译Debug/Release包
|
19
|
+
* 上传到测试平台
|
20
|
+
* 发送测试通知
|
21
|
+
|
22
|
+
使用示例:
|
23
|
+
$ pindo android autobuild # 编译Debug包
|
24
|
+
$ pindo android autobuild --release # 编译Release包
|
25
|
+
$ pindo android autobuild --upload # 编译并上传
|
26
|
+
$ pindo android autobuild --send # 编译上传并发送通知
|
27
|
+
$ pindo android autobuild --proj=myapp # 指定项目名称
|
28
|
+
|
29
|
+
DESC
|
30
|
+
|
31
|
+
def self.options
|
32
|
+
[
|
33
|
+
['--release', '使用release模式构建'],
|
34
|
+
['--proj', '指定上传到测试平台的项目名称'],
|
35
|
+
['--upload', '上传编译后的apk到测试平台'],
|
36
|
+
['--send', '上传成功后发送测试通知']
|
37
|
+
].concat(super)
|
38
|
+
end
|
39
|
+
|
40
|
+
def initialize(argv)
|
41
|
+
@args_release_flag = argv.flag?('release', false)
|
42
|
+
@args_upload_flag = argv.flag?('upload', false)
|
43
|
+
@args_send_flag = argv.flag?('send', false)
|
44
|
+
@args_proj_name = argv.option('proj')
|
45
|
+
|
46
|
+
|
47
|
+
if @args_send_flag
|
48
|
+
@args_upload_flag = true
|
49
|
+
end
|
50
|
+
|
51
|
+
super
|
52
|
+
@additional_args = argv.remainder!
|
53
|
+
end
|
54
|
+
|
55
|
+
def run
|
56
|
+
pindo_project_dir = Dir.pwd
|
57
|
+
build_helper = Pindo::BuildHelper.share_instance
|
58
|
+
project_type = build_helper.project_type(pindo_project_dir)
|
59
|
+
|
60
|
+
args_temp = []
|
61
|
+
args_temp << "--proj=#{@args_proj_name}" if @args_proj_name
|
62
|
+
args_temp << "--upload" if @args_upload_flag
|
63
|
+
args_temp << "--send" if @args_send_flag
|
64
|
+
|
65
|
+
case project_type
|
66
|
+
when :ios
|
67
|
+
puts "iOS 工程, 请使用 pindo ios build"
|
68
|
+
when :android
|
69
|
+
android_autobuild
|
70
|
+
when :unity
|
71
|
+
Pindo::Command::Unity::Apk::run(args_temp)
|
72
|
+
else
|
73
|
+
raise Informative, "当前目录不是工程目录,不能编译"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def android_autobuild
|
80
|
+
|
81
|
+
pindo_project_dir = Dir.pwd
|
82
|
+
build_helper = Pindo::BuildHelper.share_instance
|
83
|
+
|
84
|
+
if @args_upload_flag
|
85
|
+
build_helper.check_check_and_install_cliff(pindo_project_dir)
|
86
|
+
is_need_add_tag,tag_action_parms = build_helper.check_is_need_add_tag?(pindo_project_dir)
|
87
|
+
if is_need_add_tag
|
88
|
+
Pindo::Command::Dev::Tag::run(tag_action_parms)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
app_info_obj = nil
|
93
|
+
if @args_upload_flag
|
94
|
+
proj_name = @args_proj_name
|
95
|
+
app_info_obj = PgyerHelper.share_instace.prepare_upload(working_directory:Dir.pwd, proj_name:proj_name)
|
96
|
+
end
|
97
|
+
|
98
|
+
android_build_helper = Pindo::AndroidBuildHelper.share_instance
|
99
|
+
apk_path = android_build_helper.auto_build_apk(pindo_project_dir, !@args_release_flag)
|
100
|
+
ipa_file_upload = Dir.glob(apk_path).max_by {|f| File.mtime(f)}
|
101
|
+
|
102
|
+
if !ipa_file_upload.nil? && !app_info_obj.nil?
|
103
|
+
description = nil
|
104
|
+
result_data = PgyerHelper.share_instace.start_upload(app_info_obj:app_info_obj, ipa_file_upload:ipa_file_upload, description:description)
|
105
|
+
if !result_data.nil? && !result_data["data"].nil? && !result_data["data"]["id"].nil?
|
106
|
+
msg_data = PgyerHelper.share_instace.make_msg_data(app_info_obj:app_info_obj, app_version_info_obj:result_data["data"])
|
107
|
+
PgyerHelper.share_instace.print_app_version_info(msg_data:msg_data)
|
108
|
+
if @args_send_flag
|
109
|
+
PgyerHelper.share_instace.send_apptest_wechat_msg(msg_data:msg_data)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
system "open #{pindo_project_dir}"
|
115
|
+
|
116
|
+
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|