pindo 5.12.2 → 5.13.2

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/android.rb +0 -1
  5. data/lib/pindo/command/appstore/adhocbuild.rb +258 -311
  6. data/lib/pindo/command/appstore/autobuild.rb +203 -0
  7. data/lib/pindo/command/appstore/autoresign.rb +35 -17
  8. data/lib/pindo/command/appstore/bundleid.rb +120 -0
  9. data/lib/pindo/command/appstore/cert.rb +212 -0
  10. data/lib/pindo/command/appstore/configproj.rb +81 -0
  11. data/lib/pindo/command/{deploy → appstore}/getitcinfo.rb +76 -91
  12. data/lib/pindo/command/appstore/iap.rb +788 -24
  13. data/lib/pindo/command/appstore/initconfig.rb +105 -0
  14. data/lib/pindo/command/appstore/itcapp.rb +95 -13
  15. data/lib/pindo/command/{deploy → appstore}/itcinfo.rb +90 -118
  16. data/lib/pindo/command/appstore/pem.rb +136 -0
  17. data/lib/pindo/command/appstore/pullconfig.rb +99 -0
  18. data/lib/pindo/command/appstore/quswark.rb +87 -0
  19. data/lib/pindo/command/appstore/quswauth.rb +67 -0
  20. data/lib/pindo/command/appstore/tag.rb +77 -0
  21. data/lib/pindo/command/appstore.rb +13 -1
  22. data/lib/pindo/command/env/quarkenv.rb +11 -13
  23. data/lib/pindo/command/env/swarkenv.rb +11 -16
  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 +10 -7
  27. data/lib/pindo/command/ios/cert.rb +27 -20
  28. data/lib/pindo/command/jps/upload.rb +3 -3
  29. data/lib/pindo/command/unity/autobuild.rb +2 -2
  30. data/lib/pindo/command/utils/clearcert.rb +2 -17
  31. data/lib/pindo/command/{deploy → utils}/fabric.rb +13 -13
  32. data/lib/pindo/command/utils/renewcert.rb +62 -38
  33. data/lib/pindo/command/utils/renewproj.rb +0 -3
  34. data/lib/pindo/command/{deploy → utils}/updateconfig.rb +6 -7
  35. data/lib/pindo/command/utils.rb +2 -0
  36. data/lib/pindo/command/web/autobuild.rb +2 -2
  37. data/lib/pindo/command.rb +30 -3
  38. data/lib/pindo/config/build_info_manager.rb +176 -0
  39. data/lib/pindo/config/ios_config_parser.rb +404 -0
  40. data/lib/pindo/module/android/android_build_helper.rb +110 -0
  41. data/lib/pindo/module/android/android_config_helper.rb +9 -5
  42. data/lib/pindo/module/android/gradle_helper.rb +88 -0
  43. data/lib/pindo/module/appstore/bundleid_helper.rb +349 -0
  44. data/lib/pindo/module/appstore/itcapp_helper.rb +228 -0
  45. data/lib/pindo/module/build/build_helper.rb +12 -0
  46. data/lib/pindo/module/build/swark_helper.rb +116 -77
  47. data/lib/pindo/module/cert/cert_helper.rb +74 -0
  48. data/lib/pindo/module/cert/pem_helper.rb +72 -0
  49. data/lib/pindo/module/cert/{xcodecerthelper.rb → xcode_cert_helper.rb} +208 -6
  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 +197 -0
  59. data/lib/pindo/module/task/model/build/ios_build_appstore_task.rb +367 -0
  60. data/lib/pindo/module/task/model/build/{ios_dev_build_task.rb → ios_build_dev_task.rb} +37 -27
  61. data/lib/pindo/module/task/model/build/ios_build_task.rb +13 -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/task/pindo_task.rb +19 -10
  68. data/lib/pindo/module/unity/unity_helper.rb +2 -1
  69. data/lib/pindo/module/xcode/ipa_resign_helper.rb +210 -0
  70. data/lib/pindo/module/xcode/{xcodeappconfig.rb → xcode_app_config.rb} +79 -0
  71. data/lib/pindo/module/xcode/xcode_build_config.rb +152 -17
  72. data/lib/pindo/module/xcode/xcode_build_helper.rb +151 -1
  73. data/lib/pindo/module/xcode/xcode_swark_helper.rb +341 -0
  74. data/lib/pindo/options/core/global_options_state.rb +268 -0
  75. data/lib/pindo/options/core/option_configuration.rb +206 -0
  76. data/lib/pindo/options/core/option_initializer.rb +51 -0
  77. data/lib/pindo/options/core/option_item.rb +144 -0
  78. data/lib/pindo/options/core/option_value_parser.rb +54 -0
  79. data/lib/pindo/options/groups/build_options.rb +60 -0
  80. data/lib/pindo/options/groups/jps_options.rb +70 -0
  81. data/lib/pindo/options/groups/option_group.rb +73 -0
  82. data/lib/pindo/options/helpers/bundleid_selector.rb +103 -0
  83. data/lib/pindo/options/options.rb +14 -0
  84. data/lib/pindo/version.rb +1 -1
  85. metadata +49 -41
  86. data/lib/pindo/command/android/build.rb +0 -186
  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,228 @@
1
+ require 'spaceship'
2
+ require 'json'
3
+ require 'highline/import'
4
+
5
+ module Pindo
6
+ # iTunes Connect App 管理辅助类
7
+ # 负责在 App Store Connect 中创建和管理应用
8
+ class ItcAppHelper
9
+
10
+ # 从配置文件中提取所有必要的信息
11
+ # @param config_json [Hash] 配置 JSON 对象
12
+ # @return [Hash] 提取的配置信息
13
+ def self.extract_config_info(config_json)
14
+ config_info = {}
15
+
16
+ # 提取 Apple ID
17
+ if config_json['account_info'] && config_json['account_info']['apple_acount_id']
18
+ config_info[:apple_id] = config_json['account_info']['apple_acount_id']
19
+ end
20
+
21
+ # 提取 Company Name
22
+ if config_json['account_info'] && config_json['account_info']['acount_company_name']
23
+ config_info[:company_name] = config_json['account_info']['acount_company_name'].strip
24
+ end
25
+
26
+ # 提取 Bundle ID
27
+ if config_json['app_info'] && config_json['app_info']['app_identifier']
28
+ config_info[:bundle_id] = config_json['app_info']['app_identifier']
29
+ end
30
+
31
+ # 提取版本号
32
+ if config_json['app_info'] && config_json['app_info']['app_version']
33
+ config_info[:app_version] = config_json['app_info']['app_version']
34
+ else
35
+ config_info[:app_version] = "1.0.0" # 默认版本
36
+ end
37
+
38
+ config_info
39
+ end
40
+
41
+ # 执行 iTunes Connect App 创建流程
42
+ # @param config_json [Hash] 配置 JSON 对象
43
+ # @param config_path [String] 配置文件路径
44
+ # @param app_version [String, nil] 应用版本号
45
+ # @param company_name [String, nil] 公司名称
46
+ def self.execute_itcapp_creation(config_json:, config_path:, app_version: nil, company_name: nil)
47
+ # 提取配置信息
48
+ config_info = extract_config_info(config_json)
49
+
50
+ # 使用命令行参数覆盖配置
51
+ config_info[:app_version] = app_version if app_version
52
+ config_info[:company_name] = company_name if company_name
53
+
54
+ # 验证必需字段
55
+ raise "配置文件中缺少 Apple ID" if config_info[:apple_id].nil? || config_info[:apple_id].empty?
56
+ raise "配置文件中缺少 Bundle ID" if config_info[:bundle_id].nil? || config_info[:bundle_id].empty?
57
+
58
+ # 确保 Bundle ID 在开发者中心存在
59
+ ensure_bundle_id_exists(
60
+ apple_id: config_info[:apple_id],
61
+ bundle_id: config_info[:bundle_id],
62
+ config_path: config_path
63
+ )
64
+
65
+ # 创建 iTunes Connect App
66
+ puts "Create app in itc ..."
67
+ puts config_info[:apple_id]
68
+ puts "Login #{config_info[:apple_id]}..."
69
+
70
+ Spaceship::Tunes.login(config_info[:apple_id].to_s)
71
+ Spaceship::Tunes.select_team
72
+
73
+ app = create_itcapp(
74
+ bundle_id: config_info[:bundle_id],
75
+ app_version: config_info[:app_version],
76
+ company_name: config_info[:company_name]
77
+ )
78
+
79
+ # 修改配置文件,添加 App ID
80
+ if app
81
+ modify_appconfig_with_appid(
82
+ config_path: config_path,
83
+ bundle_id: config_info[:bundle_id],
84
+ app: app
85
+ )
86
+ end
87
+
88
+ app
89
+ end
90
+
91
+ # 确保 Bundle ID 在开发者中心存在
92
+ # @param apple_id [String] Apple ID
93
+ # @param bundle_id [String] Bundle ID
94
+ # @param config_path [String] 配置文件路径
95
+ def self.ensure_bundle_id_exists(apple_id:, bundle_id:, config_path:)
96
+ Spaceship::Portal.login(apple_id.to_s)
97
+ Spaceship::Portal.select_team
98
+
99
+ app = Spaceship::Portal.app.find(bundle_id)
100
+ if app.nil?
101
+ puts "Bundle ID #{bundle_id} 不存在,需要先创建"
102
+ puts "请先运行: pindo appstore bundleid #{config_path}"
103
+ raise "Bundle ID #{bundle_id} 不存在于 Apple 开发者中心"
104
+ end
105
+ end
106
+
107
+ # 创建 iTunes Connect App
108
+ # @param bundle_id [String] Bundle ID
109
+ # @param app_version [String] 应用版本号
110
+ # @param company_name [String, nil] 公司名称
111
+ # @return [Object] 创建的 App 对象
112
+ def self.create_itcapp(bundle_id:, app_version:, company_name: nil)
113
+ return nil if bundle_id.nil?
114
+
115
+ # 检查 App 是否已存在
116
+ app = Spaceship::ConnectAPI::App.find(bundle_id)
117
+ if app
118
+ puts "App is already exist !!!"
119
+ return app
120
+ end
121
+
122
+ # 生成默认 SKU ID
123
+ app_sku_id_fixed = bundle_id + ".sku"
124
+ puts "App的默认sku id 为: #{app_sku_id_fixed}"
125
+
126
+ # 让用户自定义 SKU ID
127
+ input_skuid = ask("请自定义输入App Sku ID: ") || nil
128
+ if !input_skuid.nil? && input_skuid.length > 1
129
+ app_sku_id_fixed = input_skuid
130
+ end
131
+
132
+ # 获取公司名称
133
+ if company_name.nil?
134
+ company_name = ask('Company Name : ') || nil
135
+ end
136
+
137
+ puts "App Sku ID : #{app_sku_id_fixed}"
138
+ puts "Company Name : #{company_name}"
139
+
140
+ # 确认信息
141
+ answer = agree("请确认上面信息是否正确(Y/n):")
142
+ unless answer
143
+ raise "用户取消创建,请重新运行命令"
144
+ end
145
+
146
+ # 生成 App 名称(移除点号,最多30个字符)
147
+ app_default_name = bundle_id.gsub('.', '')
148
+ if app_default_name.length > 30
149
+ app_default_name = app_default_name[0, 30]
150
+ end
151
+
152
+ # 创建 App
153
+ app = Spaceship::ConnectAPI::App.create(
154
+ name: app_default_name,
155
+ version_string: app_version,
156
+ sku: app_sku_id_fixed,
157
+ primary_locale: "en-US",
158
+ bundle_id: bundle_id,
159
+ platforms: ["IOS"],
160
+ company_name: company_name
161
+ )
162
+
163
+ puts "App is created !!!"
164
+ app
165
+ end
166
+
167
+ # 修改配置文件,添加 App ID
168
+ # @param config_path [String] 配置文件路径
169
+ # @param bundle_id [String] Bundle ID
170
+ # @param app [Object] App 对象
171
+ def self.modify_appconfig_with_appid(config_path:, bundle_id:, app:)
172
+ return if app.nil?
173
+
174
+ puts
175
+ puts "app.id : #{app.id} +++++++++"
176
+ puts
177
+
178
+ # 修改本地配置文件
179
+ modify_appconfig_file(config_file: config_path, app_info_detail: app)
180
+
181
+ # 修改远程配置仓库
182
+ begin
183
+ require_relative '../../base/githelper'
184
+ include Pindo::Githelper
185
+
186
+ app_config_dir = clong_buildconfig_repo(repo_name: bundle_id)
187
+ app_config_file = File.join(app_config_dir, "config.json")
188
+
189
+ if File.exist?(app_config_file)
190
+ modify_appconfig_file(config_file: app_config_file, app_info_detail: app)
191
+ prepare_gitenv()
192
+ git_addpush_repo(path: app_config_dir, message: "modify apple id")
193
+ end
194
+ rescue StandardError => e
195
+ puts "更新远程配置仓库失败: #{e.message}"
196
+ end
197
+ end
198
+
199
+ # 修改单个配置文件
200
+ # @param config_file [String] 配置文件路径
201
+ # @param app_info_detail [Object] App 信息对象
202
+ def self.modify_appconfig_file(config_file:, app_info_detail:)
203
+ return unless File.exist?(config_file)
204
+
205
+ config_content = JSON.parse(File.read(config_file))
206
+
207
+ File.open(config_file, "w") do |f|
208
+ # 更新 app_id_ios
209
+ config_content['app_info']['app_id_ios'] = app_info_detail.id
210
+
211
+ # 更新 apple_app_id(如果存在)
212
+ if config_content['app_setting'] && config_content['app_setting']["apple_app_id"]
213
+ config_content['app_setting']["apple_app_id"] = app_info_detail.id
214
+ end
215
+
216
+ # 更新 kGUKeyAppId(如果存在)
217
+ if config_content['app_setting'] && config_content['app_setting']["kGUKeyAppId"]
218
+ config_content['app_setting']["kGUKeyAppId"] = app_info_detail.id
219
+ end
220
+
221
+ f.write(JSON.pretty_generate(config_content))
222
+ end
223
+
224
+ puts "✓ 配置文件已更新: #{config_file}"
225
+ end
226
+
227
+ end
228
+ end
@@ -196,6 +196,18 @@ module Pindo
196
196
  nil
197
197
  end
198
198
  end
199
+
200
+ # 拉取应用配置仓库(委托给 BuildInfoManager)
201
+ # @param repo_name [String] 仓库名称(Bundle ID)
202
+ # @param target_dir [String, nil] 目标目录(默认:当前目录)
203
+ # @return [Boolean] 是否成功拉取配置
204
+ def pull_appconfig_with_reponame(repo_name:, target_dir: nil)
205
+ require_relative '../../config/build_info_manager'
206
+ Pindo::BuildInfoManager.share_instance.pull_appconfig_with_reponame(
207
+ repo_name: repo_name,
208
+ target_dir: target_dir
209
+ )
210
+ end
199
211
  end
200
212
 
201
213
  end
@@ -2,94 +2,133 @@ require 'highline/import'
2
2
  require 'xcodeproj'
3
3
  require 'json'
4
4
  require 'yaml'
5
-
5
+ require 'pindo/base/git_handler'
6
6
 
7
7
  module Pindo
8
- module SwarkHelper
9
-
10
- def check_swark_authorize(config_json:nil, buid_type:nil)
11
- if !config_json.nil? && config_json['project_info']['xcode_build_type'] && config_json["project_info"]["xcode_build_type"].include?("swark")
12
-
13
- app_config_dir = File.join(File::expand_path(pindo_single_config.pindo_dir), @deploy_identifier)
14
- swark_authorize_file = File.join(app_config_dir, "swark_authorize.json")
15
- if File.exist?(swark_authorize_file)
16
- swark_authorize_json=JSON.parse(File.read(swark_authorize_file))
17
- unless swark_authorize_json && swark_authorize_json['swark_authorize_status']
18
- show_swark_authorize_error(swark_authorize_json:swark_authorize_json , buid_type:buid_type)
19
- end
20
- end
21
- end
22
- end
8
+ # Swark 授权辅助类
9
+ # 负责 Swark 授权检查、权限配置等操作
10
+ class SwarkHelper
11
+
12
+ # 检查 Swark 授权状态
13
+ # @param config_json [Hash] 配置 JSON 对象
14
+ # @param buid_type [String] 构建类型(dev/adhoc/appstore)
15
+ # @param deploy_identifier [String] 部署标识符
16
+ def self.check_swark_authorize(config_json:, buid_type:, deploy_identifier:)
17
+ return unless config_json &&
18
+ config_json['project_info'] &&
19
+ config_json['project_info']['xcode_build_type'] &&
20
+ config_json['project_info']['xcode_build_type'].include?("swark")
23
21
 
24
- def show_swark_authorize_error(swark_authorize_json:nil, buid_type:nil)
25
-
26
- puts "++++ +++ Need authorize !!! ++++"
27
- puts "+++ Need authorize !!! ++++"
28
- puts "+++ Need authorize !!! +++++"
29
- puts " =========================="
30
- puts
31
-
32
- puts "方法一:"
33
- command = " 1. swark authorize "
34
- command = command + swark_authorize_json["swark_authorize_teamid"] + "." + swark_authorize_json["swark_authorize_bundleid"]
35
- puts command
36
- command = " 2. 修改swark_authorize.json 中的 swark_authorize_status = true 并且提交"
37
- puts
38
-
39
- puts "方法二:"
40
- puts " pindo deploy quswark"
41
- if buid_type.downcase.to_s.include?("appstore")
42
- raise Informative, "Need swark authorize !!!"
43
- end
22
+ require 'pindo/config/pindoconfig'
23
+ app_config_dir = File.join(File.expand_path(Pindoconfig.instance.pindo_dir), deploy_identifier)
24
+ swark_authorize_file = File.join(app_config_dir, "swark_authorize.json")
25
+
26
+ if File.exist?(swark_authorize_file)
27
+ swark_authorize_json = JSON.parse(File.read(swark_authorize_file))
28
+ unless swark_authorize_json && swark_authorize_json['swark_authorize_status']
29
+ show_swark_authorize_error(
30
+ swark_authorize_json: swark_authorize_json,
31
+ buid_type: buid_type
32
+ )
44
33
  end
34
+ end
35
+ end
45
36
 
37
+ # 显示 Swark 授权错误信息
38
+ # @param swark_authorize_json [Hash] Swark 授权配置 JSON
39
+ # @param buid_type [String] 构建类型
40
+ def self.show_swark_authorize_error(swark_authorize_json:, buid_type:)
41
+ puts "++++ +++ Need authorize !!! ++++"
42
+ puts "+++ Need authorize !!! ++++"
43
+ puts "+++ Need authorize !!! +++++"
44
+ puts " =========================="
45
+ puts
46
46
 
47
- def add_swark_entitlement(entitlements_plist_path:nil, bundle_id_dict:nil)
48
- if @config_json['project_info']['xcode_build_type'] && @config_json["project_info"]["xcode_build_type"].include?("swark")
49
- if File.exist?(entitlements_plist_path)
50
- entitlements_plist_dict = Xcodeproj::Plist.read_from_path(entitlements_plist_path)
47
+ puts "方法一:"
48
+ command = " 1. swark authorize "
49
+ command += swark_authorize_json["swark_authorize_teamid"] + "." + swark_authorize_json["swark_authorize_bundleid"]
50
+ puts command
51
+ puts " 2. 修改swark_authorize.json 中的 swark_authorize_status = true 并且提交"
52
+ puts
51
53
 
52
- key_value = @team_id_vaule
53
- key_value = key_value + "." + @bundle_id
54
- entitlements_plist_dict['keychain-access-groups'] = [key_value]
54
+ puts "方法二:"
55
+ puts " pindo deploy quswark"
55
56
 
56
- Xcodeproj::Plist.write_to_path(entitlements_plist_dict, entitlements_plist_path)
57
- end
58
- end
57
+ if buid_type.downcase.to_s.include?("appstore")
58
+ raise Informative, "Need swark authorize !!!"
59
59
  end
60
+ end
61
+
62
+ # 添加 Swark 权限配置到 entitlements
63
+ # @param entitlements_plist_path [String] entitlements.plist 文件路径
64
+ # @param bundle_id_dict [Hash] Bundle ID 字典
65
+ # @param config_json [Hash] 配置 JSON 对象
66
+ # @param team_id [String] Team ID
67
+ # @param bundle_id [String] Bundle ID
68
+ def self.add_swark_entitlement(
69
+ entitlements_plist_path:,
70
+ bundle_id_dict:,
71
+ config_json:,
72
+ team_id:,
73
+ bundle_id:
74
+ )
75
+ return unless config_json &&
76
+ config_json['project_info'] &&
77
+ config_json['project_info']['xcode_build_type'] &&
78
+ config_json['project_info']['xcode_build_type'].include?("swark")
79
+
80
+ return unless File.exist?(entitlements_plist_path)
81
+
82
+ entitlements_plist_dict = Xcodeproj::Plist.read_from_path(entitlements_plist_path)
60
83
 
61
- def add_swark_authorize_json
62
- if @build_type == "appstore" && @config_json['project_info']['xcode_build_type'] && @config_json["project_info"]["xcode_build_type"].include?("swark")
63
-
64
- app_config_dir = clong_buildconfig_repo(repo_name: @deploy_repo_name)
65
- swark_authorize_file = File.join(app_config_dir, "swark_authorize.json")
66
- if File.exist?(swark_authorize_file)
67
- swark_authorize_json=JSON.parse(File.read(swark_authorize_file))
68
- if swark_authorize_json && swark_authorize_json['swark_authorize_status']
69
- puts "swark already authorize success !!! "
70
- else
71
- swark_authorize_json = swark_authorize_json || {}
72
- swark_authorize_json['swark_authorize_teamid'] = @team_id_vaule
73
- swark_authorize_json['swark_authorize_bundleid'] = @bundle_id
74
- swark_authorize_json['swark_authorize_status'] = false
75
- File.open(swark_authorize_file, "w") do |f|
76
- f.write(JSON.pretty_generate(swark_authorize_json))
77
- end
78
- git_addpush_repo(path:app_config_dir, message:"add swark authorize json")
79
- end
80
- else
81
- swark_authorize_json = swark_authorize_json || {}
82
- swark_authorize_json['swark_authorize_teamid'] = @team_id_vaule
83
- swark_authorize_json['swark_authorize_bundleid'] = @bundle_id
84
- swark_authorize_json['swark_authorize_status'] = false
85
- File.open(swark_authorize_file, "w") do |f|
86
- f.write(JSON.pretty_generate(swark_authorize_json))
87
- end
88
- git_addpush_repo(path:app_config_dir, message:"add swark authorize json")
84
+ key_value = team_id + "." + bundle_id
85
+ entitlements_plist_dict['keychain-access-groups'] = [key_value]
86
+
87
+ Xcodeproj::Plist.write_to_path(entitlements_plist_dict, entitlements_plist_path)
88
+ end
89
+
90
+ # 添加 Swark 授权配置文件
91
+ # @param build_type [String] 构建类型(dev/adhoc/appstore)
92
+ # @param config_json [Hash] 配置 JSON 对象
93
+ # @param team_id [String] Team ID
94
+ # @param bundle_id [String] Bundle ID
95
+ # @param deploy_repo_name [String] 部署仓库名称
96
+ def self.add_swark_authorize_json(
97
+ build_type:,
98
+ config_json:,
99
+ team_id:,
100
+ bundle_id:,
101
+ deploy_repo_name:
102
+ )
103
+ return unless build_type == "appstore" &&
104
+ config_json &&
105
+ config_json['project_info'] &&
106
+ config_json['project_info']['xcode_build_type'] &&
107
+ config_json['project_info']['xcode_build_type'].include?("swark")
108
+
109
+ app_config_dir = Pindo::GitHandler.clong_buildconfig_repo(repo_name: deploy_repo_name)
110
+ swark_authorize_file = File.join(app_config_dir, "swark_authorize.json")
111
+
112
+ if File.exist?(swark_authorize_file)
113
+ swark_authorize_json = JSON.parse(File.read(swark_authorize_file))
114
+ if swark_authorize_json && swark_authorize_json['swark_authorize_status']
115
+ puts "swark already authorize success !!! "
116
+ return
89
117
  end
90
-
91
- end
92
118
  end
93
119
 
120
+ # 创建或更新授权文件
121
+ swark_authorize_json = {}
122
+ swark_authorize_json['swark_authorize_teamid'] = team_id
123
+ swark_authorize_json['swark_authorize_bundleid'] = bundle_id
124
+ swark_authorize_json['swark_authorize_status'] = false
125
+
126
+ File.open(swark_authorize_file, "w") do |f|
127
+ f.write(JSON.pretty_generate(swark_authorize_json))
128
+ end
129
+
130
+ Pindo::GitHandler.git_addpush_repo(path: app_config_dir, message: "add swark authorize json")
131
+ end
132
+
94
133
  end
95
- end
134
+ end
@@ -2,6 +2,8 @@
2
2
 
3
3
  require 'match'
4
4
  require 'openssl'
5
+ require 'open3'
6
+ require 'fileutils'
5
7
  require 'pindo/base/aeshelper'
6
8
  require 'pindo/module/cert/keychain_helper'
7
9
  require 'pindo/module/cert/provisioning_helper'
@@ -14,6 +16,78 @@ module Pindo
14
16
  @@password_cache = {}
15
17
 
16
18
  class << self
19
+ # 清理 Git 仓库中的证书
20
+ # @param apple_id [String] Apple ID
21
+ # @param pindo_dir [String] Pindo 目录路径
22
+ # @param deploy_cert_giturl [String] 部署证书 Git URL
23
+ # @param dev_cert_giturl [String] 开发证书 Git URL
24
+ # @param demo_apple_id [String] Demo Apple ID
25
+ def clean_git_certs(apple_id:, pindo_dir:, deploy_cert_giturl:, dev_cert_giturl:, demo_apple_id:)
26
+ require_relative '../../base/git_handler'
27
+
28
+ # 确定使用哪个 Git URL
29
+ git_url = apple_id.eql?(demo_apple_id) ? dev_cert_giturl : deploy_cert_giturl
30
+
31
+ puts "正在清理 Git 仓库中的证书..."
32
+ puts "Apple ID: #{apple_id}"
33
+ puts "Git URL: #{git_url}"
34
+
35
+ # 克隆或更新证书仓库
36
+ cert_repo_dir = Pindo::GitHandler.getcode_to_dir(
37
+ reponame: Pindo::GitHandler.get_repo_base_name(repo_url: git_url),
38
+ remote_url: git_url,
39
+ path: pindo_dir,
40
+ new_branch: apple_id
41
+ )
42
+
43
+ # 删除 certs 和 profiles 目录
44
+ certs_dir = File.join(cert_repo_dir, "certs")
45
+ profiles_dir = File.join(cert_repo_dir, "profiles")
46
+
47
+ FileUtils.rm_rf(certs_dir) if File.exist?(certs_dir)
48
+ FileUtils.rm_rf(profiles_dir) if File.exist?(profiles_dir)
49
+
50
+ puts "✓ 已删除 certs 和 profiles 目录"
51
+
52
+ # 提交并推送到远程仓库
53
+ Pindo::GitHandler.prepare_gitenv()
54
+ Pindo::GitHandler.git_addpush_repo(path: cert_repo_dir, message: "remove #{apple_id} certs")
55
+
56
+ puts "✓ Git 仓库证书清理完成"
57
+ end
58
+
59
+ # 清理本地证书
60
+ # 删除系统中所有的 Apple Development 和 Apple Distribution 证书
61
+ # 清理 Provisioning Profiles 文件夹
62
+ def clean_local_certs
63
+ puts "正在清理本地证书..."
64
+
65
+ # 获取所有代码签名证书
66
+ output, _ = Open3.capture2('security find-identity -p codesigning')
67
+ identity_ids_0 = []
68
+ identity_ids_1 = output.split("\n").map { |line| line.split(' ')[1] if line.include?('Apple Development') }.compact
69
+ identity_ids_2 = output.split("\n").map { |line| line.split(' ')[1] if line.include?('Apple Distribution') }.compact
70
+ identity_ids = identity_ids_0 + identity_ids_1 + identity_ids_2
71
+ identity_ids = identity_ids.uniq
72
+
73
+ puts "找到 #{identity_ids.size} 个证书:"
74
+ puts identity_ids
75
+
76
+ # 删除证书
77
+ identity_ids.each do |identity_id|
78
+ system "security delete-certificate -Z #{identity_id}"
79
+ end
80
+
81
+ # 清理 Provisioning Profiles
82
+ profile_file_dir = File.expand_path("~/Library/MobileDevice")
83
+ profile_file_path = File.join(profile_file_dir, "Provisioning Profiles")
84
+ if File.exist?(profile_file_path)
85
+ FileUtils.rm_rf(profile_file_path)
86
+ puts "✓ 已清理 Provisioning Profiles 文件夹"
87
+ end
88
+
89
+ puts "✓ 本地证书清理完成"
90
+ end
17
91
  # 获取密码的辅助方法,使用缓存避免重复获取
18
92
  def get_cached_password(cert_url)
19
93
  unless @@password_cache[cert_url]
@@ -4,6 +4,78 @@ module Pindo
4
4
  class PemHelper
5
5
  class << self
6
6
 
7
+ # 从配置文件中提取所有必要的信息
8
+ # @param config_json [Hash] 配置 JSON 对象
9
+ # @return [Hash] 提取的配置信息
10
+ def extract_config_info(config_json)
11
+ config_info = {}
12
+
13
+ # 提取 Apple ID
14
+ if config_json['account_info'] && config_json['account_info']['apple_acount_id']
15
+ config_info[:apple_id] = config_json['account_info']['apple_acount_id']
16
+ end
17
+
18
+ # 提取 Bundle ID
19
+ if config_json['app_info'] && config_json['app_info']['app_identifier']
20
+ config_info[:bundle_id] = config_json['app_info']['app_identifier']
21
+ end
22
+
23
+ config_info
24
+ end
25
+
26
+ # 执行 Push 证书创建流程
27
+ # @param config_json [Hash] 配置 JSON 对象
28
+ # @param dev_flag [Boolean] 是否为开发证书
29
+ # @param deploy_repo_name [String, nil] 部署仓库名称
30
+ def execute_pem_creation(config_json:, dev_flag: false, deploy_repo_name: nil)
31
+ require_relative '../../base/githelper'
32
+ include Pindo::Githelper
33
+
34
+ # 提取配置信息
35
+ config_info = extract_config_info(config_json)
36
+
37
+ # 验证必需字段
38
+ raise "配置文件中缺少 Apple ID" if config_info[:apple_id].nil? || config_info[:apple_id].empty?
39
+ raise "配置文件中缺少 Bundle ID" if config_info[:bundle_id].nil? || config_info[:bundle_id].empty?
40
+
41
+ # 登录 Apple 开发者中心
42
+ puts config_info[:apple_id]
43
+ puts "Login #{config_info[:apple_id]}..."
44
+ login(apple_id: config_info[:apple_id])
45
+
46
+ # 确定证书类型
47
+ pem_type = dev_flag ? "dev" : "prod"
48
+
49
+ # 创建输出目录
50
+ temp_dir = "push_" + Time.now.to_i.to_s
51
+ push_path = File.join(File.expand_path('~/Desktop/'), temp_dir)
52
+ FileUtils.mkdir_p(push_path) unless File.exist?(push_path)
53
+ puts "证书输出路径: #{push_path}"
54
+
55
+ # 创建证书
56
+ x509_cert_path = create_certificate(
57
+ bundle_id: config_info[:bundle_id],
58
+ type: pem_type,
59
+ output_path: push_path
60
+ )
61
+
62
+ # 如果提供了部署仓库名称,则上传到 Git 仓库
63
+ if !deploy_repo_name.nil? && !deploy_repo_name.empty? && File.exist?(x509_cert_path) && File.exist?(push_path)
64
+ app_config_dir = clong_buildconfig_repo(repo_name: deploy_repo_name)
65
+ push_repo_dir = File.join(app_config_dir, "push")
66
+
67
+ FileUtils.mkdir_p(push_repo_dir) unless File.exist?(push_repo_dir)
68
+ FileUtils.cp_r(File.join(push_path, "."), push_repo_dir)
69
+
70
+ prepare_gitenv()
71
+ git_addpush_repo(path: app_config_dir, message: "add push cert")
72
+
73
+ puts "✓ 证书已上传到配置仓库: #{push_repo_dir}"
74
+ end
75
+
76
+ x509_cert_path
77
+ end
78
+
7
79
  def create_certificate(bundle_id:nil, type:"prod", output_path:"")
8
80
 
9
81
  if bundle_id.empty? || output_path.empty?