pindo 5.17.5 → 5.18.4
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/git_handler.rb +120 -38
- data/lib/pindo/command/android/autobuild.rb +81 -40
- data/lib/pindo/command/appstore/adhocbuild.rb +1 -1
- data/lib/pindo/command/appstore/autobuild.rb +1 -1
- data/lib/pindo/command/appstore/autoresign.rb +1 -1
- data/lib/pindo/command/appstore/updateid.rb +229 -0
- data/lib/pindo/command/appstore.rb +1 -0
- data/lib/pindo/command/ios/autobuild.rb +70 -33
- data/lib/pindo/command/ios/podpush.rb +1 -1
- data/lib/pindo/command/jps/apptest.rb +2 -2
- data/lib/pindo/command/jps/bind.rb +1 -1
- data/lib/pindo/command/jps/media.rb +1 -1
- data/lib/pindo/command/jps/upload.rb +52 -22
- data/lib/pindo/command/unity/autobuild.rb +61 -44
- data/lib/pindo/command/utils/allcopyconfig.rb +144 -0
- data/lib/pindo/command/utils/copyconfig.rb +207 -0
- data/lib/pindo/command/utils/icon.rb +2 -2
- data/lib/pindo/command/utils/renewbundleid.rb +199 -0
- data/lib/pindo/command/utils/renewcert.rb +56 -54
- data/lib/pindo/command/utils.rb +3 -0
- data/lib/pindo/command/web/autobuild.rb +32 -26
- data/lib/pindo/config/build_info_manager.rb +1 -3
- data/lib/pindo/module/android/android_build_helper.rb +193 -33
- data/lib/pindo/module/android/android_config_helper.rb +305 -88
- data/lib/pindo/module/android/android_project_helper.rb +69 -14
- data/lib/pindo/module/android/android_res_helper.rb +349 -51
- data/lib/pindo/module/android/keystore_helper.rb +611 -295
- data/lib/pindo/module/android/workflow_gradle_injector.rb +702 -0
- data/lib/pindo/module/appselect.rb +4 -4
- data/lib/pindo/module/appstore/bundleid_helper.rb +204 -14
- data/lib/pindo/module/build/build_helper.rb +110 -10
- data/lib/pindo/module/build/git_repo_helper.rb +4 -4
- data/lib/pindo/module/cert/mode/base_cert_operator.rb +8 -6
- data/lib/pindo/module/pgyer/pgyerhelper.rb +105 -42
- data/lib/pindo/module/task/core/task_executor.rb +2 -0
- data/lib/pindo/module/task/model/build/android_build_dev_task.rb +64 -6
- data/lib/pindo/module/task/model/git/git_commit_task.rb +70 -54
- data/lib/pindo/module/task/model/git/git_tag_task.rb +13 -9
- data/lib/pindo/module/task/model/jps/jps_upload_task.rb +104 -1
- data/lib/pindo/module/task/model/unity/unity_export_task.rb +2 -1
- data/lib/pindo/module/task/model/unity/unity_update_task.rb +2 -1
- data/lib/pindo/module/task/model/unity/unity_yoo_asset_task.rb +2 -1
- data/lib/pindo/module/task/model/unity_task.rb +2 -1
- data/lib/pindo/module/task/task_manager.rb +8 -0
- data/lib/pindo/module/unity/unity_helper.rb +13 -10
- data/lib/pindo/module/unity/unity_proc_helper.rb +27 -2
- data/lib/pindo/module/xcode/applovin_xcode_helper.rb +4 -2
- data/lib/pindo/module/xcode/res/xcode_res_constant.rb +72 -0
- data/lib/pindo/module/xcode/xcode_build_config.rb +36 -17
- data/lib/pindo/module/xcode/xcode_build_helper.rb +180 -23
- data/lib/pindo/module/xcode/xcode_project_helper.rb +1 -1
- data/lib/pindo/module/xcode/xcode_res_helper.rb +32 -16
- data/lib/pindo/options/groups/build_options.rb +16 -5
- data/lib/pindo/options/groups/git_options.rb +7 -5
- data/lib/pindo/options/groups/unity_options.rb +11 -0
- data/lib/pindo/options/helpers/bundleid_selector.rb +25 -0
- data/lib/pindo/options/helpers/git_constants.rb +7 -6
- data/lib/pindo/version.rb +2 -2
- metadata +10 -5
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
require 'json'
|
|
3
|
+
require 'spaceship'
|
|
4
|
+
require 'pindo/options/options'
|
|
5
|
+
require 'pindo/module/appstore/bundleid_helper'
|
|
6
|
+
require 'pindo/base/git_handler'
|
|
7
|
+
require 'pindo/config/build_info_manager'
|
|
8
|
+
|
|
9
|
+
module Pindo
|
|
10
|
+
class Command
|
|
11
|
+
class Appstore < Command
|
|
12
|
+
class Updateid < Appstore
|
|
13
|
+
|
|
14
|
+
self.summary = '从Apple开发者中心同步bundle id的capabilities到config.json'
|
|
15
|
+
|
|
16
|
+
self.description = <<-DESC
|
|
17
|
+
从Apple Developer Portal读取当前项目Bundle ID的Capability状态,
|
|
18
|
+
写入config.json的capabilities字段并提交到Git仓库。
|
|
19
|
+
|
|
20
|
+
支持功能:
|
|
21
|
+
|
|
22
|
+
* 读取主Bundle ID和所有Extension的Capability状态
|
|
23
|
+
|
|
24
|
+
* 自动识别App Group、iCloud容器的关联ID
|
|
25
|
+
|
|
26
|
+
* 将capabilities写入config.json并提交到Git仓库
|
|
27
|
+
|
|
28
|
+
* 支持dry-run预览模式
|
|
29
|
+
|
|
30
|
+
使用示例:
|
|
31
|
+
|
|
32
|
+
$ pindo appstore updateid # 使用当前目录的config.json
|
|
33
|
+
|
|
34
|
+
$ pindo appstore updateid --config=config.json # 指定config.json路径
|
|
35
|
+
|
|
36
|
+
$ pindo appstore updateid --dry-run # 预览模式,不修改文件
|
|
37
|
+
DESC
|
|
38
|
+
|
|
39
|
+
self.arguments = [
|
|
40
|
+
CLAide::Argument.new('path/to/config.json', true)
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
def self.option_items
|
|
44
|
+
@option_items ||= [
|
|
45
|
+
Pindo::Options::OptionItem.new(
|
|
46
|
+
key: :config,
|
|
47
|
+
description: '指定config.json文件路径',
|
|
48
|
+
type: String,
|
|
49
|
+
optional: true,
|
|
50
|
+
example: 'pindo appstore updateid --config=config.json'
|
|
51
|
+
),
|
|
52
|
+
Pindo::Options::OptionItem.new(
|
|
53
|
+
key: :dry_run,
|
|
54
|
+
description: '预览模式,只显示差异不修改文件',
|
|
55
|
+
type: :boolean,
|
|
56
|
+
optional: true,
|
|
57
|
+
default_value: false,
|
|
58
|
+
example: 'pindo appstore updateid --dry-run'
|
|
59
|
+
)
|
|
60
|
+
]
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def self.options
|
|
64
|
+
option_items.map { |item| item.to_claide_option }.concat(super)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def initialize(argv)
|
|
68
|
+
positional_config = argv.shift_argument
|
|
69
|
+
@options = initialize_options(argv)
|
|
70
|
+
@config_path = @options[:config] || positional_config || File.join(Dir.pwd, 'config.json')
|
|
71
|
+
@dry_run = @options[:dry_run]
|
|
72
|
+
super
|
|
73
|
+
@additional_args = argv.remainder!
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def validate!
|
|
77
|
+
super
|
|
78
|
+
unless File.exist?(@config_path)
|
|
79
|
+
help! "配置文件不存在: #{@config_path}"
|
|
80
|
+
end
|
|
81
|
+
begin
|
|
82
|
+
@config_json = JSON.parse(File.read(@config_path))
|
|
83
|
+
rescue JSON::ParserError => e
|
|
84
|
+
help! "配置文件格式错误: #{e.message}"
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# 验证 app_identifier
|
|
88
|
+
app_info = @config_json['app_info']
|
|
89
|
+
if app_info.nil? || app_info['app_identifier'].nil? || app_info['app_identifier'].empty?
|
|
90
|
+
help! "config.json 中缺少 app_info.app_identifier"
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# 验证 Apple ID
|
|
94
|
+
apple_id = @config_json.dig('account_info', 'apple_acount_id')
|
|
95
|
+
if apple_id.nil? || apple_id.empty? || apple_id.include?("__________")
|
|
96
|
+
help! "config.json 中缺少有效的 Apple ID (account_info.apple_acount_id)"
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def run
|
|
101
|
+
begin
|
|
102
|
+
app_info = @config_json['app_info']
|
|
103
|
+
apple_id = @config_json.dig('account_info', 'apple_acount_id')
|
|
104
|
+
|
|
105
|
+
# 登录 Apple Developer Portal
|
|
106
|
+
puts "Login #{apple_id}..."
|
|
107
|
+
Spaceship.login(apple_id.to_s)
|
|
108
|
+
Spaceship.select_team
|
|
109
|
+
|
|
110
|
+
bundle_id = app_info['app_identifier']
|
|
111
|
+
puts
|
|
112
|
+
puts "读取 #{bundle_id} 的 Capability..."
|
|
113
|
+
|
|
114
|
+
# 读取主 Bundle ID 的 capabilities
|
|
115
|
+
capabilities = Pindo::BundleIdHelper.fetch_capabilities_from_portal(bundle_id: bundle_id)
|
|
116
|
+
|
|
117
|
+
if capabilities.nil?
|
|
118
|
+
puts "无法读取 #{bundle_id} 的 Capability,跳过"
|
|
119
|
+
return
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# 显示读取到的 capabilities
|
|
123
|
+
capabilities.each do |key, value|
|
|
124
|
+
puts " #{key}: #{value.is_a?(String) ? "\"#{value}\"" : value}"
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# 更新所有 Extension Bundle ID 的名称
|
|
128
|
+
puts
|
|
129
|
+
extension_keys = app_info.keys.select { |k| k.start_with?("app_identifier_") }
|
|
130
|
+
extension_keys.each do |key|
|
|
131
|
+
ext_bundle_id = app_info[key]
|
|
132
|
+
next if ext_bundle_id.nil? || ext_bundle_id.empty? || ext_bundle_id.include?("__________")
|
|
133
|
+
|
|
134
|
+
expected_name = Pindo::BundleIdHelper.generate_bundleid_name(ext_bundle_id)
|
|
135
|
+
ext_app = Spaceship::Portal.app.find(ext_bundle_id)
|
|
136
|
+
if ext_app.nil?
|
|
137
|
+
puts " #{ext_bundle_id} — Portal 中未找到,跳过"
|
|
138
|
+
next
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
if ext_app.name != expected_name
|
|
142
|
+
puts "Update #{ext_bundle_id} name: #{ext_app.name} -> #{expected_name}"
|
|
143
|
+
begin
|
|
144
|
+
ext_app.update_name!(expected_name)
|
|
145
|
+
rescue => e
|
|
146
|
+
puts " Portal 更新名称失败: #{e.message},尝试通过 API Key 更新..."
|
|
147
|
+
begin
|
|
148
|
+
Pindo::BundleIdHelper.update_bundleid_name(bundle_id: ext_bundle_id, new_name: expected_name)
|
|
149
|
+
rescue => e2
|
|
150
|
+
puts " 更新名称失败: #{e2.message}"
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
if @dry_run
|
|
157
|
+
# dry-run 模式:对比现有 capabilities 并显示差异
|
|
158
|
+
old_capabilities = app_info['capabilities'] || {}
|
|
159
|
+
puts
|
|
160
|
+
puts "[dry-run] 差异:"
|
|
161
|
+
has_diff = false
|
|
162
|
+
capabilities.each do |key, new_value|
|
|
163
|
+
old_value = old_capabilities[key]
|
|
164
|
+
if old_value.nil?
|
|
165
|
+
puts " + #{key}: #{new_value.is_a?(String) ? "\"#{new_value}\"" : new_value}"
|
|
166
|
+
has_diff = true
|
|
167
|
+
elsif old_value != new_value
|
|
168
|
+
old_display = old_value.is_a?(String) ? "\"#{old_value}\"" : old_value
|
|
169
|
+
new_display = new_value.is_a?(String) ? "\"#{new_value}\"" : new_value
|
|
170
|
+
puts " ~ #{key}: #{old_display} -> #{new_display}"
|
|
171
|
+
has_diff = true
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
old_capabilities.each do |key, old_value|
|
|
175
|
+
unless capabilities.key?(key)
|
|
176
|
+
old_display = old_value.is_a?(String) ? "\"#{old_value}\"" : old_value
|
|
177
|
+
puts " = #{key}: #{old_display} (保留)"
|
|
178
|
+
has_diff = true
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
puts " (无差异)" unless has_diff
|
|
182
|
+
puts
|
|
183
|
+
puts "[dry-run] 未修改任何文件"
|
|
184
|
+
else
|
|
185
|
+
# 获取 config 仓库目录并更新到最新(~/.pindo/{bundle_id}/)
|
|
186
|
+
app_config_dir = Pindo::GitHandler.clong_buildconfig_repo(repo_name: bundle_id)
|
|
187
|
+
config_repo_file = File.join(app_config_dir, "config.json")
|
|
188
|
+
|
|
189
|
+
# 提交前先丢弃仓库中未跟踪的修改,确保干净状态
|
|
190
|
+
Pindo::GitHandler.git!(%W(-C #{app_config_dir} checkout -- config.json)) rescue nil
|
|
191
|
+
|
|
192
|
+
# 读取仓库中最新的 config.json 并更新 capabilities
|
|
193
|
+
repo_config_json = JSON.parse(File.read(config_repo_file))
|
|
194
|
+
repo_config_json['app_info']['capabilities'] = (repo_config_json['app_info']['capabilities'] || {}).merge(capabilities)
|
|
195
|
+
|
|
196
|
+
# 只写入 config.json 一个文件
|
|
197
|
+
File.open(config_repo_file, "w") do |f|
|
|
198
|
+
f.write(JSON.pretty_generate(repo_config_json) + "\n")
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# 同时更新本地 config.json(如果路径不同)
|
|
202
|
+
if File.expand_path(@config_path) != File.expand_path(config_repo_file)
|
|
203
|
+
@config_json['app_info']['capabilities'] = (app_info['capabilities'] || {}).merge(capabilities)
|
|
204
|
+
File.open(@config_path, "w") do |f|
|
|
205
|
+
f.write(JSON.pretty_generate(@config_json) + "\n")
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
puts
|
|
210
|
+
|
|
211
|
+
# 只提交 config.json 到 Git 仓库
|
|
212
|
+
Pindo::GitHandler.git_addpush_repo(
|
|
213
|
+
path: app_config_dir,
|
|
214
|
+
message: "sync capabilities from Apple Developer Portal",
|
|
215
|
+
commit_file_params: ["config.json"]
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
puts "capabilities 已写入 config.json 并提交"
|
|
219
|
+
end
|
|
220
|
+
rescue StandardError => e
|
|
221
|
+
puts "\n updateid 失败: #{e.message}"
|
|
222
|
+
raise e
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
end
|
|
@@ -158,27 +158,18 @@ module Pindo
|
|
|
158
158
|
|
|
159
159
|
def validate!
|
|
160
160
|
super # 基类的 HelpValidator 会统一处理 --help
|
|
161
|
-
|
|
162
|
-
# 如果没有指定 bundleid,进行交互式选择
|
|
163
|
-
if @args_bundle_id.nil? || @args_bundle_id.empty?
|
|
164
|
-
@args_bundle_id = Pindo::Options::BundleIdSelector.select_bundleid(@build_type)
|
|
165
|
-
|
|
166
|
-
# 如果用户取消选择或选择失败,报错
|
|
167
|
-
if @args_bundle_id.nil? || @args_bundle_id.empty?
|
|
168
|
-
help! "未选择有效的 Bundle ID"
|
|
169
|
-
end
|
|
170
|
-
|
|
171
|
-
# 重要:将交互式选择的值同步回 @options,确保能被缓存系统保存
|
|
172
|
-
@options[:bundleid] = @args_bundle_id
|
|
173
|
-
end
|
|
161
|
+
# bundle_id 校验推迟到 run 中,在 load_jps_build_config 之后解析
|
|
174
162
|
end
|
|
175
163
|
|
|
176
164
|
def run
|
|
177
165
|
pindo_project_dir = Dir.pwd
|
|
178
166
|
|
|
179
167
|
begin
|
|
180
|
-
# 加载 JPS
|
|
181
|
-
Pindo::BuildHelper.share_instance.load_jps_build_config(pindo_project_dir)
|
|
168
|
+
# 加载 JPS 配置(缓存 project_name,并通过映射表解析 bundle_id)
|
|
169
|
+
Pindo::BuildHelper.share_instance.load_jps_build_config(pindo_project_dir, conf: @args_conf)
|
|
170
|
+
|
|
171
|
+
# 解析 bundle_id(优先级:命令行参数 > JPSBuildConfig映射 > 交互选择)
|
|
172
|
+
resolve_bundle_id!
|
|
182
173
|
|
|
183
174
|
# 准备配置
|
|
184
175
|
config = prepare_ios_config(pindo_project_dir)
|
|
@@ -207,6 +198,44 @@ module Pindo
|
|
|
207
198
|
|
|
208
199
|
private
|
|
209
200
|
|
|
201
|
+
# 解析 bundle_id(优先级:命令行参数 > JPSBuildConfig映射 > prepare_upload交互选择)
|
|
202
|
+
def resolve_bundle_id!
|
|
203
|
+
# 优先级 1:命令行 --bundleid 参数
|
|
204
|
+
return if @args_bundle_id && !@args_bundle_id.empty?
|
|
205
|
+
|
|
206
|
+
# 优先级 2:JPSBuildConfig.json 通过映射表解析的 bundle_id
|
|
207
|
+
resolved = Pindo::Options::GlobalOptionsState.instance[:bundleid]
|
|
208
|
+
if resolved && !resolved.empty?
|
|
209
|
+
@args_bundle_id = resolved
|
|
210
|
+
return
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
# 优先级 3:走 prepare_upload 交互选择 JPS 项目,创建/更新 JPSBuildConfig.json
|
|
214
|
+
pindo_project_dir = Dir.pwd
|
|
215
|
+
is_macos = Pindo::BuildHelper.share_instance.macos_project?(pindo_project_dir)
|
|
216
|
+
package_type = is_macos ? 'mac' : 'ipa'
|
|
217
|
+
|
|
218
|
+
@cached_app_info_obj, @cached_workflow_info = PgyerHelper.share_instace.prepare_upload(
|
|
219
|
+
working_directory: pindo_project_dir,
|
|
220
|
+
conf: @args_conf,
|
|
221
|
+
package_type: package_type
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
# prepare_upload 已创建 JPSBuildConfig.json,重新加载获取 bundle_id
|
|
225
|
+
Pindo::BuildHelper.share_instance.load_jps_build_config(pindo_project_dir, conf: @args_conf)
|
|
226
|
+
resolved = Pindo::Options::GlobalOptionsState.instance[:bundleid]
|
|
227
|
+
if resolved && !resolved.empty?
|
|
228
|
+
@args_bundle_id = resolved
|
|
229
|
+
return
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# 最终降级:交互选择 bundle_id
|
|
233
|
+
@args_bundle_id = Pindo::Options::BundleIdSelector.select_bundleid(@build_type)
|
|
234
|
+
if @args_bundle_id.nil? || @args_bundle_id.empty?
|
|
235
|
+
raise Informative, "未选择有效的 Bundle ID"
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
|
|
210
239
|
# 创建构建任务
|
|
211
240
|
def make_build_task(config)
|
|
212
241
|
# 检测项目类型
|
|
@@ -316,12 +345,15 @@ module Pindo
|
|
|
316
345
|
build_task.dependencies << tasks.last.id if tasks.any?
|
|
317
346
|
tasks << build_task
|
|
318
347
|
|
|
319
|
-
# 4. Git
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
348
|
+
# 4. Git 标签任务(skip_without_tag 模式下不创建)
|
|
349
|
+
git_tag_task = nil
|
|
350
|
+
unless process_type == Pindo::UncommittedFilesProcessType::SKIP_WITHOUT_TAG
|
|
351
|
+
# 所有参数都从 GitCommitTask 获取
|
|
352
|
+
git_tag_task = Pindo::TaskSystem::GitTagTask.new(config[:project_path])
|
|
353
|
+
git_tag_task.dependencies << build_task.id
|
|
354
|
+
git_tag_task.dependencies << git_commit_task.id
|
|
355
|
+
tasks << git_tag_task
|
|
356
|
+
end
|
|
325
357
|
|
|
326
358
|
# 5. 上传和消息发送任务(如果需要)
|
|
327
359
|
upload_task = nil # 声明变量以便后续绑定任务使用
|
|
@@ -421,7 +453,7 @@ module Pindo
|
|
|
421
453
|
)
|
|
422
454
|
# 依赖 Git Commit、Git Tag 和 Bind Package 任务
|
|
423
455
|
workflow_message_task.dependencies << git_commit_task.id
|
|
424
|
-
workflow_message_task.dependencies << git_tag_task.id
|
|
456
|
+
workflow_message_task.dependencies << git_tag_task.id if git_tag_task
|
|
425
457
|
workflow_message_task.dependencies << bind_package_task.id
|
|
426
458
|
tasks << workflow_message_task
|
|
427
459
|
end
|
|
@@ -440,17 +472,22 @@ module Pindo
|
|
|
440
472
|
# 拉取并加载配置文件到 IosConfigParser
|
|
441
473
|
load_config_file(pindo_project_dir, bundle_id)
|
|
442
474
|
|
|
443
|
-
# 获取 JPS
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
475
|
+
# 获取 JPS 配置(复用 resolve_bundle_id! 中已缓存的结果)
|
|
476
|
+
if @cached_app_info_obj && @cached_workflow_info
|
|
477
|
+
app_info_obj = @cached_app_info_obj
|
|
478
|
+
workflow_info = @cached_workflow_info
|
|
479
|
+
else
|
|
480
|
+
# 根据 Xcode 工程类型动态设置 package_type
|
|
481
|
+
# JPSUploadTask 支持的文件类型:'ipa' | 'apk' | 'html' | 'mac'
|
|
482
|
+
is_macos = Pindo::BuildHelper.share_instance.macos_project?(pindo_project_dir)
|
|
483
|
+
package_type = is_macos ? 'mac' : 'ipa'
|
|
484
|
+
|
|
485
|
+
app_info_obj, workflow_info = PgyerHelper.share_instace.prepare_upload(
|
|
486
|
+
working_directory: pindo_project_dir,
|
|
487
|
+
conf: @args_conf,
|
|
488
|
+
package_type: package_type
|
|
489
|
+
)
|
|
490
|
+
end
|
|
454
491
|
|
|
455
492
|
{
|
|
456
493
|
project_path: pindo_project_dir,
|
|
@@ -193,7 +193,7 @@ module Pindo
|
|
|
193
193
|
git!(%W(-C #{private_source.repo} reset --hard))
|
|
194
194
|
git!(%W(-C #{private_source.repo} clean -dfx))
|
|
195
195
|
git!(%W(-C #{private_source.repo} branch --set-upstream-to=origin/#{private_source_branch} #{private_source_branch}))
|
|
196
|
-
|
|
196
|
+
Pindo::GitHandler.git_remote!(private_source.repo, %W(-C #{private_source.repo} pull))
|
|
197
197
|
rescue StandardError => e
|
|
198
198
|
raise Informative, "私有Pod索引目录异常,请删除#{private_source.repo}重新新下载"
|
|
199
199
|
end
|
|
@@ -172,7 +172,7 @@ module Pindo
|
|
|
172
172
|
tasks.each { |task| task_manager.add_task(task) }
|
|
173
173
|
task_manager.start
|
|
174
174
|
|
|
175
|
-
# 6.
|
|
175
|
+
# 6. 输出结果(任务失败时 start 会自动抛出异常;这里仍要求至少成功一个任务)
|
|
176
176
|
report = task_manager.execution_report
|
|
177
177
|
if report[:success] > 0
|
|
178
178
|
puts "\n✅ 消息发送完成!"
|
|
@@ -184,4 +184,4 @@ module Pindo
|
|
|
184
184
|
end
|
|
185
185
|
end
|
|
186
186
|
end
|
|
187
|
-
end
|
|
187
|
+
end
|
|
@@ -165,7 +165,7 @@ module Pindo
|
|
|
165
165
|
tasks.each { |task| task_manager.add_task(task) }
|
|
166
166
|
task_manager.start
|
|
167
167
|
|
|
168
|
-
# 7.
|
|
168
|
+
# 7. 输出结果(任务失败时 start 会自动抛出异常;这里仍要求至少成功一个任务)
|
|
169
169
|
report = task_manager.execution_report
|
|
170
170
|
if report[:success] > 0
|
|
171
171
|
puts "\n✅ 绑定完成! 成功绑定 #{app_version_list.size} 个包到 Git Workflow"
|
|
@@ -25,7 +25,8 @@ module Pindo
|
|
|
25
25
|
支持功能:
|
|
26
26
|
|
|
27
27
|
* 上传ipa/apk/app/exe/html安装包
|
|
28
|
-
* Unity工程自动检测iOS/Android/WebGL/Windows包
|
|
28
|
+
* Unity工程自动检测iOS/Android/WebGL/macOS/Windows包
|
|
29
|
+
* 通过 --types 指定要上传的包类型(与 unity autobuild 一致)
|
|
29
30
|
* 添加版本描述
|
|
30
31
|
* 上传附件
|
|
31
32
|
* 重签名
|
|
@@ -37,6 +38,12 @@ module Pindo
|
|
|
37
38
|
|
|
38
39
|
$ pindo jps upload path/to/setup.exe # 上传 Windows 安装包
|
|
39
40
|
|
|
41
|
+
$ pindo jps upload --types=ipa # 仅上传 IPA
|
|
42
|
+
|
|
43
|
+
$ pindo jps upload --types=ipa,apk # 上传 IPA 和 APK
|
|
44
|
+
|
|
45
|
+
$ pindo jps upload --types=html # 仅上传 WebGL
|
|
46
|
+
|
|
40
47
|
$ pindo jps upload --proj=demo # 上传到指定项目
|
|
41
48
|
|
|
42
49
|
$ pindo jps upload --desc="版本说明" # 添加版本描述
|
|
@@ -59,6 +66,7 @@ module Pindo
|
|
|
59
66
|
# 定义此命令使用的参数项
|
|
60
67
|
def self.option_items
|
|
61
68
|
@option_items ||= Pindo::Options::OptionGroup.merge(
|
|
69
|
+
Pindo::Options::BuildOptions.select(:types),
|
|
62
70
|
Pindo::Options::JPSOptions.select(:conf, :send, :desc, :resign),
|
|
63
71
|
Pindo::Options::GitOptions.all
|
|
64
72
|
)
|
|
@@ -67,18 +75,18 @@ module Pindo
|
|
|
67
75
|
def self.options
|
|
68
76
|
[
|
|
69
77
|
['--login', '强制再次登录jps网站'],
|
|
70
|
-
['--
|
|
71
|
-
['--attach', '
|
|
78
|
+
['--file', '指定要上传的文件路径(支持 ipa/apk/app/exe/html)'],
|
|
79
|
+
['--attach', '指定需要和安装包一起上传的附件'],
|
|
72
80
|
].concat(option_items.map(&:to_claide_option)).concat(super)
|
|
73
81
|
end
|
|
74
82
|
|
|
75
83
|
|
|
76
84
|
def initialize(argv)
|
|
77
85
|
@args_ipa_file = argv.shift_argument
|
|
78
|
-
|
|
86
|
+
file_option = argv.option('file') || argv.option('ipa')
|
|
79
87
|
|
|
80
|
-
if
|
|
81
|
-
@args_ipa_file =
|
|
88
|
+
if !file_option.nil?
|
|
89
|
+
@args_ipa_file = file_option
|
|
82
90
|
end
|
|
83
91
|
if @args_ipa_file && !@args_ipa_file.empty?
|
|
84
92
|
@args_ipa_file = @args_ipa_file.strip.gsub(/\"/, '')
|
|
@@ -90,6 +98,8 @@ module Pindo
|
|
|
90
98
|
# 使用 Options 系统解析参数
|
|
91
99
|
@options = initialize_options(argv)
|
|
92
100
|
|
|
101
|
+
@args_types = @options[:types]
|
|
102
|
+
|
|
93
103
|
# JPS 参数
|
|
94
104
|
@args_conf = @options[:conf]
|
|
95
105
|
@args_send_flag = @options[:send] || false
|
|
@@ -283,22 +293,39 @@ module Pindo
|
|
|
283
293
|
end
|
|
284
294
|
end
|
|
285
295
|
|
|
296
|
+
# 解析 --types 参数,返回允许的类型数组,nil 表示不限制
|
|
297
|
+
def parse_types_filter
|
|
298
|
+
return nil unless @args_types
|
|
299
|
+
|
|
300
|
+
available_types = %w[ipa apk html mac exe]
|
|
301
|
+
types = @args_types.downcase.split(',').map(&:strip)
|
|
302
|
+
|
|
303
|
+
invalid_types = types - available_types
|
|
304
|
+
unless invalid_types.empty?
|
|
305
|
+
raise Informative, "无效的包类型: #{invalid_types.join(', ')}。可用类型: #{available_types.join(', ')}"
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
types
|
|
309
|
+
end
|
|
310
|
+
|
|
286
311
|
# 查找并确认 Unity 包(可能有多个平台)
|
|
287
312
|
def find_and_confirm_unity_packages(project_dir, tasks)
|
|
313
|
+
types_filter = parse_types_filter
|
|
314
|
+
|
|
288
315
|
# 1. 查找所有平台的文件
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
found_files
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
316
|
+
all_candidates = [
|
|
317
|
+
{ file: find_unity_ios_package(project_dir), type: 'ipa', name: 'iOS' },
|
|
318
|
+
{ file: find_unity_macos_package(project_dir), type: 'mac', name: 'macOS' },
|
|
319
|
+
{ file: find_unity_android_package(project_dir), type: 'apk', name: 'Android' },
|
|
320
|
+
{ file: find_unity_webgl_package(project_dir), type: 'html', name: 'WebGL' },
|
|
321
|
+
{ file: find_unity_windows_package(project_dir), type: 'exe', name: 'Windows' }
|
|
322
|
+
]
|
|
323
|
+
|
|
324
|
+
# 2. 过滤:去掉未找到的文件,按 --types 过滤
|
|
325
|
+
found_files = all_candidates.select { |info| info[:file] }
|
|
326
|
+
if types_filter
|
|
327
|
+
found_files = found_files.select { |info| types_filter.include?(info[:type]) }
|
|
328
|
+
end
|
|
302
329
|
|
|
303
330
|
# 3. 如果没有找到任何文件,直接返回
|
|
304
331
|
return if found_files.empty?
|
|
@@ -440,10 +467,13 @@ module Pindo
|
|
|
440
467
|
windows_files.max_by {|f| File.mtime(f)} if windows_files.any?
|
|
441
468
|
end
|
|
442
469
|
|
|
443
|
-
#
|
|
470
|
+
# 确认文件(交互式,设置 PINDO_AUTO_CONFIRM 时自动确认)
|
|
444
471
|
def confirm_file(file_path)
|
|
445
|
-
|
|
446
|
-
|
|
472
|
+
if ENV['PINDO_AUTO_CONFIRM'] && !ENV['PINDO_AUTO_CONFIRM'].empty?
|
|
473
|
+
puts "自动确认上传文件: #{file_path}"
|
|
474
|
+
return true
|
|
475
|
+
end
|
|
476
|
+
agree("需要上传文件: #{file_path} ?(Y/n)")
|
|
447
477
|
end
|
|
448
478
|
|
|
449
479
|
# 根据文件扩展名确定文件类型
|