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