pindo 5.13.1 → 5.13.3

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.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/lib/pindo/base/git_handler.rb +692 -0
  3. data/lib/pindo/command/android/autobuild.rb +2 -2
  4. data/lib/pindo/command/appstore/adhocbuild.rb +256 -311
  5. data/lib/pindo/command/appstore/autobuild.rb +203 -0
  6. data/lib/pindo/command/appstore/autoresign.rb +35 -17
  7. data/lib/pindo/command/appstore/bundleid.rb +120 -0
  8. data/lib/pindo/command/appstore/cert.rb +212 -0
  9. data/lib/pindo/command/appstore/configproj.rb +81 -0
  10. data/lib/pindo/command/{deploy → appstore}/getitcinfo.rb +76 -91
  11. data/lib/pindo/command/appstore/iap.rb +788 -24
  12. data/lib/pindo/command/appstore/initconfig.rb +105 -0
  13. data/lib/pindo/command/appstore/itcapp.rb +95 -13
  14. data/lib/pindo/command/{deploy → appstore}/itcinfo.rb +90 -118
  15. data/lib/pindo/command/appstore/pem.rb +136 -0
  16. data/lib/pindo/command/appstore/pullconfig.rb +99 -0
  17. data/lib/pindo/command/appstore/quswark.rb +87 -0
  18. data/lib/pindo/command/appstore/quswauth.rb +67 -0
  19. data/lib/pindo/command/appstore/tag.rb +77 -0
  20. data/lib/pindo/command/appstore.rb +13 -1
  21. data/lib/pindo/command/env/quarkenv.rb +11 -13
  22. data/lib/pindo/command/env/swarkenv.rb +11 -16
  23. data/lib/pindo/command/ios/applovin.rb +24 -182
  24. data/lib/pindo/command/ios/autobuild.rb +64 -43
  25. data/lib/pindo/command/ios/autoresign.rb +34 -19
  26. data/lib/pindo/command/ios/build.rb +9 -6
  27. data/lib/pindo/command/ios/cert.rb +27 -20
  28. data/lib/pindo/command/ios/podupdate.rb +6 -37
  29. data/lib/pindo/command/jps/upload.rb +3 -3
  30. data/lib/pindo/command/unity/autobuild.rb +2 -2
  31. data/lib/pindo/command/utils/clearcert.rb +2 -17
  32. data/lib/pindo/command/{deploy → utils}/fabric.rb +13 -13
  33. data/lib/pindo/command/utils/renewcert.rb +62 -38
  34. data/lib/pindo/command/utils/renewproj.rb +0 -3
  35. data/lib/pindo/command/{deploy → utils}/updateconfig.rb +6 -7
  36. data/lib/pindo/command/utils.rb +2 -0
  37. data/lib/pindo/command/web/autobuild.rb +2 -2
  38. data/lib/pindo/command.rb +30 -3
  39. data/lib/pindo/config/build_info_manager.rb +176 -0
  40. data/lib/pindo/config/ios_config_parser.rb +404 -0
  41. data/lib/pindo/module/android/android_config_helper.rb +9 -5
  42. data/lib/pindo/module/appstore/bundleid_helper.rb +349 -0
  43. data/lib/pindo/module/appstore/itcapp_helper.rb +228 -0
  44. data/lib/pindo/module/build/build_helper.rb +12 -0
  45. data/lib/pindo/module/build/swark_helper.rb +116 -77
  46. data/lib/pindo/module/cert/cert_helper.rb +74 -0
  47. data/lib/pindo/module/cert/pem_helper.rb +72 -0
  48. data/lib/pindo/module/cert/{xcodecerthelper.rb → xcode_cert_helper.rb} +211 -6
  49. data/lib/pindo/module/pgyer/pgyerhelper.rb +13 -5
  50. data/lib/pindo/module/task/model/appstore/appstore_task.rb +18 -0
  51. data/lib/pindo/module/task/model/appstore/appstore_upload_ipa_task.rb +151 -0
  52. data/lib/pindo/module/task/model/appstore/appstore_upload_metadata_task.rb +250 -0
  53. data/lib/pindo/module/task/model/appstore/appstore_upload_screenshot_task.rb +276 -0
  54. data/lib/pindo/module/task/model/build/android_build_adhoc_task.rb +210 -0
  55. data/lib/pindo/module/task/model/build/{android_dev_build_task.rb → android_build_dev_task.rb} +2 -2
  56. data/lib/pindo/module/task/model/build/android_build_gplay_task.rb +210 -0
  57. data/lib/pindo/module/task/model/build/android_build_task.rb +13 -0
  58. data/lib/pindo/module/task/model/build/ios_build_adhoc_task.rb +342 -0
  59. data/lib/pindo/module/task/model/build/ios_build_appstore_task.rb +341 -0
  60. data/lib/pindo/module/task/model/build/{ios_dev_build_task.rb → ios_build_dev_task.rb} +40 -59
  61. data/lib/pindo/module/task/model/build/ios_build_task.rb +23 -0
  62. data/lib/pindo/module/task/model/build/{web_dev_build_task.rb → web_build_dev_task.rb} +1 -1
  63. data/lib/pindo/module/task/model/build_task.rb +15 -12
  64. data/lib/pindo/module/task/model/jps_resign_task.rb +185 -0
  65. data/lib/pindo/module/task/model/{upload_task.rb → jps_upload_task.rb} +3 -3
  66. data/lib/pindo/module/task/model/unity_export_task.rb +3 -1
  67. data/lib/pindo/module/unity/unity_helper.rb +2 -1
  68. data/lib/pindo/module/xcode/applovin_xcode_helper.rb +271 -0
  69. data/lib/pindo/module/xcode/cocoapods_helper.rb +153 -0
  70. data/lib/pindo/module/xcode/ipa_resign_helper.rb +210 -0
  71. data/lib/pindo/module/xcode/{xcodeappconfig.rb → xcode_app_config.rb} +79 -0
  72. data/lib/pindo/module/xcode/xcode_build_config.rb +152 -17
  73. data/lib/pindo/module/xcode/xcode_build_helper.rb +151 -1
  74. data/lib/pindo/module/xcode/xcode_swark_helper.rb +341 -0
  75. data/lib/pindo/options/core/global_options_state.rb +268 -0
  76. data/lib/pindo/options/core/option_configuration.rb +206 -0
  77. data/lib/pindo/options/core/option_initializer.rb +51 -0
  78. data/lib/pindo/options/core/option_item.rb +144 -0
  79. data/lib/pindo/options/core/option_value_parser.rb +54 -0
  80. data/lib/pindo/options/groups/build_options.rb +60 -0
  81. data/lib/pindo/options/groups/jps_options.rb +70 -0
  82. data/lib/pindo/options/groups/option_group.rb +73 -0
  83. data/lib/pindo/options/helpers/bundleid_selector.rb +103 -0
  84. data/lib/pindo/options/options.rb +14 -0
  85. data/lib/pindo/version.rb +1 -1
  86. metadata +51 -40
  87. data/lib/pindo/command/appstore/import.rb +0 -259
  88. data/lib/pindo/command/deploy/build.rb +0 -250
  89. data/lib/pindo/command/deploy/bundleid.rb +0 -259
  90. data/lib/pindo/command/deploy/cert.rb +0 -202
  91. data/lib/pindo/command/deploy/check.rb +0 -93
  92. data/lib/pindo/command/deploy/configproj.rb +0 -120
  93. data/lib/pindo/command/deploy/confusecode.rb +0 -262
  94. data/lib/pindo/command/deploy/confuseproj.rb +0 -122
  95. data/lib/pindo/command/deploy/iap.rb +0 -826
  96. data/lib/pindo/command/deploy/initconfig.rb +0 -138
  97. data/lib/pindo/command/deploy/itcapp.rb +0 -146
  98. data/lib/pindo/command/deploy/pem.rb +0 -55
  99. data/lib/pindo/command/deploy/pullconfig.rb +0 -56
  100. data/lib/pindo/command/deploy/pushconfig.rb +0 -93
  101. data/lib/pindo/command/deploy/quswark.rb +0 -156
  102. data/lib/pindo/command/deploy/quswauth.rb +0 -76
  103. data/lib/pindo/command/deploy/reportbug.rb +0 -145
  104. data/lib/pindo/command/deploy/resign.rb +0 -300
  105. data/lib/pindo/command/deploy/tag.rb +0 -108
  106. data/lib/pindo/command/deploy/uploadipa.rb +0 -73
  107. data/lib/pindo/command/deploy.rb +0 -42
  108. data/lib/pindo/command/dev/autobuild.rb +0 -117
  109. data/lib/pindo/command/dev/build.rb +0 -94
  110. data/lib/pindo/command/dev/debug.rb +0 -112
  111. data/lib/pindo/module/task/model/build/android_release_build_task.rb +0 -29
  112. data/lib/pindo/module/task/model/build/ios_adhoc_build_task.rb +0 -53
  113. data/lib/pindo/module/task/model/build/ios_release_build_task.rb +0 -53
  114. data/lib/pindo/options/appconfigoptions.rb +0 -24
  115. data/lib/pindo/options/deployoptions.rb +0 -372
@@ -0,0 +1,342 @@
1
+ require_relative 'ios_build_task'
2
+ require 'pindo/module/build/build_helper'
3
+ require 'pindo/module/build/version_helper'
4
+ require 'pindo/module/build/git_repo_helper'
5
+ require 'pindo/module/xcode/xcode_build_config'
6
+ require 'pindo/module/xcode/xcode_build_helper'
7
+ require 'pindo/module/xcode/xcode_app_config'
8
+ require 'pindo/module/xcode/cocoapods_helper'
9
+ require 'pindo/module/xcode/applovin_xcode_helper'
10
+ require 'pindo/module/cert/xcode_cert_helper'
11
+ require 'pindo/module/pgyer/pgyerhelper'
12
+ require 'pindo/config/ios_config_parser'
13
+
14
+ module Pindo
15
+ module TaskSystem
16
+ # iOS AdHoc 模式构建任务
17
+ # 使用 AdHoc 证书编译 iOS 工程
18
+ # 包含 AdHoc 特有的准备工作(版本号增加、Tag 创建、Quark/Swark 处理等)
19
+ class IosBuildAdhocTask < IosBuildTask
20
+ def initialize(options = {})
21
+ @bundle_id = options[:bundle_id]
22
+ @proj_name = options[:proj_name]
23
+ @upload_flag = options[:upload] || false
24
+ @send_flag = options[:send] || false
25
+ @macos_flag = false
26
+
27
+ # 保存 Unity 根目录路径(用于查找 config.json)
28
+ @unity_root_path = options[:unity_root_path]
29
+
30
+ super(:ios, :adhoc, options)
31
+ end
32
+
33
+ protected
34
+
35
+ def build_task_name
36
+ "构建 IPA (AdHoc)"
37
+ end
38
+
39
+ #准备构建
40
+ def prepare_build
41
+ Dir.chdir(@project_path)
42
+
43
+ # 0. 清理 Firebase Shell Script
44
+ cleanup_firebase_shell
45
+
46
+ # 1. 加载配置到 IosConfigParser 单例
47
+ load_ios_config
48
+
49
+ # 2. 自动增加版本号
50
+ auto_increase_buildnumber
51
+
52
+ # 3. 检查代码版本
53
+ check_code_version
54
+
55
+ # 4. 配置 Xcode 项目
56
+ configure_xcode_project
57
+
58
+ # 5. Quark/Swark 处理
59
+ handle_quswark_processing
60
+
61
+ # 6. 使用 adhoc cert 命令
62
+ configure_adhoc_certificate
63
+
64
+ # 7. Applovin 处理
65
+ handle_applovin_processing
66
+ end
67
+
68
+ def execute_build
69
+ handle_cocoapods
70
+ build_ios_project
71
+ end
72
+
73
+ def find_output
74
+ build_path = File.join(@project_path, "build", "*.{ipa,app}")
75
+ ipa_files = Dir.glob(build_path)
76
+
77
+ if ipa_files.any?
78
+ latest_ipa = ipa_files.max_by { |f| File.mtime(f) }
79
+ puts " 找到 IPA 文件: #{latest_ipa}"
80
+ latest_ipa
81
+ else
82
+ puts " 警告: 未找到 IPA 文件"
83
+ nil
84
+ end
85
+ end
86
+
87
+ private
88
+
89
+ # 加载 iOS 配置
90
+ def load_ios_config
91
+ # 直接使用 IosConfigParser 单例中已加载的配置
92
+ config_parser = Pindo::IosConfigParser.instance
93
+ if config_parser.config_json.nil?
94
+ # 如果单例中没有配置,说明命令层未正确初始化
95
+ raise Informative, "配置未加载,请确保在命令层(如 pindo adhoc autobuild)已正确加载 config.json"
96
+ else
97
+ puts " 使用已加载的配置..."
98
+ end
99
+ end
100
+
101
+ # 自动增加版本号
102
+ def auto_increase_buildnumber
103
+ config_parser = Pindo::IosConfigParser.instance
104
+ config_json = config_parser.config_json
105
+ return unless config_json
106
+
107
+ # 从全局配置获取 deploy_identifier
108
+ deploy_identifier = config_json.dig('project_info', 'deploy_identifier')
109
+ return unless deploy_identifier
110
+
111
+ puts " 自动增加版本号..."
112
+
113
+ # 从全局配置获取 pindo_dir
114
+ pindo_dir = File.expand_path(config_parser.pindo_dir)
115
+ app_config_repo_dir = File.join(pindo_dir, deploy_identifier)
116
+
117
+ # 增加项目目录的版本号
118
+ project_config_file = File.join(@project_path, "config.json")
119
+ if File.exist?(project_config_file)
120
+ increase_buildnumber_in_file(project_config_file)
121
+ end
122
+
123
+ # 增加配置仓库的版本号
124
+ app_config_file = File.join(app_config_repo_dir, "config.json")
125
+ if File.exist?(app_config_file)
126
+ increase_buildnumber_in_file(app_config_file)
127
+
128
+ # 提交到配置仓库
129
+ require 'pindo/module/build/git_repo_helper'
130
+ git_helper = Pindo::GitRepoHelper.share_instance
131
+ git_helper.git_addpush_repo(
132
+ path: app_config_repo_dir,
133
+ message: "increate build number",
134
+ commit_file_params: ["config.json"]
135
+ )
136
+ end
137
+ end
138
+
139
+ # 增加配置文件中的版本号
140
+ def increase_buildnumber_in_file(config_file)
141
+ config_json = JSON.parse(File.read(config_file))
142
+
143
+ if config_json["app_info"] && config_json["app_info"]["app_version"]
144
+ version_parts = config_json["app_info"]["app_version"].split(".")
145
+ if version_parts.length >= 3
146
+ build_number = version_parts[2].to_i + 1
147
+ version_parts[2] = build_number.to_s
148
+ config_json["app_info"]["app_version"] = version_parts.join(".")
149
+
150
+ File.write(config_file, JSON.pretty_generate(config_json))
151
+ puts " ✓ 版本号: #{config_json["app_info"]["app_version"]}"
152
+ end
153
+ end
154
+ end
155
+
156
+ # 检查代码版本
157
+ def check_code_version
158
+ config_parser = Pindo::IosConfigParser.instance
159
+ config_json = config_parser.config_json
160
+ return unless config_json
161
+
162
+ deploy_identifier = config_json.dig('project_info', 'deploy_identifier')
163
+ return unless deploy_identifier
164
+
165
+ puts " 检查代码版本..."
166
+
167
+ pindo_dir = File.expand_path(config_parser.pindo_dir)
168
+ app_config_dir = File.join(pindo_dir, deploy_identifier)
169
+ build_verify_file = File.join(app_config_dir, "build_verify.json")
170
+
171
+ build_verify_json = nil
172
+ begin
173
+ build_verify_json = JSON.parse(File.read(build_verify_file)) if File.exist?(build_verify_file)
174
+ rescue => error
175
+ build_verify_json = nil
176
+ end
177
+
178
+ require 'pindo/module/build/git_repo_helper'
179
+ git_helper = Pindo::GitRepoHelper.share_instance
180
+ release_code_commit = git_helper.git_latest_commit_id(local_repo_dir: @project_path)
181
+
182
+ if !release_code_commit.nil? && !build_verify_json.nil? && !build_verify_json["output_code_commit"].nil?
183
+ output_code_commit = build_verify_json["output_code_commit"]
184
+ if !release_code_commit.eql?(output_code_commit)
185
+ puts
186
+ puts " ⚠ 不是最新代码,请更新代码!"
187
+ puts " 当前 commit: #{release_code_commit}"
188
+ puts " 期望 commit: #{output_code_commit}"
189
+ puts
190
+
191
+ require 'highline/import'
192
+ answer = agree(" 请确认要用当前代码编译: (Y/n)")
193
+ unless answer
194
+ raise Informative, "请更新代码重新打包!"
195
+ end
196
+ end
197
+ end
198
+ end
199
+
200
+ # 配置 Xcode 项目
201
+ def configure_xcode_project
202
+ puts " 配置 Xcode 项目..."
203
+ Pindo::XcodeBuildConfig.configure_xcode_project(project_dir: @project_path)
204
+ end
205
+
206
+ # 处理 Quark/Swark
207
+ def handle_quswark_processing
208
+ config_parser = Pindo::IosConfigParser.instance
209
+ config_json = config_parser.config_json
210
+ return unless config_json
211
+
212
+ # 从 config_json 中判断是否需要处理 Quark/Swark
213
+ xcode_build_type = config_json.dig('project_info', 'xcode_build_type')
214
+ return unless xcode_build_type
215
+
216
+ build_type_array = xcode_build_type.split("_") || []
217
+ return unless build_type_array.include?("quark") || build_type_array.include?("swark")
218
+
219
+ puts " 处理 Quark/Swark..."
220
+
221
+ require 'pindo/module/xcode/xcode_swark_helper'
222
+ Dir.chdir(@project_path)
223
+
224
+ if xcode_build_type.include?("quark")
225
+ Pindo::XcodeSwarkHelper.quark_run(
226
+ project_dir: @project_path,
227
+ config_json: config_json,
228
+ build_type: 'adhoc'
229
+ )
230
+ else
231
+ Pindo::XcodeSwarkHelper.swark_run(
232
+ project_dir: @project_path,
233
+ config_json: config_json,
234
+ build_type: 'adhoc'
235
+ )
236
+ end
237
+ end
238
+
239
+ # 配置 AdHoc 证书
240
+ def configure_adhoc_certificate
241
+ puts " 配置 AdHoc 证书..."
242
+
243
+ # 检测平台类型
244
+ detect_macos_platform
245
+ platform_type = @macos_flag ? 'macos' : 'ios'
246
+
247
+ # 使用 XcodeCertHelper 安装和配置证书
248
+ Pindo::XcodeCertHelper.install_and_config_certs(
249
+ build_type: 'adhoc',
250
+ platform_type: platform_type,
251
+ project_dir: @project_path
252
+ )
253
+ end
254
+
255
+ # # 创建发布 tag
256
+ # def create_release_tag_for_adhoc
257
+ # puts " 创建发布 Tag..."
258
+ #
259
+ # config_parser = Pindo::IosConfigParser.instance
260
+ # config_json = config_parser.config_json
261
+ # bundle_id = config_parser.bundle_id
262
+ #
263
+ # tag_helper = Object.new
264
+ # tag_helper.extend(Pindo::XcodeAppConfig)
265
+ # tag_helper.create_release_tag(
266
+ # project_dir: @project_path,
267
+ # config_json: config_json,
268
+ # bundle_id: bundle_id
269
+ # )
270
+ # end
271
+
272
+ # 处理 Applovin
273
+ def handle_applovin_processing
274
+ return unless File.exist?(File.join(@project_path, "Podfile.lock"))
275
+
276
+ begin
277
+ # 检查是否使用了 FancyAD 或 AppLovinSDK
278
+ if Pindo::CocoaPodsHelper.using_pods?(@project_path, ["FancyAD", "AppLovinSDK"])
279
+ puts
280
+ puts " 运行 Applovin Script..."
281
+
282
+ Pindo::ApplovinXcodeHelper.update_applovin_config(
283
+ project_dir: @project_path,
284
+ appstore_mode: false,
285
+ install_script: true,
286
+ upload_config: false
287
+ )
288
+ end
289
+ rescue => e
290
+ puts " ⚠ Applovin 处理失败: #{e.message}"
291
+ end
292
+ end
293
+
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
+ # 检测是否为 macOS 平台
310
+ def detect_macos_platform
311
+ project_fullname = Dir.glob(File.join(@project_path, "/*.xcodeproj")).max_by { |f| File.mtime(f) }
312
+ return if project_fullname.nil?
313
+
314
+ require 'xcodeproj'
315
+ project_obj = Xcodeproj::Project.open(project_fullname)
316
+ project_build_platform = project_obj.root_object.build_configuration_list.get_setting("SDKROOT")["Release"]
317
+
318
+ if !project_build_platform.nil? && project_build_platform.eql?("macosx")
319
+ @macos_flag = true
320
+ end
321
+ end
322
+
323
+ # 编译 iOS 工程
324
+ def build_ios_project
325
+ Dir.chdir(@project_path)
326
+
327
+ # 使用 XcodeBuildHelper 进行构建
328
+ ipa_file = Pindo::XcodeBuildHelper.build_project(
329
+ project_dir: @project_path,
330
+ icloud_id: nil
331
+ )
332
+
333
+ if ipa_file.nil?
334
+ raise Informative, "构建失败:未生成 IPA 文件"
335
+ end
336
+
337
+ puts "构建成功:#{ipa_file}"
338
+ ipa_file
339
+ end
340
+ end
341
+ end
342
+ end
@@ -0,0 +1,341 @@
1
+ require_relative 'ios_build_task'
2
+ require 'pindo/module/build/build_helper'
3
+ require 'pindo/module/build/version_helper'
4
+ require 'pindo/module/build/git_repo_helper'
5
+ require 'pindo/module/xcode/xcode_build_config'
6
+ require 'pindo/module/xcode/xcode_build_helper'
7
+ require 'pindo/module/xcode/xcode_app_config'
8
+ require 'pindo/module/xcode/cocoapods_helper'
9
+ require 'pindo/module/xcode/applovin_xcode_helper'
10
+ require 'pindo/module/cert/xcode_cert_helper'
11
+ require 'pindo/module/pgyer/pgyerhelper'
12
+ require 'pindo/config/ios_config_parser'
13
+
14
+ module Pindo
15
+ module TaskSystem
16
+ # iOS AppStore 模式构建任务
17
+ # 使用 Distribution/App Store 证书编译 iOS 工程
18
+ # 包含 AppStore 特有的准备工作(版本号增加、Tag 创建、Quark/Swark 处理等)
19
+ class IosBuildAppStoreTask < IosBuildTask
20
+ def initialize(options = {})
21
+ @bundle_id = options[:bundle_id]
22
+ @proj_name = options[:proj_name]
23
+ @upload_flag = options[:upload] || false
24
+ @send_flag = options[:send] || false
25
+ @macos_flag = false
26
+
27
+ # 保存 Unity 根目录路径(用于查找 config.json)
28
+ @unity_root_path = options[:unity_root_path]
29
+
30
+ super(:ios, :release, options)
31
+ end
32
+
33
+ protected
34
+
35
+ def build_task_name
36
+ "构建 IPA (Release)"
37
+ end
38
+
39
+ #准备构建
40
+ def prepare_build
41
+ Dir.chdir(@project_path)
42
+
43
+ # 0. 清理 Firebase Shell Script
44
+ cleanup_firebase_shell
45
+
46
+ # 1. 加载配置到 IosConfigParser 单例
47
+ load_ios_config
48
+
49
+ # 2. 自动增加版本号
50
+ auto_increase_buildnumber
51
+
52
+ # 3. 检查代码版本
53
+ check_code_version
54
+
55
+ # 4. 配置 Xcode 项目
56
+ configure_xcode_project
57
+
58
+ # 5. Quark/Swark 处理
59
+ handle_quswark_processing
60
+
61
+ # 6. 使用 appstore cert 命令
62
+ configure_appstore_certificate
63
+
64
+ # 7. Applovin 处理
65
+ handle_applovin_processing
66
+ end
67
+
68
+ def execute_build
69
+ handle_cocoapods
70
+ build_ios_project
71
+ end
72
+
73
+ def find_output
74
+ build_path = File.join(@project_path, "build", "*.{ipa,app}")
75
+ ipa_files = Dir.glob(build_path)
76
+
77
+ if ipa_files.any?
78
+ latest_ipa = ipa_files.max_by { |f| File.mtime(f) }
79
+ puts " 找到 IPA 文件: #{latest_ipa}"
80
+ latest_ipa
81
+ else
82
+ puts " 警告: 未找到 IPA 文件"
83
+ nil
84
+ end
85
+ end
86
+
87
+ private
88
+
89
+ # 加载 iOS 配置
90
+ def load_ios_config
91
+ # 直接使用 IosConfigParser 单例中已加载的配置
92
+ config_parser = Pindo::IosConfigParser.instance
93
+ if config_parser.config_json.nil?
94
+ # 如果单例中没有配置,说明命令层未正确初始化
95
+ raise Informative, "配置未加载,请确保在命令层(如 pindo appstore autobuild)已正确加载 config.json"
96
+ else
97
+ puts " 使用已加载的配置..."
98
+ end
99
+ end
100
+
101
+ # 自动增加版本号
102
+ def auto_increase_buildnumber
103
+ config_parser = Pindo::IosConfigParser.instance
104
+ config_json = config_parser.config_json
105
+ return unless config_json
106
+
107
+ # 从全局配置获取 deploy_identifier
108
+ deploy_identifier = config_json.dig('project_info', 'deploy_identifier')
109
+ return unless deploy_identifier
110
+
111
+ puts " 自动增加版本号..."
112
+
113
+ # 从全局配置获取 pindo_dir
114
+ pindo_dir = File.expand_path(config_parser.pindo_dir)
115
+ app_config_repo_dir = File.join(pindo_dir, deploy_identifier)
116
+
117
+ # 增加项目目录的版本号
118
+ project_config_file = File.join(@project_path, "config.json")
119
+ if File.exist?(project_config_file)
120
+ increase_buildnumber_in_file(project_config_file)
121
+ end
122
+
123
+ # 增加配置仓库的版本号
124
+ app_config_file = File.join(app_config_repo_dir, "config.json")
125
+ if File.exist?(app_config_file)
126
+ increase_buildnumber_in_file(app_config_file)
127
+
128
+ # 提交到配置仓库
129
+ require 'pindo/module/build/git_repo_helper'
130
+ git_helper = Pindo::GitRepoHelper.share_instance
131
+ git_helper.git_addpush_repo(
132
+ path: app_config_repo_dir,
133
+ message: "increate build number",
134
+ commit_file_params: ["config.json"]
135
+ )
136
+ end
137
+ end
138
+
139
+ # 增加配置文件中的版本号
140
+ def increase_buildnumber_in_file(config_file)
141
+ config_json = JSON.parse(File.read(config_file))
142
+
143
+ if config_json["app_info"] && config_json["app_info"]["app_version"]
144
+ version_parts = config_json["app_info"]["app_version"].split(".")
145
+ if version_parts.length >= 3
146
+ build_number = version_parts[2].to_i + 1
147
+ version_parts[2] = build_number.to_s
148
+ config_json["app_info"]["app_version"] = version_parts.join(".")
149
+
150
+ File.write(config_file, JSON.pretty_generate(config_json))
151
+ puts " ✓ 版本号: #{config_json["app_info"]["app_version"]}"
152
+ end
153
+ end
154
+ end
155
+
156
+ # 检查代码版本
157
+ def check_code_version
158
+ config_parser = Pindo::IosConfigParser.instance
159
+ config_json = config_parser.config_json
160
+ return unless config_json
161
+
162
+ deploy_identifier = config_json.dig('project_info', 'deploy_identifier')
163
+ return unless deploy_identifier
164
+
165
+ puts " 检查代码版本..."
166
+
167
+ pindo_dir = File.expand_path(config_parser.pindo_dir)
168
+ app_config_dir = File.join(pindo_dir, deploy_identifier)
169
+ build_verify_file = File.join(app_config_dir, "build_verify.json")
170
+
171
+ build_verify_json = nil
172
+ begin
173
+ build_verify_json = JSON.parse(File.read(build_verify_file)) if File.exist?(build_verify_file)
174
+ rescue => error
175
+ build_verify_json = nil
176
+ end
177
+
178
+ require 'pindo/module/build/git_repo_helper'
179
+ git_helper = Pindo::GitRepoHelper.share_instance
180
+ release_code_commit = git_helper.git_latest_commit_id(local_repo_dir: @project_path)
181
+
182
+ if !release_code_commit.nil? && !build_verify_json.nil? && !build_verify_json["output_code_commit"].nil?
183
+ output_code_commit = build_verify_json["output_code_commit"]
184
+ if !release_code_commit.eql?(output_code_commit)
185
+ puts
186
+ puts " ⚠ 不是最新代码,请更新代码!"
187
+ puts " 当前 commit: #{release_code_commit}"
188
+ puts " 期望 commit: #{output_code_commit}"
189
+ puts
190
+
191
+ require 'highline/import'
192
+ answer = agree(" 请确认要用当前代码编译: (Y/n)")
193
+ unless answer
194
+ raise Informative, "请更新代码重新打包!"
195
+ end
196
+ end
197
+ end
198
+ end
199
+
200
+ # 配置 Xcode 项目
201
+ def configure_xcode_project
202
+ puts " 配置 Xcode 项目..."
203
+ Pindo::XcodeBuildConfig.configure_xcode_project(project_dir: @project_path)
204
+ end
205
+
206
+ # 处理 Quark/Swark
207
+ def handle_quswark_processing
208
+ config_parser = Pindo::IosConfigParser.instance
209
+ config_json = config_parser.config_json
210
+ return unless config_json
211
+
212
+ # 从 config_json 中判断是否需要处理 Quark/Swark
213
+ xcode_build_type = config_json.dig('project_info', 'xcode_build_type')
214
+ return unless xcode_build_type
215
+
216
+ build_type_array = xcode_build_type.split("_") || []
217
+ return unless build_type_array.include?("quark") || build_type_array.include?("swark")
218
+
219
+ puts " 处理 Quark/Swark..."
220
+
221
+ require 'pindo/module/xcode/xcode_swark_helper'
222
+ Dir.chdir(@project_path)
223
+
224
+ if xcode_build_type.include?("quark")
225
+ Pindo::XcodeSwarkHelper.quark_run(
226
+ project_dir: @project_path,
227
+ config_json: config_json,
228
+ build_type: 'release'
229
+ )
230
+ else
231
+ Pindo::XcodeSwarkHelper.swark_run(
232
+ project_dir: @project_path,
233
+ config_json: config_json,
234
+ build_type: 'release'
235
+ )
236
+ end
237
+ end
238
+
239
+ # 配置 AppStore 证书
240
+ def configure_appstore_certificate
241
+ puts " 配置 AppStore 证书..."
242
+
243
+ # 检测平台类型
244
+ detect_macos_platform
245
+ platform_type = @macos_flag ? 'macos' : 'ios'
246
+
247
+ # 使用 XcodeCertHelper 安装和配置证书
248
+ Pindo::XcodeCertHelper.install_and_config_certs(
249
+ build_type: 'appstore',
250
+ platform_type: platform_type,
251
+ project_dir: @project_path
252
+ )
253
+ end
254
+
255
+ # # 创建发布 tag
256
+ # def create_release_tag_for_appstore
257
+ # puts " 创建发布 Tag..."
258
+
259
+ # config_parser = Pindo::IosConfigParser.instance
260
+ # config_json = config_parser.config_json
261
+ # bundle_id = config_parser.bundle_id
262
+
263
+ # tag_helper = Object.new
264
+ # tag_helper.extend(Pindo::XcodeAppConfig)
265
+ # tag_helper.create_release_tag(
266
+ # project_dir: @project_path,
267
+ # config_json: config_json,
268
+ # bundle_id: bundle_id
269
+ # )
270
+ # end
271
+
272
+ # 处理 Applovin
273
+ def handle_applovin_processing
274
+ return unless File.exist?(File.join(@project_path, "Podfile.lock"))
275
+
276
+ begin
277
+ # 检查是否使用了 FancyAD 或 AppLovinSDK
278
+ if Pindo::CocoaPodsHelper.using_pods?(@project_path, ["FancyAD", "AppLovinSDK"])
279
+ puts
280
+ puts " 运行 Applovin Script..."
281
+
282
+ Pindo::ApplovinXcodeHelper.update_applovin_config(
283
+ project_dir: @project_path,
284
+ appstore_mode: true,
285
+ install_script: true,
286
+ upload_config: false
287
+ )
288
+ end
289
+ rescue => e
290
+ puts " ⚠ Applovin 处理失败: #{e.message}"
291
+ end
292
+ end
293
+
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
+ # 检测是否为 macOS 平台
309
+ def detect_macos_platform
310
+ project_fullname = Dir.glob(File.join(@project_path, "/*.xcodeproj")).max_by { |f| File.mtime(f) }
311
+ return if project_fullname.nil?
312
+
313
+ require 'xcodeproj'
314
+ project_obj = Xcodeproj::Project.open(project_fullname)
315
+ project_build_platform = project_obj.root_object.build_configuration_list.get_setting("SDKROOT")["Release"]
316
+
317
+ if !project_build_platform.nil? && project_build_platform.eql?("macosx")
318
+ @macos_flag = true
319
+ end
320
+ end
321
+
322
+ # 编译 iOS 工程
323
+ def build_ios_project
324
+ Dir.chdir(@project_path)
325
+
326
+ # 使用 XcodeBuildHelper 进行构建
327
+ ipa_file = Pindo::XcodeBuildHelper.build_project(
328
+ project_dir: @project_path,
329
+ icloud_id: nil
330
+ )
331
+
332
+ if ipa_file.nil?
333
+ raise Informative, "构建失败:未生成 IPA 文件"
334
+ end
335
+
336
+ puts "构建成功:#{ipa_file}"
337
+ ipa_file
338
+ end
339
+ end
340
+ end
341
+ end