fastlane-plugin-pgyer 0.3.1 → 0.3.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.
- checksums.yaml +4 -4
- data/lib/fastlane/plugin/pgyer/actions/pgyer_action.rb +226 -29
- data/lib/fastlane/plugin/pgyer/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 76598ee4c500e69dc2628a463315f2b45ece7db0bebca38e26b65a9d8f3413cc
|
|
4
|
+
data.tar.gz: b2df8a60da19d648c964dbd92da17a50edd471a5343867afb6be2c56553dd721
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 60302c4a4e3c101df47ed239c8c2a012fe161a3535d70ceb4f9047b94bd1e7f312eb8eb8e5b5f0fe39deae53b43299d312d8dc0c9d87f883911fc1e2379d94e3
|
|
7
|
+
data.tar.gz: 27415b535fa5f9110ecf86f145aa8499c8290c2abf3bf215175e1a31da517e28f384843e7caaafce192d2fc448d0f1034a6ef6207960b447b07f59890b977883
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
require "faraday"
|
|
2
2
|
require "faraday_middleware"
|
|
3
|
+
require "timeout"
|
|
3
4
|
|
|
4
5
|
module Fastlane
|
|
5
6
|
module Actions
|
|
@@ -74,18 +75,9 @@ module Fastlane
|
|
|
74
75
|
},
|
|
75
76
|
}
|
|
76
77
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
pgyer_client =
|
|
80
|
-
c.request :multipart
|
|
81
|
-
c.request :url_encoded
|
|
82
|
-
c.response :json, content_type: /\bjson$/
|
|
83
|
-
c.adapter :net_http
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
response = pgyer_client.post "#{api_host}/getCOSToken", request_params
|
|
87
|
-
|
|
88
|
-
info = response.body
|
|
78
|
+
# 选择可用的 API 域名
|
|
79
|
+
use_doh = params[:doh] == true
|
|
80
|
+
api_host, pgyer_client, info = self.select_available_api_host(conn_options, request_params, use_doh)
|
|
89
81
|
|
|
90
82
|
if info["code"] != 0
|
|
91
83
|
UI.user_error!("Get token is failed, info: #{info}")
|
|
@@ -121,7 +113,16 @@ module Fastlane
|
|
|
121
113
|
UI.user_error!("PGYER Plugin Upload Error: #{response.body}")
|
|
122
114
|
end
|
|
123
115
|
|
|
124
|
-
|
|
116
|
+
# 如果使用 DoH,需要传递 DoH 相关信息
|
|
117
|
+
doh_info = nil
|
|
118
|
+
if use_doh && api_host.include?("www.pgyer.com")
|
|
119
|
+
domain = "www.pgyer.com"
|
|
120
|
+
ip_address = resolve_domain_via_doh(domain)
|
|
121
|
+
if ip_address
|
|
122
|
+
doh_info = { domain: domain, ip_address: ip_address }
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
answer = self.checkPublishStatus(pgyer_client, api_host, api_key, key, doh_info)
|
|
125
126
|
|
|
126
127
|
if params[:save_uploaded_info_json]
|
|
127
128
|
File.open("pgyer-fastlane-uploaded-app-info.json", "w") do |f|
|
|
@@ -167,17 +168,6 @@ module Fastlane
|
|
|
167
168
|
conflict_block: proc do |value|
|
|
168
169
|
UI.user_error!("You can't use 'apk' and '#{value.key}' options in one run")
|
|
169
170
|
end),
|
|
170
|
-
FastlaneCore::ConfigItem.new(key: :hap,
|
|
171
|
-
env_name: "PGYER_HAP",
|
|
172
|
-
description: "Path to your HAP file",
|
|
173
|
-
optional: true,
|
|
174
|
-
verify_block: proc do |value|
|
|
175
|
-
UI.user_error!("Couldn't find hap file at path '#{value}'") unless File.exist?(value)
|
|
176
|
-
end,
|
|
177
|
-
conflicting_options: [:ipa, :apk],
|
|
178
|
-
conflict_block: proc do |value|
|
|
179
|
-
UI.user_error!("You can't use 'hap' and '#{value.key}' options in one run")
|
|
180
|
-
end),
|
|
181
171
|
FastlaneCore::ConfigItem.new(key: :ipa,
|
|
182
172
|
env_name: "PGYER_IPA",
|
|
183
173
|
description: "Path to your IPA file. Optional if you use the _gym_ or _xcodebuild_ action. For Mac zip the .app. For Android provide path to .apk file",
|
|
@@ -192,7 +182,7 @@ module Fastlane
|
|
|
192
182
|
end),
|
|
193
183
|
FastlaneCore::ConfigItem.new(key: :hap,
|
|
194
184
|
env_name: "PGYER_HAP",
|
|
195
|
-
description: "Path to your HAP file
|
|
185
|
+
description: "Path to your HAP file",
|
|
196
186
|
default_value: Actions.lane_context[:HVIGOR_HAP_OUTPUT_PATH],
|
|
197
187
|
optional: true,
|
|
198
188
|
verify_block: proc do |value|
|
|
@@ -259,6 +249,12 @@ module Fastlane
|
|
|
259
249
|
description: "Need to update the specified channel of the download short link, can specify only one channel, string type, such as: ABCD",
|
|
260
250
|
optional: true,
|
|
261
251
|
type: String),
|
|
252
|
+
FastlaneCore::ConfigItem.new(key: :doh,
|
|
253
|
+
env_name: "PGYER_DOH",
|
|
254
|
+
description: "Use DNS over HTTPS (DoH) to resolve domain names, bypassing local DNS. Experimental feature",
|
|
255
|
+
optional: true,
|
|
256
|
+
default_value: false,
|
|
257
|
+
type: Boolean),
|
|
262
258
|
]
|
|
263
259
|
end
|
|
264
260
|
|
|
@@ -272,6 +268,193 @@ module Fastlane
|
|
|
272
268
|
|
|
273
269
|
private
|
|
274
270
|
|
|
271
|
+
def self.select_available_api_host(conn_options, request_params, use_doh = false)
|
|
272
|
+
# 如果启用 DoH,直接使用 DoH 解析 www.pgyer.com,跳过三个域名测试
|
|
273
|
+
if use_doh
|
|
274
|
+
return select_api_host_via_doh(conn_options, request_params)
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
# 尝试多个域名,防止 DNS 劫持
|
|
278
|
+
api_hosts = [
|
|
279
|
+
"https://www.pgyer.com/apiv2/app",
|
|
280
|
+
"https://www.xcxwo.com/apiv2/app",
|
|
281
|
+
"https://www.pgyerapp.com/apiv2/app",
|
|
282
|
+
]
|
|
283
|
+
|
|
284
|
+
api_host = nil
|
|
285
|
+
pgyer_client = nil
|
|
286
|
+
info = nil
|
|
287
|
+
|
|
288
|
+
api_hosts.each_with_index do |host, index|
|
|
289
|
+
UI.message "尝试使用域名 #{index + 1}/#{api_hosts.length}: #{host}"
|
|
290
|
+
|
|
291
|
+
begin
|
|
292
|
+
# 为域名检测设置 5 秒超时
|
|
293
|
+
test_conn_options = {
|
|
294
|
+
request: {
|
|
295
|
+
timeout: 5,
|
|
296
|
+
open_timeout: 5,
|
|
297
|
+
},
|
|
298
|
+
}
|
|
299
|
+
test_client = create_faraday_client(test_conn_options, nil)
|
|
300
|
+
|
|
301
|
+
# 使用超时控制,5 秒后如果还没响应就放弃
|
|
302
|
+
test_response = nil
|
|
303
|
+
test_info = nil
|
|
304
|
+
|
|
305
|
+
begin
|
|
306
|
+
Timeout.timeout(5) do
|
|
307
|
+
test_response = test_client.post "#{host}/getCOSToken", request_params
|
|
308
|
+
test_info = test_response.body
|
|
309
|
+
end
|
|
310
|
+
rescue Timeout::Error
|
|
311
|
+
UI.message "域名 #{host} 请求超时(5秒),切换到下一个域名"
|
|
312
|
+
next
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
# 检查响应是否有效:如果返回了有效的 JSON 且包含 code 字段,说明域名解析正常
|
|
316
|
+
if test_info && test_info.is_a?(Hash) && test_info.key?("code")
|
|
317
|
+
if test_info["code"] == 0
|
|
318
|
+
# API 调用成功,使用该域名
|
|
319
|
+
# 使用原始的超时设置重新创建客户端(用于后续上传)
|
|
320
|
+
api_host = host
|
|
321
|
+
pgyer_client = create_faraday_client(conn_options, nil)
|
|
322
|
+
info = test_info
|
|
323
|
+
UI.success "成功使用域名: #{host}"
|
|
324
|
+
break
|
|
325
|
+
else
|
|
326
|
+
# API 返回了业务错误,但域名解析正常
|
|
327
|
+
# 保存第一个可用的域名作为备选,继续尝试其他域名看是否有返回 code == 0 的
|
|
328
|
+
if api_host.nil?
|
|
329
|
+
api_host = host
|
|
330
|
+
# 使用原始的超时设置重新创建客户端
|
|
331
|
+
pgyer_client = create_faraday_client(conn_options, nil)
|
|
332
|
+
info = test_info
|
|
333
|
+
UI.message "域名 #{host} 解析正常,但 API 返回错误,保存为备选: #{test_info}"
|
|
334
|
+
else
|
|
335
|
+
UI.message "域名 #{host} 可用,但 API 返回错误: #{test_info}"
|
|
336
|
+
end
|
|
337
|
+
end
|
|
338
|
+
else
|
|
339
|
+
# 响应格式不正确,可能是 DNS 劫持
|
|
340
|
+
UI.message "域名 #{host} 返回的响应格式不正确,可能遭遇 DNS 劫持"
|
|
341
|
+
end
|
|
342
|
+
rescue => e
|
|
343
|
+
UI.message "域名 #{host} 测试失败(可能是 DNS 劫持或超时): #{e.message}"
|
|
344
|
+
next
|
|
345
|
+
end
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
if api_host.nil? || pgyer_client.nil? || info.nil?
|
|
349
|
+
UI.user_error!("所有域名都无法使用,可能都遭遇了 DNS 劫持。尝试的域名: #{api_hosts.join(', ')}")
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
return api_host, pgyer_client, info
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
# DoH 模式:使用 DoH 解析 www.pgyer.com(实验性功能)
|
|
356
|
+
def self.select_api_host_via_doh(conn_options, request_params)
|
|
357
|
+
UI.message "启用 DoH 模式,使用 DoH 解析 www.pgyer.com"
|
|
358
|
+
|
|
359
|
+
host = "https://www.pgyer.com/apiv2/app"
|
|
360
|
+
domain = "www.pgyer.com"
|
|
361
|
+
|
|
362
|
+
# 通过 DoH 解析域名
|
|
363
|
+
ip_address = resolve_domain_via_doh(domain)
|
|
364
|
+
|
|
365
|
+
if ip_address.nil?
|
|
366
|
+
UI.user_error!("DoH 解析失败,无法获取 www.pgyer.com 的 IP 地址")
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
UI.message "DoH 解析成功: #{domain} -> #{ip_address}"
|
|
370
|
+
|
|
371
|
+
# 使用 IP 地址替换域名,但保留 Host header
|
|
372
|
+
actual_url = host.gsub(domain, ip_address)
|
|
373
|
+
host_header = domain
|
|
374
|
+
|
|
375
|
+
begin
|
|
376
|
+
test_client = create_faraday_client(conn_options, host_header)
|
|
377
|
+
|
|
378
|
+
# 设置 Host header
|
|
379
|
+
request_headers = { "Host" => host_header }
|
|
380
|
+
|
|
381
|
+
test_response = test_client.post "#{actual_url}/getCOSToken", request_params, request_headers
|
|
382
|
+
test_info = test_response.body
|
|
383
|
+
|
|
384
|
+
if test_info && test_info.is_a?(Hash) && test_info.key?("code")
|
|
385
|
+
if test_info["code"] == 0
|
|
386
|
+
UI.success "DoH 模式:成功使用域名 #{host}"
|
|
387
|
+
return host, test_client, test_info
|
|
388
|
+
else
|
|
389
|
+
UI.user_error!("DoH 模式:API 返回错误: #{test_info}")
|
|
390
|
+
end
|
|
391
|
+
else
|
|
392
|
+
UI.user_error!("DoH 模式:返回的响应格式不正确: #{test_info}")
|
|
393
|
+
end
|
|
394
|
+
rescue => e
|
|
395
|
+
UI.user_error!("DoH 模式:请求失败: #{e.message}")
|
|
396
|
+
end
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
# DoH 相关方法(实验性功能)
|
|
400
|
+
def self.resolve_domain_via_doh(domain)
|
|
401
|
+
# 使用阿里云公共 DoH 服务
|
|
402
|
+
doh_url = "https://dns.alidns.com/resolve"
|
|
403
|
+
|
|
404
|
+
begin
|
|
405
|
+
doh_client = Faraday.new do |c|
|
|
406
|
+
c.request :url_encoded
|
|
407
|
+
c.response :json
|
|
408
|
+
c.adapter :net_http
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
response = doh_client.get(doh_url, { name: domain, type: "A" })
|
|
412
|
+
result = response.body
|
|
413
|
+
|
|
414
|
+
if result && result.is_a?(Hash) && result["Answer"]
|
|
415
|
+
# 获取第一个 A 记录
|
|
416
|
+
a_record = result["Answer"].find { |r| r["type"] == 1 }
|
|
417
|
+
if a_record && a_record["data"]
|
|
418
|
+
return a_record["data"]
|
|
419
|
+
end
|
|
420
|
+
end
|
|
421
|
+
rescue => e
|
|
422
|
+
UI.message "DoH 解析出错: #{e.message}"
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
return nil
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
def self.extract_domain_from_url(url)
|
|
429
|
+
# 从 URL 中提取域名
|
|
430
|
+
# 例如: https://www.pgyer.com/apiv2/app -> www.pgyer.com
|
|
431
|
+
uri = URI.parse(url)
|
|
432
|
+
return uri.host
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
def self.create_faraday_client(conn_options, host_header = nil)
|
|
436
|
+
# 创建基础的 Faraday 客户端
|
|
437
|
+
# Host header 将在请求时通过 headers 参数设置
|
|
438
|
+
# DoH 模式下禁用 SSL 证书验证(因为使用 IP 地址,证书绑定域名)
|
|
439
|
+
final_options = conn_options.dup
|
|
440
|
+
|
|
441
|
+
Faraday.new(nil, final_options) do |c|
|
|
442
|
+
c.request :multipart
|
|
443
|
+
c.request :url_encoded
|
|
444
|
+
c.response :json, content_type: /\bjson$/
|
|
445
|
+
c.adapter :net_http do |http|
|
|
446
|
+
if host_header
|
|
447
|
+
# DoH 模式:使用 IP 地址,禁用 SSL 证书验证
|
|
448
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
|
449
|
+
UI.message "DoH 模式:已禁用 SSL 证书验证(实验性功能)"
|
|
450
|
+
else
|
|
451
|
+
# 普通模式:使用默认 SSL 验证
|
|
452
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
|
453
|
+
end
|
|
454
|
+
end
|
|
455
|
+
end
|
|
456
|
+
end
|
|
457
|
+
|
|
275
458
|
def self.get_type(params)
|
|
276
459
|
type = params[:ipa].nil? ? "android" : "ios"
|
|
277
460
|
|
|
@@ -282,10 +465,24 @@ module Fastlane
|
|
|
282
465
|
type
|
|
283
466
|
end
|
|
284
467
|
|
|
285
|
-
def self.checkPublishStatus(client, api_host, api_key, buildKey)
|
|
286
|
-
|
|
468
|
+
def self.checkPublishStatus(client, api_host, api_key, buildKey, doh_info = nil)
|
|
469
|
+
# URL 保持使用域名(用于显示)
|
|
470
|
+
url = "#{api_host}/buildInfo"
|
|
287
471
|
UI.message "checkPublishStatus url: #{url}"
|
|
288
|
-
|
|
472
|
+
|
|
473
|
+
# 如果使用 DoH,实际请求时使用 IP 地址,但设置 Host header
|
|
474
|
+
actual_url = api_host
|
|
475
|
+
request_headers = {}
|
|
476
|
+
|
|
477
|
+
if doh_info && doh_info[:ip_address]
|
|
478
|
+
# 实际连接使用 IP 地址
|
|
479
|
+
actual_url = api_host.gsub(doh_info[:domain], doh_info[:ip_address])
|
|
480
|
+
# 设置 Host header 为原始域名
|
|
481
|
+
request_headers["Host"] = doh_info[:domain]
|
|
482
|
+
UI.message "DoH 模式:实际连接使用 IP 地址 #{doh_info[:ip_address]},Host header: #{doh_info[:domain]}"
|
|
483
|
+
end
|
|
484
|
+
|
|
485
|
+
response = client.post "#{actual_url}/buildInfo", { :_api_key => api_key, :buildKey => buildKey }, request_headers
|
|
289
486
|
info = response.body
|
|
290
487
|
code = info["code"]
|
|
291
488
|
if code == 0
|
|
@@ -299,7 +496,7 @@ module Fastlane
|
|
|
299
496
|
return info["data"]
|
|
300
497
|
elsif code == 1246 || code == 1247
|
|
301
498
|
sleep 3
|
|
302
|
-
self.checkPublishStatus(client, api_host, api_key, buildKey)
|
|
499
|
+
self.checkPublishStatus(client, api_host, api_key, buildKey, doh_info)
|
|
303
500
|
else
|
|
304
501
|
UI.user_error!("PGYER Plugin Published Error: #{info} buildKey: #{buildKey}")
|
|
305
502
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: fastlane-plugin-pgyer
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- rexshi
|
|
@@ -178,7 +178,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
178
178
|
- !ruby/object:Gem::Version
|
|
179
179
|
version: '0'
|
|
180
180
|
requirements: []
|
|
181
|
-
rubygems_version: 3.
|
|
181
|
+
rubygems_version: 3.6.9
|
|
182
182
|
specification_version: 4
|
|
183
183
|
summary: distribute app to pgyer beta testing service
|
|
184
184
|
test_files: []
|