pindo 5.13.4 → 5.13.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/aeshelper.rb +15 -13
- data/lib/pindo/command/appstore/adhocbuild.rb +61 -30
- data/lib/pindo/command/appstore/autobuild.rb +18 -5
- data/lib/pindo/command/appstore/autoresign.rb +294 -163
- data/lib/pindo/command/ios/autobuild.rb +6 -0
- data/lib/pindo/command/jps/upload.rb +1 -1
- data/lib/pindo/command/unity/autobuild.rb +6 -0
- data/lib/pindo/config/build_info_manager.rb +32 -0
- data/lib/pindo/config/ios_config_parser.rb +163 -1
- data/lib/pindo/module/cert/cert_helper.rb +1 -1
- data/lib/pindo/module/pgyer/pgyerhelper.rb +162 -0
- data/lib/pindo/module/task/model/build/ios_build_adhoc_task.rb +94 -15
- data/lib/pindo/module/task/model/build/ios_build_appstore_task.rb +41 -14
- data/lib/pindo/module/task/model/build/ios_build_dev_task.rb +23 -14
- data/lib/pindo/module/task/model/ipa_local_resign_task.rb +189 -0
- data/lib/pindo/module/task/model/jps_upload_task.rb +65 -21
- data/lib/pindo/module/xcode/cocoapods_helper.rb +127 -4
- data/lib/pindo/module/xcode/ipa_resign_helper.rb +1 -1
- data/lib/pindo/module/xcode/res/xcode_res_handler.rb +9 -8
- data/lib/pindo/module/xcode/xcode_app_config.rb +9 -1
- data/lib/pindo/module/xcode/xcode_build_config.rb +7 -2
- data/lib/pindo/module/xcode/xcode_swark_helper.rb +9 -1
- data/lib/pindo/version.rb +1 -1
- metadata +2 -1
|
@@ -21,13 +21,14 @@ module Pindo
|
|
|
21
21
|
class IosConfigParser
|
|
22
22
|
include Singleton
|
|
23
23
|
|
|
24
|
-
attr_reader :config_file_path, :config_json
|
|
24
|
+
attr_reader :config_file_path, :config_json, :app_repo_name
|
|
25
25
|
|
|
26
26
|
def initialize
|
|
27
27
|
@config_file_path = nil
|
|
28
28
|
@config_json = nil
|
|
29
29
|
@config_data = {}
|
|
30
30
|
@overrides = {}
|
|
31
|
+
@app_repo_name = nil # 保存原始 Bundle ID,用于配置仓库路径
|
|
31
32
|
end
|
|
32
33
|
|
|
33
34
|
# 加载配置文件
|
|
@@ -67,6 +68,7 @@ module Pindo
|
|
|
67
68
|
@config_json = nil
|
|
68
69
|
@config_data = {}
|
|
69
70
|
@overrides = {}
|
|
71
|
+
@app_repo_name = nil
|
|
70
72
|
end
|
|
71
73
|
|
|
72
74
|
# ==================== 账号信息 ====================
|
|
@@ -292,6 +294,155 @@ module Pindo
|
|
|
292
294
|
!@config_json.nil?
|
|
293
295
|
end
|
|
294
296
|
|
|
297
|
+
# ==================== AdHoc 发布配置合并 ====================
|
|
298
|
+
|
|
299
|
+
# 合并 AdHoc 发布配置
|
|
300
|
+
# 1. 替换所有 Bundle ID 为 AdHoc 配置的 Bundle ID(确保使用 AdHoc 证书)
|
|
301
|
+
# 2. 合并第三方 SDK 配置(Facebook、AdMob、AppLovin)
|
|
302
|
+
# 3. 合并 app_setting(排除主机和 URL 配置)
|
|
303
|
+
# @param adhoc_config_dir [String] AdHoc 配置仓库目录
|
|
304
|
+
# @return [Boolean] 是否成功
|
|
305
|
+
def modify_config_with_adhoc(adhoc_config_dir:)
|
|
306
|
+
return false unless loaded?
|
|
307
|
+
return false if adhoc_config_dir.nil? || adhoc_config_dir.empty?
|
|
308
|
+
|
|
309
|
+
begin
|
|
310
|
+
# 1. 读取 AdHoc 配置
|
|
311
|
+
adhoc_config_file = File.join(adhoc_config_dir, "config.json")
|
|
312
|
+
unless File.exist?(adhoc_config_file)
|
|
313
|
+
puts "AdHoc 配置文件不存在: #{adhoc_config_file}"
|
|
314
|
+
return false
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
adhoc_config_json = JSON.parse(File.read(adhoc_config_file))
|
|
318
|
+
|
|
319
|
+
# 1.5 替换 Apple ID(使用 AdHoc 配置的 Apple ID)
|
|
320
|
+
if adhoc_config_json.dig('account_info', 'apple_acount_id')
|
|
321
|
+
original_apple_id = @config_json.dig('account_info', 'apple_acount_id')
|
|
322
|
+
adhoc_apple_id = adhoc_config_json['account_info']['apple_acount_id']
|
|
323
|
+
|
|
324
|
+
if original_apple_id && adhoc_apple_id && original_apple_id != adhoc_apple_id
|
|
325
|
+
@config_json['account_info']['apple_acount_id'] = adhoc_apple_id
|
|
326
|
+
puts " 替换 Apple ID:"
|
|
327
|
+
puts " 原始 Apple ID: #{original_apple_id}"
|
|
328
|
+
puts " AdHoc Apple ID: #{adhoc_apple_id}"
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
# 如果 AdHoc 配置包含 company_name,也一并替换
|
|
332
|
+
if adhoc_config_json.dig('account_info', 'acount_company_name')
|
|
333
|
+
@config_json['account_info']['acount_company_name'] = adhoc_config_json['account_info']['acount_company_name']
|
|
334
|
+
end
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
# 2. 替换所有 Bundle ID(使用 AdHoc 配置的 Bundle ID)
|
|
338
|
+
original_bundle_id = @config_json.dig('app_info', 'app_identifier')
|
|
339
|
+
adhoc_bundle_id = adhoc_config_json.dig('app_info', 'app_identifier')
|
|
340
|
+
|
|
341
|
+
if original_bundle_id && adhoc_bundle_id && original_bundle_id != adhoc_bundle_id
|
|
342
|
+
puts " 替换 Bundle ID 前缀:"
|
|
343
|
+
puts " 原始前缀: #{original_bundle_id}"
|
|
344
|
+
puts " AdHoc 前缀: #{adhoc_bundle_id}"
|
|
345
|
+
|
|
346
|
+
# Bundle ID 字段映射表
|
|
347
|
+
bundle_id_keys = [
|
|
348
|
+
'app_identifier', # 主应用
|
|
349
|
+
'app_identifier_pushcontent', # Push Content Extension
|
|
350
|
+
'app_identifier_pushservice', # Push Service Extension
|
|
351
|
+
'app_identifier_keyboard', # Keyboard Extension
|
|
352
|
+
'app_identifier_imessage', # iMessage Extension
|
|
353
|
+
'app_identifier_extension', # 通用 Extension
|
|
354
|
+
'app_identifier_siri', # Siri Extension
|
|
355
|
+
'app_identifier_siriui', # Siri UI Extension
|
|
356
|
+
'app_identifier_widget', # Widget Extension
|
|
357
|
+
'app_identifier_extensionad', # 广告 Extension
|
|
358
|
+
'app_identifier_extensionporn',# Porn Extension
|
|
359
|
+
'app_identifier_watchapp', # Watch App
|
|
360
|
+
'app_identifier_watchapp_extension' # Watch App Extension
|
|
361
|
+
]
|
|
362
|
+
|
|
363
|
+
# 遍历所有 Bundle ID 字段并替换前缀
|
|
364
|
+
bundle_id_keys.each do |key|
|
|
365
|
+
current_value = @config_json.dig('app_info', key)
|
|
366
|
+
next if current_value.nil? || current_value.empty?
|
|
367
|
+
|
|
368
|
+
# 如果当前值以原始主 Bundle ID 开头,替换为 AdHoc Bundle ID
|
|
369
|
+
if current_value.start_with?(original_bundle_id)
|
|
370
|
+
# 计算后缀部分(如 .extension、.keyboard 等)
|
|
371
|
+
suffix = current_value[original_bundle_id.length..-1]
|
|
372
|
+
new_value = adhoc_bundle_id + suffix
|
|
373
|
+
|
|
374
|
+
@config_json['app_info'][key] = new_value
|
|
375
|
+
puts " ✓ #{key}: #{current_value} → #{new_value}"
|
|
376
|
+
end
|
|
377
|
+
end
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
# 2.5 替换 App Group ID 和 iCloud Container ID
|
|
381
|
+
if original_bundle_id && adhoc_bundle_id && original_bundle_id != adhoc_bundle_id
|
|
382
|
+
# 处理 app_group_id (格式: group.com.example.app)
|
|
383
|
+
if @config_json.dig('app_setting', 'app_group_id')
|
|
384
|
+
current_group_id = @config_json['app_setting']['app_group_id']
|
|
385
|
+
if current_group_id.include?(original_bundle_id)
|
|
386
|
+
new_group_id = current_group_id.gsub(original_bundle_id, adhoc_bundle_id)
|
|
387
|
+
@config_json['app_setting']['app_group_id'] = new_group_id
|
|
388
|
+
puts " ✓ app_group_id: #{current_group_id} → #{new_group_id}"
|
|
389
|
+
end
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
# 处理 app_icloud_id (格式: iCloud.com.example.app)
|
|
393
|
+
if @config_json.dig('app_setting', 'app_icloud_id')
|
|
394
|
+
current_icloud_id = @config_json['app_setting']['app_icloud_id']
|
|
395
|
+
if current_icloud_id.include?(original_bundle_id)
|
|
396
|
+
new_icloud_id = current_icloud_id.gsub(original_bundle_id, adhoc_bundle_id)
|
|
397
|
+
@config_json['app_setting']['app_icloud_id'] = new_icloud_id
|
|
398
|
+
puts " ✓ app_icloud_id: #{current_icloud_id} → #{new_icloud_id}"
|
|
399
|
+
end
|
|
400
|
+
end
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
# 3. 合并第三方 SDK 配置
|
|
404
|
+
# Facebook 配置
|
|
405
|
+
if adhoc_config_json.dig('app_info', 'facebook_app_id')
|
|
406
|
+
@config_json['app_info']['facebook_app_id'] = adhoc_config_json['app_info']['facebook_app_id']
|
|
407
|
+
@config_json['app_info']['facebook_client_token'] = adhoc_config_json['app_info']['facebook_client_token']
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
# AdMob 配置
|
|
411
|
+
if @config_json.dig('app_info', 'admob_app_id') && adhoc_config_json.dig('app_info', 'admob_app_id')
|
|
412
|
+
@config_json['app_info']['admob_app_id'] = adhoc_config_json['app_info']['admob_app_id']
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
# AppLovin 配置
|
|
416
|
+
if @config_json.dig('app_info', 'applovin_app_id') && adhoc_config_json.dig('app_info', 'applovin_app_id')
|
|
417
|
+
@config_json['app_info']['applovin_app_id'] = adhoc_config_json['app_info']['applovin_app_id']
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
# 4. 合并 app_setting(排除主机和 URL 配置)
|
|
421
|
+
excluded_keys = ['kGUKeyAppClientHost', 'kGUKeyResBaseUrl', 'app_web_host', 'app_client_url']
|
|
422
|
+
|
|
423
|
+
if @config_json['app_setting'] && adhoc_config_json['app_setting']
|
|
424
|
+
@config_json['app_setting'].each_key do |key|
|
|
425
|
+
next if excluded_keys.include?(key)
|
|
426
|
+
|
|
427
|
+
if adhoc_config_json['app_setting'][key]
|
|
428
|
+
@config_json['app_setting'][key] = adhoc_config_json['app_setting'][key]
|
|
429
|
+
end
|
|
430
|
+
end
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
# 5. 重新解析配置数据,同步更新 @config_data
|
|
434
|
+
# 这样 bundle_id、bundle_id_pushcontent 等属性方法才能返回替换后的值
|
|
435
|
+
parse_config_data
|
|
436
|
+
|
|
437
|
+
puts "✅ 已替换 Apple ID、Bundle ID 并合并 AdHoc 配置(Facebook、AdMob、AppLovin)"
|
|
438
|
+
true
|
|
439
|
+
rescue => e
|
|
440
|
+
puts "合并发布配置失败: #{e.message}"
|
|
441
|
+
puts e.backtrace.join("\n")
|
|
442
|
+
false
|
|
443
|
+
end
|
|
444
|
+
end
|
|
445
|
+
|
|
295
446
|
# ==================== 调试和信息 ====================
|
|
296
447
|
|
|
297
448
|
# 打印所有配置信息(用于调试)
|
|
@@ -346,6 +497,17 @@ module Pindo
|
|
|
346
497
|
if @config_json['app_info']
|
|
347
498
|
app_info = @config_json['app_info']
|
|
348
499
|
@config_data[:bundle_id] = app_info['app_identifier']
|
|
500
|
+
|
|
501
|
+
# 保存原始 Bundle ID 作为配置仓库名称(只在第一次设置,后续不覆盖)
|
|
502
|
+
if @app_repo_name.nil? && app_info['app_identifier']
|
|
503
|
+
repo_name = app_info['app_identifier']
|
|
504
|
+
# 如果是通配符 Bundle ID(以 .* 结尾),去除通配符后缀
|
|
505
|
+
if repo_name.end_with?('.*')
|
|
506
|
+
repo_name = repo_name[0...-2] # 去除最后的 .*
|
|
507
|
+
end
|
|
508
|
+
@app_repo_name = repo_name
|
|
509
|
+
end
|
|
510
|
+
|
|
349
511
|
@config_data[:bundle_id_pushcontent] = app_info['app_identifier_pushcontent']
|
|
350
512
|
@config_data[:bundle_id_pushservice] = app_info['app_identifier_pushservice']
|
|
351
513
|
@config_data[:bundle_id_keyboard] = app_info['app_identifier_keyboard']
|
|
@@ -259,7 +259,7 @@ module Pindo
|
|
|
259
259
|
provision_start_name = "Development"
|
|
260
260
|
cert_sub_dir = cert_type.downcase
|
|
261
261
|
elsif cert_type.downcase.include?("adhoc")
|
|
262
|
-
provision_start_name = "
|
|
262
|
+
provision_start_name = "AdHoc"
|
|
263
263
|
cert_sub_dir = "adhoc"
|
|
264
264
|
else
|
|
265
265
|
provision_start_name = "AppStore"
|
|
@@ -220,6 +220,168 @@ module Pindo
|
|
|
220
220
|
}
|
|
221
221
|
end
|
|
222
222
|
|
|
223
|
+
# AdHoc 专用工作流选择
|
|
224
|
+
# 筛选条件:
|
|
225
|
+
# 1. package_type 匹配
|
|
226
|
+
# 2. tab_name 必须包含 "提交包"
|
|
227
|
+
#
|
|
228
|
+
# @param project_id [String] 项目ID
|
|
229
|
+
# @param package_type [String] 包类型(ipa/apk/zip/app)
|
|
230
|
+
# @return [Hash] 选择的工作流信息
|
|
231
|
+
def select_workflow_for_adhoc(project_id:, package_type:)
|
|
232
|
+
# 1. 从 JPS API 获取可用工作流列表
|
|
233
|
+
workflow_result = @pgyer_client.get_project_workflows(project_id: project_id)
|
|
234
|
+
|
|
235
|
+
if workflow_result.nil? || workflow_result['data'].nil?
|
|
236
|
+
raise Informative, "获取工作流列表失败"
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
workflows = workflow_result['data']
|
|
240
|
+
|
|
241
|
+
if workflows.empty?
|
|
242
|
+
raise Informative, "该项目没有可用的工作流"
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
# 2. 第一层过滤:根据 package_type
|
|
246
|
+
filtered_by_type = workflows.select do |w|
|
|
247
|
+
if w['packageType']
|
|
248
|
+
case package_type
|
|
249
|
+
when 'ipa'
|
|
250
|
+
w['packageType'] == 'ipa'
|
|
251
|
+
when 'apk'
|
|
252
|
+
w['packageType'] == 'apk'
|
|
253
|
+
when 'zip'
|
|
254
|
+
w['packageType'] == 'zip'
|
|
255
|
+
when 'app'
|
|
256
|
+
w['packageType'] == 'app'
|
|
257
|
+
else
|
|
258
|
+
true
|
|
259
|
+
end
|
|
260
|
+
else
|
|
261
|
+
# 如果没有 packageType 字段,保留(后续通过名称筛选)
|
|
262
|
+
true
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
# 3. 第二层过滤:tab_name 必须包含 "提交包"
|
|
267
|
+
adhoc_workflows = filtered_by_type.select do |w|
|
|
268
|
+
tab_name = w['tabName'] || w['tab_name'] || ''
|
|
269
|
+
tab_name.include?('提交包')
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
if adhoc_workflows.empty?
|
|
273
|
+
raise Informative, "未找到符合条件的 AdHoc 工作流\n" \
|
|
274
|
+
"要求:package_type=#{package_type} 且 tab_name 包含 '提交包'\n" \
|
|
275
|
+
"请检查 JPS 工作流配置"
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
# 4. 根据匹配数量决定选择方式
|
|
279
|
+
workflow = nil
|
|
280
|
+
|
|
281
|
+
if adhoc_workflows.size == 1
|
|
282
|
+
# 只有 1 个匹配,自动选择
|
|
283
|
+
workflow = adhoc_workflows.first
|
|
284
|
+
else
|
|
285
|
+
# 有多个匹配,让用户选择
|
|
286
|
+
require 'highline/import'
|
|
287
|
+
cli = HighLine.new
|
|
288
|
+
|
|
289
|
+
workflow_choices = adhoc_workflows.map do |w|
|
|
290
|
+
tab_name = w['tabName'] || w['tab_name']
|
|
291
|
+
workflow_id = w['id'] || w['workflow_id']
|
|
292
|
+
"#{tab_name} (ID: #{workflow_id})"
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
selected = cli.choose do |menu|
|
|
296
|
+
menu.prompt = "请选择 AdHoc 工作流:"
|
|
297
|
+
menu.choices(*workflow_choices)
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
# 提取选择的工作流
|
|
301
|
+
selected_index = workflow_choices.index(selected)
|
|
302
|
+
workflow = adhoc_workflows[selected_index]
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
# 5. 返回标准化的工作流信息
|
|
306
|
+
{
|
|
307
|
+
workflow_id: workflow['id'] || workflow['workflow_id'],
|
|
308
|
+
tab_name: workflow['tabName'] || workflow['tab_name'],
|
|
309
|
+
package_type: workflow['packageType'] || package_type,
|
|
310
|
+
package_name: workflow['packageName'] || workflow['package_name'] || '',
|
|
311
|
+
manage_type: workflow['manageType'] || workflow['manage_type'] || ''
|
|
312
|
+
}
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
# 获取 AdHoc 上传信息
|
|
316
|
+
# 用于 adhoc 编译命令,不保存配置到 JPSBuildConfig.json
|
|
317
|
+
#
|
|
318
|
+
# @param working_directory [String] 工作目录
|
|
319
|
+
# @param package_type [String] 包类型(ipa/apk/zip/app)
|
|
320
|
+
# @param proj_name [String] 项目名称(可选)
|
|
321
|
+
# @param skip_config_file [Boolean] 是否跳过从 config.json 获取项目名称(默认 false)
|
|
322
|
+
# @return [Array] [app_info_obj, workflow_info]
|
|
323
|
+
def get_adhoc_upload_info(working_directory:, package_type:, proj_name: nil, skip_config_file: false)
|
|
324
|
+
upload_proj_name = proj_name
|
|
325
|
+
|
|
326
|
+
# 1. 项目名称获取逻辑
|
|
327
|
+
# 1.1 如果 proj_name 为空,从环境变量获取
|
|
328
|
+
if upload_proj_name.nil? || upload_proj_name.empty?
|
|
329
|
+
upload_proj_name = ENV['PINDO_PROJECT_NAME']
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
# 1.2 如果仍为空且未禁用,从 IosConfigParser 获取
|
|
333
|
+
if (upload_proj_name.nil? || upload_proj_name.empty?) && !skip_config_file
|
|
334
|
+
require 'pindo/config/ios_config_parser'
|
|
335
|
+
config_parser = Pindo::IosConfigParser.instance
|
|
336
|
+
if config_parser.config_json
|
|
337
|
+
upload_proj_name = config_parser.config_json.dig("project_info", "project_name")
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
# 1.3 如果还是为空,让用户输入
|
|
342
|
+
if upload_proj_name.nil? || upload_proj_name.empty?
|
|
343
|
+
require 'highline/import'
|
|
344
|
+
puts "\n未找到项目名称配置"
|
|
345
|
+
upload_proj_name = ask("请输入 JPS 项目名称: ") do |q|
|
|
346
|
+
q.validate = /\S+/
|
|
347
|
+
q.responses[:not_valid] = "项目名称不能为空"
|
|
348
|
+
end
|
|
349
|
+
upload_proj_name = upload_proj_name.strip if upload_proj_name
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
# 2. 确保已登录
|
|
353
|
+
unless login
|
|
354
|
+
raise Informative, "请先登录 JPS 网站"
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
# 3. 获取 app_info_obj
|
|
358
|
+
app_info_obj = find_app_info_with_obj_list(proj_name: upload_proj_name)
|
|
359
|
+
|
|
360
|
+
unless app_info_obj
|
|
361
|
+
raise Informative, "未找到项目: #{upload_proj_name},请检查项目名称是否正确"
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
# 4. 获取 AdHoc 工作流(调用专用函数)
|
|
365
|
+
workflow_info = select_workflow_for_adhoc(
|
|
366
|
+
project_id: app_info_obj["id"],
|
|
367
|
+
package_type: package_type
|
|
368
|
+
)
|
|
369
|
+
|
|
370
|
+
unless workflow_info
|
|
371
|
+
raise Informative, "未能获取 AdHoc 工作流信息"
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
# 5. 输出最终选择的项目和工作流
|
|
375
|
+
puts "\n✓ 项目: #{app_info_obj['projectName']}"
|
|
376
|
+
puts "✓ 工作流: #{workflow_info[:tab_name]}"
|
|
377
|
+
|
|
378
|
+
# 6. 保存项目名称到实例变量
|
|
379
|
+
@proj_name = upload_proj_name
|
|
380
|
+
|
|
381
|
+
# 7. 返回结果(不保存配置到 JPSBuildConfig.json)
|
|
382
|
+
return app_info_obj, workflow_info
|
|
383
|
+
end
|
|
384
|
+
|
|
223
385
|
def prepare_upload(working_directory:nil, proj_name:nil, package_type:nil)
|
|
224
386
|
upload_proj_name = proj_name
|
|
225
387
|
if upload_proj_name.nil? || upload_proj_name.empty?
|
|
@@ -46,6 +46,38 @@ module Pindo
|
|
|
46
46
|
# 1. 加载配置到 IosConfigParser 单例
|
|
47
47
|
load_ios_config
|
|
48
48
|
|
|
49
|
+
# 1.5 获取 AdHoc 配置目录并合并配置
|
|
50
|
+
adhoc_config_dir = nil
|
|
51
|
+
begin
|
|
52
|
+
config_parser = Pindo::IosConfigParser.instance
|
|
53
|
+
config_json = config_parser.config_json
|
|
54
|
+
|
|
55
|
+
# 根据 app_type 获取 AdHoc 配置仓库
|
|
56
|
+
if config_json && config_json['project_info'] && config_json['project_info']['app_type']
|
|
57
|
+
require 'pindo/config/build_info_manager'
|
|
58
|
+
|
|
59
|
+
build_info_manager = Pindo::BuildInfoManager.share_instance
|
|
60
|
+
adhoc_repo_name = build_info_manager.get_deploy_repo_with_modul_name(
|
|
61
|
+
module_name: config_json['project_info']['app_type']
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
if adhoc_repo_name.nil? || adhoc_repo_name.empty?
|
|
65
|
+
raise Informative, "config.json app_type is error!!!"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# 克隆 AdHoc 配置仓库
|
|
69
|
+
adhoc_config_dir = build_info_manager.clong_buildconfig_repo(repo_name: adhoc_repo_name)
|
|
70
|
+
|
|
71
|
+
# 合并 AdHoc 配置
|
|
72
|
+
config_parser.modify_config_with_adhoc(adhoc_config_dir: adhoc_config_dir)
|
|
73
|
+
else
|
|
74
|
+
puts "配置中缺少 app_type,跳过 AdHoc 配置合并"
|
|
75
|
+
end
|
|
76
|
+
rescue => e
|
|
77
|
+
puts "获取 AdHoc 配置失败: #{e.message}"
|
|
78
|
+
adhoc_config_dir = nil
|
|
79
|
+
end
|
|
80
|
+
|
|
49
81
|
# 2. 自动增加版本号
|
|
50
82
|
auto_increase_buildnumber
|
|
51
83
|
|
|
@@ -55,6 +87,16 @@ module Pindo
|
|
|
55
87
|
# 4. 配置 Xcode 项目
|
|
56
88
|
configure_xcode_project
|
|
57
89
|
|
|
90
|
+
# 4.5 安装 Firebase 配置 - 使用 AdHoc 配置仓库目录
|
|
91
|
+
if adhoc_config_dir && File.directory?(adhoc_config_dir)
|
|
92
|
+
require 'pindo/module/xcode/xcode_build_helper'
|
|
93
|
+
|
|
94
|
+
Pindo::XcodeBuildHelper.install_google_plist(
|
|
95
|
+
project_dir: @project_path,
|
|
96
|
+
app_config_dir: adhoc_config_dir
|
|
97
|
+
)
|
|
98
|
+
end
|
|
99
|
+
|
|
58
100
|
# 5. Quark/Swark 处理
|
|
59
101
|
handle_quswark_processing
|
|
60
102
|
|
|
@@ -84,6 +126,58 @@ module Pindo
|
|
|
84
126
|
end
|
|
85
127
|
end
|
|
86
128
|
|
|
129
|
+
# 处理 CocoaPods 依赖(AdHoc 构建)
|
|
130
|
+
def handle_cocoapods
|
|
131
|
+
return unless File.exist?(File.join(@project_path, "Podfile"))
|
|
132
|
+
|
|
133
|
+
require 'pindo/module/xcode/cocoapods_helper'
|
|
134
|
+
require 'pindo/config/pindoconfig'
|
|
135
|
+
|
|
136
|
+
config_parser = Pindo::IosConfigParser.instance
|
|
137
|
+
|
|
138
|
+
# 使用原始 Bundle ID(app_repo_name)作为配置仓库名称
|
|
139
|
+
# 注意:config_parser.bundle_id 在 AdHoc 构建中已被替换为 AdHoc Bundle ID
|
|
140
|
+
# 而 app_repo_name 保留了原始值,用于定位正确的配置仓库
|
|
141
|
+
app_repo_name = config_parser.app_repo_name
|
|
142
|
+
app_version = config_parser.app_version || "unknown"
|
|
143
|
+
|
|
144
|
+
# 获取配置仓库目录(用于备份)
|
|
145
|
+
# 使用 clong_buildconfig_repo 确保仓库已克隆或更新
|
|
146
|
+
require 'pindo/base/git_handler'
|
|
147
|
+
app_config_dir = Pindo::GitHandler.clong_buildconfig_repo(repo_name: app_repo_name)
|
|
148
|
+
|
|
149
|
+
# 1. 清理 Pods 和 Podfile.lock(强制清理)
|
|
150
|
+
puts "\n🧹 清理 Pods 和 Podfile.lock..."
|
|
151
|
+
pods_dir = File.join(@project_path, "Pods")
|
|
152
|
+
podfile_lock = File.join(@project_path, "Podfile.lock")
|
|
153
|
+
FileUtils.rm_rf(pods_dir) if File.exist?(pods_dir)
|
|
154
|
+
FileUtils.rm_rf(podfile_lock) if File.exist?(podfile_lock)
|
|
155
|
+
|
|
156
|
+
# 2. 更新私有索引库
|
|
157
|
+
Pindo::CocoaPodsHelper.update_pod_repo(
|
|
158
|
+
install: false,
|
|
159
|
+
project_dir: @project_path
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
# 3. 移除测试 Pod 模块
|
|
163
|
+
Pindo::CocoaPodsHelper.remove_test_pods(@project_path)
|
|
164
|
+
|
|
165
|
+
# 4. 清理并重新安装(删除 Podfile.lock)
|
|
166
|
+
Pindo::CocoaPodsHelper.deintegrate_and_install(@project_path, clean_podfile_lock: true)
|
|
167
|
+
|
|
168
|
+
# 5. 备份 Podfile.lock 到配置仓库
|
|
169
|
+
unless app_config_dir && File.directory?(app_config_dir)
|
|
170
|
+
raise Informative, "配置仓库目录不存在或无法访问,无法备份 Podfile.lock: #{app_config_dir}"
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
puts "\n💾 备份 Podfile.lock 到配置仓库: #{app_config_dir}"
|
|
174
|
+
Pindo::CocoaPodsHelper.backup_podfile_lock(
|
|
175
|
+
@project_path,
|
|
176
|
+
app_config_dir,
|
|
177
|
+
app_version
|
|
178
|
+
)
|
|
179
|
+
end
|
|
180
|
+
|
|
87
181
|
private
|
|
88
182
|
|
|
89
183
|
# 加载 iOS 配置
|
|
@@ -291,21 +385,6 @@ module Pindo
|
|
|
291
385
|
end
|
|
292
386
|
end
|
|
293
387
|
|
|
294
|
-
|
|
295
|
-
# 处理 CocoaPods
|
|
296
|
-
def handle_cocoapods
|
|
297
|
-
return unless File.exist?(File.join(@project_path, "Podfile"))
|
|
298
|
-
|
|
299
|
-
# 1. 更新私有索引库
|
|
300
|
-
Pindo::CocoaPodsHelper.update_pod_repo(
|
|
301
|
-
install: false,
|
|
302
|
-
project_dir: @project_path
|
|
303
|
-
)
|
|
304
|
-
|
|
305
|
-
# 2. 清理并重新安装
|
|
306
|
-
Pindo::CocoaPodsHelper.deintegrate_and_install(@project_path)
|
|
307
|
-
end
|
|
308
|
-
|
|
309
388
|
# 检测是否为 macOS 平台
|
|
310
389
|
def detect_macos_platform
|
|
311
390
|
project_fullname = Dir.glob(File.join(@project_path, "/*.xcodeproj")).max_by { |f| File.mtime(f) }
|
|
@@ -84,6 +84,47 @@ module Pindo
|
|
|
84
84
|
end
|
|
85
85
|
end
|
|
86
86
|
|
|
87
|
+
# 处理 CocoaPods 依赖(AppStore 构建)
|
|
88
|
+
def handle_cocoapods
|
|
89
|
+
return unless File.exist?(File.join(@project_path, "Podfile"))
|
|
90
|
+
|
|
91
|
+
require 'pindo/module/xcode/cocoapods_helper'
|
|
92
|
+
require 'pindo/config/pindoconfig'
|
|
93
|
+
|
|
94
|
+
config_parser = Pindo::IosConfigParser.instance
|
|
95
|
+
|
|
96
|
+
# 使用原始 Bundle ID(app_repo_name)作为配置仓库名称
|
|
97
|
+
app_repo_name = config_parser.app_repo_name
|
|
98
|
+
|
|
99
|
+
# 获取配置仓库目录
|
|
100
|
+
pindo_dir = File.expand_path(Pindo::Pindoconfig.instance.pindo_dir)
|
|
101
|
+
app_config_dir = File.join(pindo_dir, app_repo_name)
|
|
102
|
+
|
|
103
|
+
# 1. 清理 Pods 和 Podfile.lock(强制清理)
|
|
104
|
+
puts "\n🧹 清理 Pods 和 Podfile.lock..."
|
|
105
|
+
pods_dir = File.join(@project_path, "Pods")
|
|
106
|
+
podfile_lock = File.join(@project_path, "Podfile.lock")
|
|
107
|
+
FileUtils.rm_rf(pods_dir) if File.exist?(pods_dir)
|
|
108
|
+
FileUtils.rm_rf(podfile_lock) if File.exist?(podfile_lock)
|
|
109
|
+
|
|
110
|
+
# 2. 更新私有索引库
|
|
111
|
+
Pindo::CocoaPodsHelper.update_pod_repo(
|
|
112
|
+
install: false,
|
|
113
|
+
project_dir: @project_path
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
# 3. 移除测试 Pod 模块
|
|
117
|
+
Pindo::CocoaPodsHelper.remove_test_pods(@project_path)
|
|
118
|
+
|
|
119
|
+
# 4. 从配置仓库拷贝 Podfile.lock
|
|
120
|
+
if File.directory?(app_config_dir)
|
|
121
|
+
Pindo::CocoaPodsHelper.copy_podfile_lock_from_config(@project_path, app_config_dir)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# 5. 清理并重新安装(不删除 Podfile.lock)
|
|
125
|
+
Pindo::CocoaPodsHelper.deintegrate_and_install(@project_path, clean_podfile_lock: false)
|
|
126
|
+
end
|
|
127
|
+
|
|
87
128
|
private
|
|
88
129
|
|
|
89
130
|
# 加载 iOS 配置
|
|
@@ -291,20 +332,6 @@ module Pindo
|
|
|
291
332
|
end
|
|
292
333
|
end
|
|
293
334
|
|
|
294
|
-
# 处理 CocoaPods
|
|
295
|
-
def handle_cocoapods
|
|
296
|
-
return unless File.exist?(File.join(@project_path, "Podfile"))
|
|
297
|
-
|
|
298
|
-
# 1. 更新私有索引库
|
|
299
|
-
Pindo::CocoaPodsHelper.update_pod_repo(
|
|
300
|
-
install: false,
|
|
301
|
-
project_dir: @project_path
|
|
302
|
-
)
|
|
303
|
-
|
|
304
|
-
# 2. 清理并重新安装
|
|
305
|
-
Pindo::CocoaPodsHelper.deintegrate_and_install(@project_path)
|
|
306
|
-
end
|
|
307
|
-
|
|
308
335
|
# 检测是否为 macOS 平台
|
|
309
336
|
def detect_macos_platform
|
|
310
337
|
project_fullname = Dir.glob(File.join(@project_path, "/*.xcodeproj")).max_by { |f| File.mtime(f) }
|
|
@@ -70,6 +70,29 @@ module Pindo
|
|
|
70
70
|
end
|
|
71
71
|
end
|
|
72
72
|
|
|
73
|
+
# 处理 CocoaPods 依赖(Dev 构建)
|
|
74
|
+
def handle_cocoapods
|
|
75
|
+
return unless File.exist?(File.join(@project_path, "Podfile"))
|
|
76
|
+
|
|
77
|
+
require 'pindo/module/xcode/cocoapods_helper'
|
|
78
|
+
|
|
79
|
+
# 1. 清理 Pods 和 Podfile.lock(强制清理)
|
|
80
|
+
puts "\n🧹 清理 Pods 和 Podfile.lock..."
|
|
81
|
+
pods_dir = File.join(@project_path, "Pods")
|
|
82
|
+
podfile_lock = File.join(@project_path, "Podfile.lock")
|
|
83
|
+
FileUtils.rm_rf(pods_dir) if File.exist?(pods_dir)
|
|
84
|
+
FileUtils.rm_rf(podfile_lock) if File.exist?(podfile_lock)
|
|
85
|
+
|
|
86
|
+
# 2. 更新私有索引库
|
|
87
|
+
Pindo::CocoaPodsHelper.update_pod_repo(
|
|
88
|
+
install: false,
|
|
89
|
+
project_dir: @project_path
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
# 3. 清理并重新安装(删除 Podfile.lock)
|
|
93
|
+
Pindo::CocoaPodsHelper.deintegrate_and_install(@project_path, clean_podfile_lock: true)
|
|
94
|
+
end
|
|
95
|
+
|
|
73
96
|
private
|
|
74
97
|
|
|
75
98
|
# Git 标签检查
|
|
@@ -158,20 +181,6 @@ module Pindo
|
|
|
158
181
|
)
|
|
159
182
|
end
|
|
160
183
|
|
|
161
|
-
# 处理 CocoaPods
|
|
162
|
-
def handle_cocoapods
|
|
163
|
-
return unless File.exist?(File.join(@project_path, "Podfile"))
|
|
164
|
-
|
|
165
|
-
# 1. 更新私有索引库
|
|
166
|
-
Pindo::CocoaPodsHelper.update_pod_repo(
|
|
167
|
-
install: false,
|
|
168
|
-
project_dir: @project_path
|
|
169
|
-
)
|
|
170
|
-
|
|
171
|
-
# 2. 清理并重新安装
|
|
172
|
-
Pindo::CocoaPodsHelper.deintegrate_and_install(@project_path)
|
|
173
|
-
end
|
|
174
|
-
|
|
175
184
|
# 配置证书
|
|
176
185
|
def configure_certificate
|
|
177
186
|
# 检查是否是 macOS 工程
|