fastlane-plugin-pgyer 0.3.2 → 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 -18
- 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|
|
|
@@ -181,7 +182,7 @@ module Fastlane
|
|
|
181
182
|
end),
|
|
182
183
|
FastlaneCore::ConfigItem.new(key: :hap,
|
|
183
184
|
env_name: "PGYER_HAP",
|
|
184
|
-
description: "Path to your HAP file
|
|
185
|
+
description: "Path to your HAP file",
|
|
185
186
|
default_value: Actions.lane_context[:HVIGOR_HAP_OUTPUT_PATH],
|
|
186
187
|
optional: true,
|
|
187
188
|
verify_block: proc do |value|
|
|
@@ -248,6 +249,12 @@ module Fastlane
|
|
|
248
249
|
description: "Need to update the specified channel of the download short link, can specify only one channel, string type, such as: ABCD",
|
|
249
250
|
optional: true,
|
|
250
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),
|
|
251
258
|
]
|
|
252
259
|
end
|
|
253
260
|
|
|
@@ -261,6 +268,193 @@ module Fastlane
|
|
|
261
268
|
|
|
262
269
|
private
|
|
263
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
|
+
|
|
264
458
|
def self.get_type(params)
|
|
265
459
|
type = params[:ipa].nil? ? "android" : "ios"
|
|
266
460
|
|
|
@@ -271,10 +465,24 @@ module Fastlane
|
|
|
271
465
|
type
|
|
272
466
|
end
|
|
273
467
|
|
|
274
|
-
def self.checkPublishStatus(client, api_host, api_key, buildKey)
|
|
275
|
-
|
|
468
|
+
def self.checkPublishStatus(client, api_host, api_key, buildKey, doh_info = nil)
|
|
469
|
+
# URL 保持使用域名(用于显示)
|
|
470
|
+
url = "#{api_host}/buildInfo"
|
|
276
471
|
UI.message "checkPublishStatus url: #{url}"
|
|
277
|
-
|
|
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
|
|
278
486
|
info = response.body
|
|
279
487
|
code = info["code"]
|
|
280
488
|
if code == 0
|
|
@@ -288,7 +496,7 @@ module Fastlane
|
|
|
288
496
|
return info["data"]
|
|
289
497
|
elsif code == 1246 || code == 1247
|
|
290
498
|
sleep 3
|
|
291
|
-
self.checkPublishStatus(client, api_host, api_key, buildKey)
|
|
499
|
+
self.checkPublishStatus(client, api_host, api_key, buildKey, doh_info)
|
|
292
500
|
else
|
|
293
501
|
UI.user_error!("PGYER Plugin Published Error: #{info} buildKey: #{buildKey}")
|
|
294
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: []
|