pindo 5.13.1 → 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 (110) 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 +258 -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/autobuild.rb +64 -43
  24. data/lib/pindo/command/ios/autoresign.rb +34 -19
  25. data/lib/pindo/command/ios/build.rb +9 -6
  26. data/lib/pindo/command/ios/cert.rb +27 -20
  27. data/lib/pindo/command/jps/upload.rb +3 -3
  28. data/lib/pindo/command/unity/autobuild.rb +2 -2
  29. data/lib/pindo/command/utils/clearcert.rb +2 -17
  30. data/lib/pindo/command/{deploy → utils}/fabric.rb +13 -13
  31. data/lib/pindo/command/utils/renewcert.rb +62 -38
  32. data/lib/pindo/command/utils/renewproj.rb +0 -3
  33. data/lib/pindo/command/{deploy → utils}/updateconfig.rb +6 -7
  34. data/lib/pindo/command/utils.rb +2 -0
  35. data/lib/pindo/command/web/autobuild.rb +2 -2
  36. data/lib/pindo/command.rb +30 -3
  37. data/lib/pindo/config/build_info_manager.rb +176 -0
  38. data/lib/pindo/config/ios_config_parser.rb +404 -0
  39. data/lib/pindo/module/android/android_config_helper.rb +9 -5
  40. data/lib/pindo/module/appstore/bundleid_helper.rb +349 -0
  41. data/lib/pindo/module/appstore/itcapp_helper.rb +228 -0
  42. data/lib/pindo/module/build/build_helper.rb +12 -0
  43. data/lib/pindo/module/build/swark_helper.rb +116 -77
  44. data/lib/pindo/module/cert/cert_helper.rb +74 -0
  45. data/lib/pindo/module/cert/pem_helper.rb +72 -0
  46. data/lib/pindo/module/cert/{xcodecerthelper.rb → xcode_cert_helper.rb} +208 -6
  47. data/lib/pindo/module/task/model/appstore/appstore_task.rb +18 -0
  48. data/lib/pindo/module/task/model/appstore/appstore_upload_ipa_task.rb +151 -0
  49. data/lib/pindo/module/task/model/appstore/appstore_upload_metadata_task.rb +250 -0
  50. data/lib/pindo/module/task/model/appstore/appstore_upload_screenshot_task.rb +276 -0
  51. data/lib/pindo/module/task/model/build/android_build_adhoc_task.rb +210 -0
  52. data/lib/pindo/module/task/model/build/{android_dev_build_task.rb → android_build_dev_task.rb} +2 -2
  53. data/lib/pindo/module/task/model/build/android_build_gplay_task.rb +210 -0
  54. data/lib/pindo/module/task/model/build/android_build_task.rb +13 -0
  55. data/lib/pindo/module/task/model/build/ios_build_adhoc_task.rb +197 -0
  56. data/lib/pindo/module/task/model/build/ios_build_appstore_task.rb +367 -0
  57. data/lib/pindo/module/task/model/build/{ios_dev_build_task.rb → ios_build_dev_task.rb} +37 -27
  58. data/lib/pindo/module/task/model/build/ios_build_task.rb +13 -0
  59. data/lib/pindo/module/task/model/build/{web_dev_build_task.rb → web_build_dev_task.rb} +1 -1
  60. data/lib/pindo/module/task/model/build_task.rb +15 -12
  61. data/lib/pindo/module/task/model/jps_resign_task.rb +185 -0
  62. data/lib/pindo/module/task/model/{upload_task.rb → jps_upload_task.rb} +3 -3
  63. data/lib/pindo/module/task/model/unity_export_task.rb +3 -1
  64. data/lib/pindo/module/unity/unity_helper.rb +2 -1
  65. data/lib/pindo/module/xcode/ipa_resign_helper.rb +210 -0
  66. data/lib/pindo/module/xcode/{xcodeappconfig.rb → xcode_app_config.rb} +79 -0
  67. data/lib/pindo/module/xcode/xcode_build_config.rb +152 -17
  68. data/lib/pindo/module/xcode/xcode_build_helper.rb +151 -1
  69. data/lib/pindo/module/xcode/xcode_swark_helper.rb +341 -0
  70. data/lib/pindo/options/core/global_options_state.rb +268 -0
  71. data/lib/pindo/options/core/option_configuration.rb +206 -0
  72. data/lib/pindo/options/core/option_initializer.rb +51 -0
  73. data/lib/pindo/options/core/option_item.rb +144 -0
  74. data/lib/pindo/options/core/option_value_parser.rb +54 -0
  75. data/lib/pindo/options/groups/build_options.rb +60 -0
  76. data/lib/pindo/options/groups/jps_options.rb +70 -0
  77. data/lib/pindo/options/groups/option_group.rb +73 -0
  78. data/lib/pindo/options/helpers/bundleid_selector.rb +103 -0
  79. data/lib/pindo/options/options.rb +14 -0
  80. data/lib/pindo/version.rb +1 -1
  81. metadata +49 -40
  82. data/lib/pindo/command/appstore/import.rb +0 -259
  83. data/lib/pindo/command/deploy/build.rb +0 -250
  84. data/lib/pindo/command/deploy/bundleid.rb +0 -259
  85. data/lib/pindo/command/deploy/cert.rb +0 -202
  86. data/lib/pindo/command/deploy/check.rb +0 -93
  87. data/lib/pindo/command/deploy/configproj.rb +0 -120
  88. data/lib/pindo/command/deploy/confusecode.rb +0 -262
  89. data/lib/pindo/command/deploy/confuseproj.rb +0 -122
  90. data/lib/pindo/command/deploy/iap.rb +0 -826
  91. data/lib/pindo/command/deploy/initconfig.rb +0 -138
  92. data/lib/pindo/command/deploy/itcapp.rb +0 -146
  93. data/lib/pindo/command/deploy/pem.rb +0 -55
  94. data/lib/pindo/command/deploy/pullconfig.rb +0 -56
  95. data/lib/pindo/command/deploy/pushconfig.rb +0 -93
  96. data/lib/pindo/command/deploy/quswark.rb +0 -156
  97. data/lib/pindo/command/deploy/quswauth.rb +0 -76
  98. data/lib/pindo/command/deploy/reportbug.rb +0 -145
  99. data/lib/pindo/command/deploy/resign.rb +0 -300
  100. data/lib/pindo/command/deploy/tag.rb +0 -108
  101. data/lib/pindo/command/deploy/uploadipa.rb +0 -73
  102. data/lib/pindo/command/deploy.rb +0 -42
  103. data/lib/pindo/command/dev/autobuild.rb +0 -117
  104. data/lib/pindo/command/dev/build.rb +0 -94
  105. data/lib/pindo/command/dev/debug.rb +0 -112
  106. data/lib/pindo/module/task/model/build/android_release_build_task.rb +0 -29
  107. data/lib/pindo/module/task/model/build/ios_adhoc_build_task.rb +0 -53
  108. data/lib/pindo/module/task/model/build/ios_release_build_task.rb +0 -53
  109. data/lib/pindo/options/appconfigoptions.rb +0 -24
  110. data/lib/pindo/options/deployoptions.rb +0 -372
@@ -0,0 +1,206 @@
1
+ require 'pindo/options/core/option_item'
2
+
3
+ module Pindo
4
+ module Options
5
+ # 参数配置管理器(简化版)
6
+ # 负责管理参数值的生命周期:默认值、类型转换、验证
7
+ class OptionConfiguration
8
+
9
+ # 初始化
10
+ # @param available_options [Array<OptionItem>] 可用参数列表
11
+ # @param raw_values [Hash] 原始参数值
12
+ # @param command_instance [Object, nil] 命令实例(用于 value_block)
13
+ def initialize(available_options, raw_values = {}, command_instance: nil)
14
+ @available_options = available_options
15
+ @raw_values = raw_values
16
+ @command_instance = command_instance
17
+ @values = {}
18
+ @options_map = build_options_map
19
+
20
+ # 执行参数处理流程
21
+ process_all_options
22
+ end
23
+
24
+ # 获取参数值(支持符号和字符串)
25
+ # @param key [Symbol, String] 参数键名
26
+ # @return [Object] 参数值
27
+ def [](key)
28
+ key = normalize_key(key)
29
+ @values[key]
30
+ end
31
+
32
+ # 设置参数值
33
+ # @param key [Symbol, String] 参数键名
34
+ # @param value [Object] 参数值
35
+ def []=(key, value)
36
+ key = normalize_key(key)
37
+ option_item = @options_map[key]
38
+
39
+ if option_item
40
+ @values[key] = option_item.auto_convert_value(value)
41
+ option_item.valid?(@values[key])
42
+ else
43
+ @values[key] = value
44
+ end
45
+ end
46
+
47
+ # 获取所有参数值
48
+ # @return [Hash] 所有参数值
49
+ def to_hash
50
+ @values.dup
51
+ end
52
+
53
+ # 检查参数是否存在
54
+ # @param key [Symbol, String] 参数键名
55
+ # @return [Boolean]
56
+ def key?(key)
57
+ @values.key?(normalize_key(key))
58
+ end
59
+
60
+ # 获取所有参数键
61
+ # @return [Array<Symbol>]
62
+ def keys
63
+ @values.keys
64
+ end
65
+
66
+ # 遍历所有参数
67
+ # @yield [key, value] 参数键值对
68
+ def each(&block)
69
+ @values.each(&block)
70
+ end
71
+
72
+ private
73
+
74
+ # 构建参数映射表(支持别名)
75
+ # @return [Hash{Symbol => OptionItem}]
76
+ def build_options_map
77
+ map = {}
78
+ @available_options.each do |item|
79
+ # 主键
80
+ map[item.key] = item
81
+ # 别名
82
+ item.aliases.each do |alias_name|
83
+ map[alias_name] = item
84
+ end
85
+ end
86
+ map
87
+ end
88
+
89
+ # 参数处理主流程
90
+ def process_all_options
91
+ # 1. 应用默认值
92
+ apply_defaults
93
+
94
+ # 2. 应用原始值(命令行参数和环境变量)
95
+ apply_raw_values
96
+
97
+ # 3. 应用 value_block(交互式获取值)
98
+ apply_value_blocks
99
+
100
+ # 4. 类型转换
101
+ convert_types
102
+
103
+ # 5. 验证必填参数
104
+ validate_required
105
+
106
+ # 6. 自定义验证
107
+ validate_custom
108
+ end
109
+
110
+ # 应用默认值
111
+ def apply_defaults
112
+ @available_options.each do |item|
113
+ @values[item.key] = item.default_value if item.default_value
114
+ end
115
+ end
116
+
117
+ # 应用原始值(映射别名到主键)
118
+ def apply_raw_values
119
+ @raw_values.each do |key, value|
120
+ normalized_key = normalize_key(key)
121
+ option_item = @options_map[normalized_key]
122
+
123
+ if option_item
124
+ # 使用主键存储
125
+ @values[option_item.key] = value
126
+ else
127
+ # 未知参数,仍然保存(可能是其他用途)
128
+ @values[normalized_key] = value
129
+ end
130
+ end
131
+ end
132
+
133
+ # 应用 value_block(交互式获取值)
134
+ # 优先级:命令行参数 > 缓存(已在 raw_values) > value_block > 默认值
135
+ def apply_value_blocks
136
+ @available_options.each do |item|
137
+ # 只有当参数没有值时,才调用 value_block
138
+ next if @values.key?(item.key) && !@values[item.key].nil?
139
+ next unless item.value_block
140
+
141
+ begin
142
+ # 调用 value_block 获取值
143
+ # 如果 value_block 接受参数,则传入命令实例
144
+ value = if item.value_block.arity > 0
145
+ item.value_block.call(@command_instance)
146
+ else
147
+ item.value_block.call
148
+ end
149
+ @values[item.key] = value unless value.nil?
150
+ rescue StandardError => e
151
+ # value_block 执行失败,记录错误但不中断流程
152
+ puts "[OptionConfiguration] value_block 执行失败 (#{item.key}): #{e.message}"
153
+ end
154
+ end
155
+ end
156
+
157
+ # 类型转换
158
+ def convert_types
159
+ @available_options.each do |item|
160
+ next unless @values.key?(item.key)
161
+
162
+ begin
163
+ converted_value = item.auto_convert_value(@values[item.key])
164
+ @values[item.key] = converted_value
165
+ rescue StandardError => e
166
+ raise ArgumentError, "参数 '#{item.key}' 类型转换失败: #{e.message}"
167
+ end
168
+ end
169
+ end
170
+
171
+ # 验证必填参数
172
+ def validate_required
173
+ @available_options.each do |item|
174
+ next if item.optional
175
+
176
+ # 检查参数是否存在且不为 nil
177
+ unless @values.key?(item.key) && !@values[item.key].nil?
178
+ raise ArgumentError, "参数 '#{item.key}' 是必填的"
179
+ end
180
+ end
181
+ end
182
+
183
+ # 自定义验证(verify_block)
184
+ def validate_custom
185
+ @available_options.each do |item|
186
+ next unless item.verify_block
187
+ next unless @values.key?(item.key)
188
+
189
+ value = @values[item.key]
190
+ begin
191
+ item.verify_block.call(value)
192
+ rescue StandardError => e
193
+ raise ArgumentError, "参数 '#{item.key}' 验证失败: #{e.message}"
194
+ end
195
+ end
196
+ end
197
+
198
+ # 标准化键名(转为 Symbol)
199
+ # @param key [Symbol, String] 键名
200
+ # @return [Symbol]
201
+ def normalize_key(key)
202
+ key.to_sym
203
+ end
204
+ end
205
+ end
206
+ end
@@ -0,0 +1,51 @@
1
+ require 'pindo/options/core/option_value_parser'
2
+ require 'pindo/options/core/option_configuration'
3
+ require 'pindo/options/core/global_options_state'
4
+
5
+ module Pindo
6
+ module Options
7
+ # 参数初始化器
8
+ # 提供统一的参数初始化流程:解析 → 配置 → 注册
9
+ module OptionInitializer
10
+ # 初始化命令参数
11
+ #
12
+ # @param command_instance [Object] 命令实例
13
+ # @param argv [CLAide::ARGV] 命令行参数
14
+ # @param option_items [Array<OptionItem>] 参数项列表
15
+ # @param command_name [String] 命令名称
16
+ # @param directory [String, nil] 工作目录(默认:当前目录)
17
+ # @param enable_cache [Boolean] 是否启用缓存(默认:false)
18
+ # @return [OptionConfiguration] 参数配置对象
19
+ def self.initialize(command_instance, argv, option_items, command_name, directory: nil, enable_cache: false)
20
+ # 1. 解析参数值(从命令行和环境变量)
21
+ raw_values = OptionValueParser.parse(argv, option_items)
22
+
23
+ # 2. 如果启用缓存,合并缓存值到 raw_values
24
+ if enable_cache
25
+ state = GlobalOptionsState.instance
26
+ state.prepare_cache(command_name, directory || Dir.pwd)
27
+ cached_values = state.load_cached_values
28
+
29
+ # 缓存值优先级:命令行参数 > 缓存 > 默认值
30
+ # 只有在命令行未提供的参数才使用缓存
31
+ cached_values.each do |key, value|
32
+ raw_values[key] = value unless raw_values.key?(key)
33
+ end
34
+ end
35
+
36
+ # 3. 创建参数配置(自动处理验证等,传入命令实例用于 value_block)
37
+ options = OptionConfiguration.new(option_items, raw_values, command_instance: command_instance)
38
+
39
+ # 4. 设置全局状态
40
+ GlobalOptionsState.instance.set_command(
41
+ command_name,
42
+ options,
43
+ directory: directory || Dir.pwd,
44
+ enable_cache: enable_cache
45
+ )
46
+
47
+ options
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,144 @@
1
+ module Pindo
2
+ module Options
3
+ # OptionItem 类定义单个参数的所有属性和行为(简化版)
4
+ class OptionItem
5
+
6
+ # 核心属性
7
+ attr_accessor :key # Symbol: 参数键名
8
+ attr_accessor :description # String: 参数描述
9
+ attr_accessor :type # Class: 数据类型 (String/Integer/Boolean)
10
+ attr_accessor :env_name # String: 环境变量名
11
+ attr_accessor :aliases # Array<Symbol>: 参数别名
12
+ attr_accessor :default_value # Any: 默认值
13
+ attr_accessor :optional # Boolean: 是否可选(默认为 true)
14
+ attr_accessor :verify_block # Proc: 自定义验证逻辑
15
+ attr_accessor :value_block # Proc: 获取参数值的 block(交互式输入)
16
+ attr_accessor :example # String: 使用示例
17
+
18
+ # Boolean 类型标记
19
+ Boolean = :boolean
20
+
21
+ # 初始化方法
22
+ # @param key [Symbol] 参数键名(必填)
23
+ # @param options [Hash] 其他配置选项
24
+ def initialize(key:, **options)
25
+ raise ArgumentError, "key must be a Symbol" unless key.is_a?(Symbol)
26
+
27
+ @key = key
28
+ @description = options[:description] || options[:desc] || ""
29
+ @type = options[:type] || String
30
+ @env_name = options[:env_name]
31
+ @aliases = options[:aliases] || []
32
+ @default_value = options[:default_value] || options[:default]
33
+ @optional = options.fetch(:optional, true)
34
+ @verify_block = options[:verify_block]
35
+ @value_block = options[:value_block]
36
+ @example = options[:example]
37
+
38
+ validate_type!
39
+ end
40
+
41
+ # 判断是否是 Boolean 类型
42
+ def boolean?
43
+ @type == Boolean || @type == :boolean
44
+ end
45
+
46
+ # 从环境变量读取值
47
+ # @return [String, nil] 环境变量的值
48
+ def fetch_env_value
49
+ return nil unless @env_name
50
+ value = ENV[@env_name]
51
+ value if value && !value.empty?
52
+ end
53
+
54
+ # 自动类型转换
55
+ # @param value [Any] 原始值
56
+ # @return [Any] 转换后的值
57
+ def auto_convert_value(value)
58
+ return nil if value.nil?
59
+
60
+ case @type
61
+ when Boolean, :boolean
62
+ # Boolean 转换
63
+ if value.is_a?(String)
64
+ return true if value.downcase == 'true' || value == '1'
65
+ return false if value.downcase == 'false' || value == '0'
66
+ end
67
+ !!value
68
+ when Integer
69
+ value.to_i
70
+ else
71
+ # String 或其他类型
72
+ value.to_s
73
+ end
74
+ rescue StandardError => e
75
+ raise ArgumentError, "参数 '#{@key}' 类型转换失败: #{e.message}"
76
+ end
77
+
78
+ # 验证参数值
79
+ # @param value [Any] 要验证的值
80
+ # @return [Boolean] 验证是否通过
81
+ def valid?(value)
82
+ return true unless @verify_block
83
+
84
+ begin
85
+ @verify_block.call(value)
86
+ true
87
+ rescue StandardError => e
88
+ raise ArgumentError, "参数 '#{@key}' 验证失败: #{e.message}"
89
+ end
90
+ end
91
+
92
+ # 转换为 CLAide 选项格式(用于 --help 输出)
93
+ # @return [Array] CLAide 选项格式 [option_string, description]
94
+ def to_claide_option
95
+ option_string = build_option_string
96
+ description_text = build_description_text
97
+
98
+ [option_string, description_text]
99
+ end
100
+
101
+ private
102
+
103
+ # 验证类型是否合法
104
+ def validate_type!
105
+ valid_types = [String, Integer, Boolean, :boolean]
106
+ unless valid_types.include?(@type)
107
+ raise ArgumentError, "Invalid type: #{@type}. Valid types: #{valid_types.join(', ')}"
108
+ end
109
+ end
110
+
111
+ # 构建选项字符串(--key[=VALUE] 格式)
112
+ def build_option_string
113
+ # 只显示主选项,不显示别名(避免输出过长导致换行)
114
+ if boolean?
115
+ "--#{@key}"
116
+ else
117
+ type_hint = type_to_hint
118
+ "--#{@key}=#{type_hint}"
119
+ end
120
+ end
121
+
122
+ # 构建描述文本(描述 + 环境变量)
123
+ def build_description_text
124
+ if @env_name
125
+ "#{@description} (环境变量: #{@env_name})"
126
+ else
127
+ @description
128
+ end
129
+ end
130
+
131
+ # 类型转换为提示字符串
132
+ def type_to_hint
133
+ case @type
134
+ when String
135
+ 'VALUE'
136
+ when Integer
137
+ 'NUMBER'
138
+ else
139
+ 'VALUE'
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,54 @@
1
+ require 'pindo/options/core/option_item'
2
+
3
+ module Pindo
4
+ module Options
5
+ # 参数值解析器
6
+ # 负责从 CLAide::ARGV 和环境变量中提取参数的原始值
7
+ class OptionValueParser
8
+
9
+ # 解析参数值
10
+ # @param argv [CLAide::ARGV] CLAide 的参数对象
11
+ # @param option_items [Array<OptionItem>] 参数定义列表
12
+ # @return [Hash] 原始参数值 Hash { key: raw_value }
13
+ def self.parse(argv, option_items)
14
+ values = {}
15
+
16
+ option_items.each do |item|
17
+ # 1. 从 argv 提取值(优先级最高)
18
+ raw_value = extract_from_argv(argv, item)
19
+
20
+ # 2. 如果 argv 没有,尝试从环境变量读取
21
+ if raw_value.nil?
22
+ raw_value = item.fetch_env_value
23
+ end
24
+
25
+ # 3. 存储值(可能是 nil)
26
+ values[item.key] = raw_value unless raw_value.nil?
27
+
28
+ # 4. 处理别名(别名指向同一个值)
29
+ item.aliases.each do |alias_name|
30
+ values[alias_name] = raw_value unless raw_value.nil?
31
+ end
32
+ end
33
+
34
+ values
35
+ end
36
+
37
+ private
38
+
39
+ # 从 argv 提取参数值
40
+ # @param argv [CLAide::ARGV] CLAide 参数对象
41
+ # @param item [OptionItem] 参数定义
42
+ # @return [Object, nil] 提取的值
43
+ def self.extract_from_argv(argv, item)
44
+ if item.boolean?
45
+ # Boolean 类型:使用 flag?
46
+ argv.flag?(item.key.to_s, nil)
47
+ else
48
+ # 其他类型:使用 option
49
+ argv.option(item.key.to_s, nil)
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,60 @@
1
+ require 'pindo/options/core/option_item'
2
+ require 'pindo/options/groups/option_group'
3
+
4
+ module Pindo
5
+ module Options
6
+ # 通用构建参数组
7
+ # 定义跨平台(iOS/Android)的构建参数
8
+ module BuildOptions
9
+ extend OptionGroup
10
+
11
+ def self.all_options
12
+
13
+ @all_options ||= {
14
+
15
+ bundleid: OptionItem.new(
16
+ key: :bundleid,
17
+ description: '指定打包的 Bundle ID',
18
+ type: String,
19
+ env_name: 'PINDO_BUNDLE_ID',
20
+ aliases: [:bundle_id, :package_name, :bundle_name],
21
+ optional: true,
22
+ verify_block: proc do |value|
23
+ # 支持 iOS 格式 (com.example.app) 和 Android 格式 (com.example.app)
24
+ # iOS 可以包含大写字母、连字符和通配符(*)
25
+ unless value =~ /^[a-zA-Z0-9\-\.\*]+$/
26
+ raise "Bundle ID/Package Name 格式错误: #{value},应该类似 com.example.app 或 com.example.*"
27
+ end
28
+ end,
29
+ example: 'pindo ios autobuild --bundleid=com.example.app'
30
+ ),
31
+
32
+ build_type: OptionItem.new(
33
+ key: :build_type,
34
+ description: '指定构建类型(dev/adhoc/release)',
35
+ type: String,
36
+ env_name: 'PINDO_BUILD_TYPE',
37
+ default_value: 'dev',
38
+ optional: true,
39
+ verify_block: proc do |value|
40
+ valid_types = ['dev', 'adhoc', 'release']
41
+ unless valid_types.include?(value.to_s.downcase)
42
+ raise "构建类型错误: #{value},必须是 dev、adhoc 或 release 之一"
43
+ end
44
+ end,
45
+ example: 'pindo ios autobuild --build_type=release'
46
+ ),
47
+
48
+ scheme: OptionItem.new(
49
+ key: :scheme,
50
+ description: '指定构建 Scheme',
51
+ type: String,
52
+ env_name: 'PINDO_SCHEME',
53
+ optional: true,
54
+ example: 'pindo ios autobuild --scheme=MyAppScheme'
55
+ )
56
+ }
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,70 @@
1
+ require 'pindo/options/core/option_item'
2
+ require 'pindo/options/groups/option_group'
3
+
4
+ module Pindo
5
+ module Options
6
+ # JPS 平台参数组
7
+ # 定义 JPS 测试平台特有的参数
8
+ module JPSOptions
9
+ extend OptionGroup
10
+
11
+ def self.all_options
12
+ @all_options ||= {
13
+ proj: OptionItem.new(
14
+ key: :proj,
15
+ description: '指定上传到测试平台的项目名称',
16
+ type: String,
17
+ env_name: 'PINDO_PROJECT_NAME',
18
+ optional: true,
19
+ example: 'pindo ios autobuild --proj="My App"'
20
+ ),
21
+
22
+ upload: OptionItem.new(
23
+ key: :upload,
24
+ description: '编译后上传到测试平台(上传成功后自动发送给自己)',
25
+ type: OptionItem::Boolean,
26
+ env_name: 'PINDO_UPLOAD',
27
+ optional: true,
28
+ example: 'pindo ios autobuild --upload'
29
+ ),
30
+
31
+ send: OptionItem.new(
32
+ key: :send,
33
+ description: '发送通知到测试群组(同时也会发送给自己)',
34
+ type: OptionItem::Boolean,
35
+ env_name: 'PINDO_SEND',
36
+ optional: true,
37
+ example: 'pindo ios autobuild --send'
38
+ ),
39
+ desc: OptionItem.new(
40
+ key: :desc,
41
+ description: '指定上传的备注信息',
42
+ type: String,
43
+ env_name: 'PINDO_UPLOAD_DESC',
44
+ aliases: [:description],
45
+ optional: true,
46
+ example: 'pindo jps upload --desc="版本说明"'
47
+ ),
48
+
49
+ resign: OptionItem.new(
50
+ key: :resign,
51
+ description: '上传后是否重签名',
52
+ type: OptionItem::Boolean,
53
+ env_name: 'PINDO_RESIGN',
54
+ optional: true,
55
+ example: 'pindo jps upload --resign'
56
+ ),
57
+
58
+ certid: OptionItem.new(
59
+ key: :certid,
60
+ description: '设置重签名的Bundle ID',
61
+ type: String,
62
+ env_name: 'PINDO_CERT_ID',
63
+ optional: true,
64
+ example: 'pindo jps resign --certid=com.test.bundleid'
65
+ )
66
+ }
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,73 @@
1
+ require 'pindo/options/core/option_item'
2
+
3
+ module Pindo
4
+ module Options
5
+ # 参数组工具模块
6
+ # 提供参数组的定义、筛选和合并功能
7
+ # 合并了原 OptionGroupBase 和 OptionRegistry 的功能
8
+ module OptionGroup
9
+
10
+ # ==================== 实例方法(供参数组使用) ====================
11
+
12
+ # 选择指定的参数
13
+ # @param keys [Array<Symbol>] 要选择的参数键名
14
+ # @return [Array<OptionItem>] 选中的参数列表
15
+ def select(*keys)
16
+ keys = keys.flatten.map(&:to_sym)
17
+ all_options_hash = all_options
18
+
19
+ selected = keys.map do |key|
20
+ option = all_options_hash[key]
21
+ if option.nil?
22
+ raise ArgumentError, "参数组 #{self.name} 中不存在参数: #{key}"
23
+ end
24
+ option
25
+ end
26
+
27
+ selected
28
+ end
29
+
30
+ # 排除指定的参数,返回剩余参数
31
+ # @param keys [Array<Symbol>] 要排除的参数键名
32
+ # @return [Array<OptionItem>] 剩余的参数列表
33
+ def except(*keys)
34
+ keys = keys.flatten.map(&:to_sym)
35
+ all_options_hash = all_options
36
+
37
+ all_options_hash.reject { |k, v| keys.include?(k) }.values
38
+ end
39
+
40
+ # 获取所有参数(返回数组)
41
+ # @return [Array<OptionItem>] 所有参数列表
42
+ def all
43
+ all_options.values
44
+ end
45
+
46
+ # 子类必须实现此方法
47
+ # @return [Hash{Symbol => OptionItem}] 所有参数的 Hash
48
+ def all_options
49
+ raise NotImplementedError, "子类必须实现 all_options 方法"
50
+ end
51
+
52
+ # ==================== 类方法(合并参数组) ====================
53
+
54
+ # 合并多个参数组
55
+ # @param option_groups [Array<Array<OptionItem>>] 参数组列表
56
+ # @return [Array<OptionItem>] 合并后的参数列表(去重)
57
+ def self.merge(*option_groups)
58
+ merged_map = {}
59
+
60
+ option_groups.flatten.compact.each do |item|
61
+ unless item.is_a?(OptionItem)
62
+ raise ArgumentError, "Expected OptionItem, got #{item.class}"
63
+ end
64
+
65
+ # 如果键已存在,后面的覆盖前面的
66
+ merged_map[item.key] = item
67
+ end
68
+
69
+ merged_map.values
70
+ end
71
+ end
72
+ end
73
+ end