fastlane-plugin-pgyersws 0.3.5
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 +7 -0
- data/LICENSE +21 -0
- data/README.md +170 -0
- data/lib/fastlane/plugin/pgyer/actions/pgyer_action.rb +507 -0
- data/lib/fastlane/plugin/pgyer/helper/pgyer_helper.rb +16 -0
- data/lib/fastlane/plugin/pgyer/sws.rb +1 -0
- data/lib/fastlane/plugin/pgyer/version.rb +5 -0
- data/lib/fastlane/plugin/pgyer.rb +16 -0
- data/lib/fastlane/plugin/pgyersws.rb +11 -0
- metadata +226 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: edc1b6a7f6942167bf1cdce64cccb9fe0b84ba85ff10e2b4a2ed58477bd4f554
|
|
4
|
+
data.tar.gz: 347172bc15c543ce38098f6c4cfdcab5b560131e720bef85aef8f7bea7eed410
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 48774d857a74bfe5873b809337588397925b2c98451b788071ad69dff18d6144c4b47a018b4684778c607221cefd9bae8401959348c8c9f435fb9bf2ce55ddcb
|
|
7
|
+
data.tar.gz: 189d5b3ab41e26b71632573013a4322885138ae81b0710f301dae0f0af39c703be5162553f0d02ecec77fc5715e1ee3a608c0c57cb63395a2373966443b0ac0c
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2017 rexshi <rexshi@pgyer.com>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# pgyer plugin
|
|
2
|
+
|
|
3
|
+
This fork is published as `fastlane-plugin-pgyersws` to preserve compatibility with `fastlane 2.238.0` while keeping the `pgyer(...)` action name unchanged.
|
|
4
|
+
|
|
5
|
+
[](https://rubygems.org/gems/fastlane-plugin-pgyersws)
|
|
6
|
+
## Important Notifications
|
|
7
|
+
|
|
8
|
+
- Since pgyer has migrated the API domain name, Please update the plugin to the latest version (>= 0.2.6) to avoid uploading failures.
|
|
9
|
+
|
|
10
|
+
## Getting Started
|
|
11
|
+
|
|
12
|
+
This project is a [fastlane](https://github.com/fastlane/fastlane) plugin. To get started with `fastlane-plugin-pgyersws`, add it to your project by running:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
fastlane add_plugin pgyersws
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## About pgyer
|
|
19
|
+
|
|
20
|
+
This pluginin allow you distribute app automatically to [pgyer beta testing service](https://www.pgyer.com) in fastlane workflow.
|
|
21
|
+
|
|
22
|
+
## How to update pgyer plugin to the latest version
|
|
23
|
+
|
|
24
|
+
**Due to the adjustment of the API interface, please ensure that the plugin version is at least `0.2.4`**
|
|
25
|
+
|
|
26
|
+
Plan A: update all plguins (Recommended)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
fastlane update_plugins
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Plan B: update pgyer plugin only
|
|
34
|
+
|
|
35
|
+
modify `fastlane/Pluginfile`, update the following line:
|
|
36
|
+
|
|
37
|
+
```ruby
|
|
38
|
+
gem 'fastlane-plugin-pgyersws', ">= 0.3.5"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
and run `bundle install` at the root of your fastlane project to update gemfile.lock
|
|
42
|
+
|
|
43
|
+
## Plugin avaliable options
|
|
44
|
+
|
|
45
|
+
please visit [https://github.com/shishirui/fastlane-plugin-pgyer/blob/master/lib/fastlane/plugin/pgyer/actions/pgyer_action.rb#L135-L205](https://github.com/shishirui/fastlane-plugin-pgyer/blob/master/lib/fastlane/plugin/pgyer/actions/pgyer_action.rb#L135-L205) to know the options.
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
## Example
|
|
49
|
+
|
|
50
|
+
Check out the [example `Fastfile`](fastlane/Fastfile) to see how to use this plugin. Try it by cloning the repo, running `fastlane install_plugins` and `bundle exec fastlane test`.
|
|
51
|
+
|
|
52
|
+
Just specify the `api_key` associated with your pgyer account.
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
lane :beta do
|
|
56
|
+
gym
|
|
57
|
+
pgyer(api_key: "7f15xxxxxxxxxxxxxxxxxx141")
|
|
58
|
+
end
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
You can also set a password to protect the App from being downloaded publicly:
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
lane :beta do
|
|
65
|
+
gym
|
|
66
|
+
pgyer(api_key: "7f15xxxxxxxxxxxxxxxxxx141", password: "123456", install_type: "2")
|
|
67
|
+
end
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Set a version update description for App:
|
|
71
|
+
acd88a1a52f0818dc7923150c4d86f08
|
|
72
|
+
```
|
|
73
|
+
lane :beta do
|
|
74
|
+
gym
|
|
75
|
+
pgyer(api_key: "7f15xxxxxxxxxxxxxxxxxx141", update_description: "update by fastlane")
|
|
76
|
+
end
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
If the upload is successful, you will get information about the app after it is uploaded, which is returned from the API interface app/buildinfo . You can pass it to other plugins, or export it to the terminal for use by other scripts:
|
|
81
|
+
|
|
82
|
+
```ruby
|
|
83
|
+
lane :beta do
|
|
84
|
+
gym
|
|
85
|
+
answer = pgyer(api_key: "xxxxxx")
|
|
86
|
+
puts answer
|
|
87
|
+
# terminal outputs like this if uploaded successfully
|
|
88
|
+
# {"buildKey"=>"xxxx", "buildType"=>"2", "buildIsFirst"=>"0", "buildIsLastest"=>"1", "buildFileKey"=>"xxx.apk", "buildFileName"=>"", "buildFileSize"=>"111111", "buildName"=>"testApk", "buildVersion"=>"0.11.0", "buildVersionNo"=>"13", "buildBuildVersion"=>"10", "buildIdentifier"=>"com.pgyer.testapk", "buildIcon"=>"xxxx", "buildDescription"=>"", "buildUpdateDescription"=>"", "buildScreenshots"=>"", "buildShortcutUrl"=>"xxxxxxx", "buildCreated"=>"2023-04-04 11:33:24", "buildUpdated"=>"2023-04-04 11:33:24", "buildQRCodeURL"=>"https://www.pgyer.com/app/qrcodeHistory/xxxxxx", "fastlaneAddedWholeVisitUrl"=>"https://www.pgyer.com/xxxxxx"}
|
|
89
|
+
puts "url = #{answer["fastlaneAddedWholeVisitUrl"]}"
|
|
90
|
+
|
|
91
|
+
# terminal outputs like this if uploaded successfully
|
|
92
|
+
# url = https://www.pgyer.com/xxxxxx
|
|
93
|
+
|
|
94
|
+
# More information please visit https://www.pgyer.com/doc/view/api#fastUploadApp to check API "https://www.pgyer.com/apiv2/app/buildInfo"
|
|
95
|
+
|
|
96
|
+
end
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
HAP file upload
|
|
101
|
+
|
|
102
|
+
pgyer supports hap file to upload, use params hap to specify the absolute file path.
|
|
103
|
+
|
|
104
|
+
```ruby
|
|
105
|
+
lane :beta do
|
|
106
|
+
gym
|
|
107
|
+
pgyer(api_key: "7f15xxxxxxxxxxxxxxxxxx141", hap: "xxxx")
|
|
108
|
+
end
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
or in bash
|
|
112
|
+
```bash
|
|
113
|
+
fastlane run pgyer api_key:7f15xxxxxxxxxxxxxxxxxx141 hap:xxx.hap
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
And more params
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
password: Set password to protect app.
|
|
123
|
+
|
|
124
|
+
update_description: Set update description for app.
|
|
125
|
+
|
|
126
|
+
install_type: Set install type for app (1=public, 2=password, 3=invite), Please set as a string.
|
|
127
|
+
|
|
128
|
+
install_date: Set install type for app (1=Set valid time, 2=Long-term effective, other=Do not modify the last setting), Please set as a string.
|
|
129
|
+
|
|
130
|
+
install_start_date: The value is a string of characters, for example, 2018-01-01.
|
|
131
|
+
|
|
132
|
+
install_end_date: The value is a string of characters, such as 2018-12-31.
|
|
133
|
+
|
|
134
|
+
channel: Need to update the specified channel of the download short link, can specify only one channel, string type, such as: ABCD. Specifies channel uploads. If you do not have one, do not use this parameter.
|
|
135
|
+
|
|
136
|
+
user_download_file_name: The name of the file downloaded by the user, the string type, such as: test.apk.
|
|
137
|
+
|
|
138
|
+
save_uploaded_info_json: (true or false, default to false) Whether to save the information returned by the API interface to a json file.
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
## Run tests for this plugin
|
|
144
|
+
|
|
145
|
+
To run both the tests, and code style validation, run
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
rake
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
To automatically fix many of the styling issues, use
|
|
152
|
+
```
|
|
153
|
+
rubocop -a
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Issues and Feedback
|
|
157
|
+
|
|
158
|
+
For any other issues and feedback about this plugin, please submit it to this repository.
|
|
159
|
+
|
|
160
|
+
## Troubleshooting
|
|
161
|
+
|
|
162
|
+
If you have trouble using plugins, check out the [Plugins Troubleshooting](https://docs.fastlane.tools/plugins/plugins-troubleshooting/) guide.
|
|
163
|
+
|
|
164
|
+
## Using `fastlane` Plugins
|
|
165
|
+
|
|
166
|
+
For more information about how the `fastlane` plugin system works, check out the [Plugins documentation](https://docs.fastlane.tools/plugins/create-plugin/).
|
|
167
|
+
|
|
168
|
+
## About `fastlane`
|
|
169
|
+
|
|
170
|
+
`fastlane` is the easiest way to automate beta deployments and releases for your iOS and Android apps. To learn more, check out [fastlane.tools](https://fastlane.tools).
|
|
@@ -0,0 +1,507 @@
|
|
|
1
|
+
require "faraday"
|
|
2
|
+
require "faraday/multipart"
|
|
3
|
+
require "faraday/response/json"
|
|
4
|
+
require "timeout"
|
|
5
|
+
|
|
6
|
+
module Fastlane
|
|
7
|
+
module Actions
|
|
8
|
+
class PgyerAction < Action
|
|
9
|
+
def self.run(params)
|
|
10
|
+
UI.message("The pgyer plugin is working.")
|
|
11
|
+
|
|
12
|
+
api_key = params[:api_key]
|
|
13
|
+
|
|
14
|
+
build_file = [
|
|
15
|
+
params[:ipa],
|
|
16
|
+
params[:apk],
|
|
17
|
+
params[:hap],
|
|
18
|
+
].detect { |e| !e.to_s.empty? }
|
|
19
|
+
|
|
20
|
+
if build_file.nil?
|
|
21
|
+
UI.user_error!("You have to provide a build file")
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
type = get_type(params)
|
|
25
|
+
|
|
26
|
+
UI.message "build_file: #{build_file}, type: #{type}"
|
|
27
|
+
|
|
28
|
+
install_type = params[:install_type]
|
|
29
|
+
if install_type.nil?
|
|
30
|
+
install_type = "1"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
password = params[:password]
|
|
34
|
+
if password.nil?
|
|
35
|
+
password = ""
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
request_params = {
|
|
39
|
+
"_api_key" => api_key,
|
|
40
|
+
"buildType" => type,
|
|
41
|
+
"buildInstallType" => install_type,
|
|
42
|
+
"buildPassword" => password,
|
|
43
|
+
}
|
|
44
|
+
request_params["oversea"] = params[:oversea] unless params[:oversea].nil?
|
|
45
|
+
|
|
46
|
+
update_description = params[:update_description]
|
|
47
|
+
|
|
48
|
+
if update_description != nil
|
|
49
|
+
request_params["buildUpdateDescription"] = update_description
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
install_date = params[:install_date]
|
|
53
|
+
|
|
54
|
+
if install_date != nil
|
|
55
|
+
if install_date == "1"
|
|
56
|
+
request_params["buildInstallDate"] = install_date
|
|
57
|
+
install_start_date = params[:install_start_date]
|
|
58
|
+
request_params["buildInstallStartDate"] = install_start_date
|
|
59
|
+
install_end_date = params[:install_end_date]
|
|
60
|
+
request_params["buildInstallEndDate"] = install_end_date
|
|
61
|
+
elsif install_date == "2"
|
|
62
|
+
request_params["buildInstallDate"] = install_date
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
channel = params[:channel]
|
|
67
|
+
if channel != nil
|
|
68
|
+
request_params["buildChannelShortcut"] = channel
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# start upload
|
|
72
|
+
conn_options = {
|
|
73
|
+
request: {
|
|
74
|
+
timeout: 1000,
|
|
75
|
+
open_timeout: 300,
|
|
76
|
+
},
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
# 选择可用的 API 域名
|
|
80
|
+
use_doh = params[:doh] == true
|
|
81
|
+
api_host, pgyer_client, info = self.select_available_api_host(conn_options, request_params, use_doh)
|
|
82
|
+
|
|
83
|
+
if info["code"] != 0
|
|
84
|
+
UI.user_error!("Get token is failed, info: #{info}")
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
key = info["data"]["key"]
|
|
88
|
+
|
|
89
|
+
endpoint = info["data"]["endpoint"]
|
|
90
|
+
|
|
91
|
+
request_params = info["data"]["params"]
|
|
92
|
+
|
|
93
|
+
if key.nil? || endpoint.nil? || request_params.nil?
|
|
94
|
+
UI.user_error!("Get token is failed")
|
|
95
|
+
end
|
|
96
|
+
content_type = type == "android" ? "application/vnd.android.package-archive" : "application/octet-stream"
|
|
97
|
+
|
|
98
|
+
if !params[:user_download_file_name].nil?
|
|
99
|
+
request_params["x-cos-meta-file-name"] = params[:user_download_file_name]
|
|
100
|
+
end
|
|
101
|
+
request_params["file"] = Faraday::UploadIO.new(build_file, content_type)
|
|
102
|
+
|
|
103
|
+
UI.message "Start upload #{build_file} to pgyer..."
|
|
104
|
+
|
|
105
|
+
UI.message "Upload endpoint: #{endpoint}"
|
|
106
|
+
|
|
107
|
+
UI.message "Upload request_params: #{request_params}"
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
response = pgyer_client.post endpoint, request_params
|
|
112
|
+
|
|
113
|
+
if response.status != 204
|
|
114
|
+
UI.user_error!("PGYER Plugin Upload Error: #{response.body}")
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# 如果使用 DoH,需要传递 DoH 相关信息
|
|
118
|
+
doh_info = nil
|
|
119
|
+
if use_doh && api_host.include?("www.pgyer.com")
|
|
120
|
+
domain = "www.pgyer.com"
|
|
121
|
+
ip_address = resolve_domain_via_doh(domain)
|
|
122
|
+
if ip_address
|
|
123
|
+
doh_info = { domain: domain, ip_address: ip_address }
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
answer = self.checkPublishStatus(pgyer_client, api_host, api_key, key, doh_info)
|
|
127
|
+
|
|
128
|
+
if params[:save_uploaded_info_json]
|
|
129
|
+
File.open("pgyer-fastlane-uploaded-app-info.json", "w") do |f|
|
|
130
|
+
f.write(answer.to_json)
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
answer
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def self.description
|
|
137
|
+
"distribute app to pgyer beta testing service"
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def self.authors
|
|
141
|
+
["rexshi"]
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def self.return_value
|
|
145
|
+
# If your method provides a return value, you can describe here what it does
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def self.details
|
|
149
|
+
# Optional:
|
|
150
|
+
"distribute app to pgyer beta testing service"
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def self.available_options
|
|
154
|
+
[
|
|
155
|
+
FastlaneCore::ConfigItem.new(key: :api_key,
|
|
156
|
+
env_name: "PGYER_API_KEY",
|
|
157
|
+
description: "api_key in your pgyer account",
|
|
158
|
+
optional: false,
|
|
159
|
+
type: String),
|
|
160
|
+
FastlaneCore::ConfigItem.new(key: :apk,
|
|
161
|
+
env_name: "PGYER_APK",
|
|
162
|
+
description: "Path to your APK file",
|
|
163
|
+
default_value: Actions.lane_context[SharedValues::GRADLE_APK_OUTPUT_PATH],
|
|
164
|
+
optional: true,
|
|
165
|
+
verify_block: proc do |value|
|
|
166
|
+
UI.user_error!("Couldn't find apk file at path '#{value}'") unless File.exist?(value)
|
|
167
|
+
end,
|
|
168
|
+
conflicting_options: [:ipa, :hap],
|
|
169
|
+
conflict_block: proc do |value|
|
|
170
|
+
UI.user_error!("You can't use 'apk' and '#{value.key}' options in one run")
|
|
171
|
+
end),
|
|
172
|
+
FastlaneCore::ConfigItem.new(key: :ipa,
|
|
173
|
+
env_name: "PGYER_IPA",
|
|
174
|
+
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",
|
|
175
|
+
default_value: Actions.lane_context[SharedValues::IPA_OUTPUT_PATH],
|
|
176
|
+
optional: true,
|
|
177
|
+
verify_block: proc do |value|
|
|
178
|
+
UI.user_error!("Couldn't find ipa file at path '#{value}'") unless File.exist?(value)
|
|
179
|
+
end,
|
|
180
|
+
conflicting_options: [:apk, :hap],
|
|
181
|
+
conflict_block: proc do |value|
|
|
182
|
+
UI.user_error!("You can't use 'ipa' and '#{value.key}' options in one run")
|
|
183
|
+
end),
|
|
184
|
+
FastlaneCore::ConfigItem.new(key: :hap,
|
|
185
|
+
env_name: "PGYER_HAP",
|
|
186
|
+
description: "Path to your HAP file",
|
|
187
|
+
default_value: Actions.lane_context[:HVIGOR_HAP_OUTPUT_PATH],
|
|
188
|
+
optional: true,
|
|
189
|
+
verify_block: proc do |value|
|
|
190
|
+
UI.user_error!("Couldn't find hap file at path '#{value}'") unless File.exist?(value)
|
|
191
|
+
end,
|
|
192
|
+
conflicting_options: [:apk, :ipa],
|
|
193
|
+
conflict_block: proc do |value|
|
|
194
|
+
UI.user_error!("You can't use 'hap' and '#{value.key}' options in one run")
|
|
195
|
+
end),
|
|
196
|
+
FastlaneCore::ConfigItem.new(key: :password,
|
|
197
|
+
env_name: "PGYER_PASSWORD",
|
|
198
|
+
description: "Set password to protect app",
|
|
199
|
+
optional: true,
|
|
200
|
+
type: String),
|
|
201
|
+
|
|
202
|
+
FastlaneCore::ConfigItem.new(key: :user_download_file_name,
|
|
203
|
+
env_name: "USER_DOWNLOAD_FILE_NAME",
|
|
204
|
+
description: "Rename the file name that user downloaded from pgyer",
|
|
205
|
+
optional: true,
|
|
206
|
+
type: String),
|
|
207
|
+
|
|
208
|
+
FastlaneCore::ConfigItem.new(key: :update_description,
|
|
209
|
+
env_name: "PGYER_UPDATE_DESCRIPTION",
|
|
210
|
+
description: "Set update description for app",
|
|
211
|
+
optional: true,
|
|
212
|
+
type: String),
|
|
213
|
+
|
|
214
|
+
FastlaneCore::ConfigItem.new(key: :save_uploaded_info_json,
|
|
215
|
+
env_name: "PGYER_SAVE_UPLOADED_INFO_JSON",
|
|
216
|
+
description: "Save uploaded info json to file named pgyer-fastlane-uploaded-app-info.json",
|
|
217
|
+
optional: true,
|
|
218
|
+
default_value: false,
|
|
219
|
+
type: Boolean),
|
|
220
|
+
|
|
221
|
+
FastlaneCore::ConfigItem.new(key: :install_type,
|
|
222
|
+
env_name: "PGYER_INSTALL_TYPE",
|
|
223
|
+
description: "Set install type for app (1=public, 2=password, 3=invite). Please set as a string",
|
|
224
|
+
optional: true,
|
|
225
|
+
type: String),
|
|
226
|
+
FastlaneCore::ConfigItem.new(key: :install_date,
|
|
227
|
+
env_name: "PGYER_INSTALL_DATE",
|
|
228
|
+
description: "Set install type for app (1=Set valid time, 2=Long-term effective, other=Do not modify the last setting). Please set as a string",
|
|
229
|
+
optional: true,
|
|
230
|
+
type: String),
|
|
231
|
+
FastlaneCore::ConfigItem.new(key: :install_start_date,
|
|
232
|
+
env_name: "PGYER_INSTALL_START_DATE",
|
|
233
|
+
description: "The value is a string of characters, for example, 2018-01-01",
|
|
234
|
+
optional: true,
|
|
235
|
+
type: String),
|
|
236
|
+
|
|
237
|
+
FastlaneCore::ConfigItem.new(key: :install_end_date,
|
|
238
|
+
env_name: "PGYER_INSTALL_END_DATE",
|
|
239
|
+
description: "The value is a string of characters, such as 2018-12-31",
|
|
240
|
+
optional: true,
|
|
241
|
+
type: String),
|
|
242
|
+
|
|
243
|
+
FastlaneCore::ConfigItem.new(key: :oversea,
|
|
244
|
+
env_name: "PGYER_OVERSEA",
|
|
245
|
+
description: "Whether to use overseas acceleration. 1 for overseas accelerated upload, 0 for domestic accelerated upload, not filled in for automatic judgment based on IP",
|
|
246
|
+
optional: true,
|
|
247
|
+
type: Numeric),
|
|
248
|
+
FastlaneCore::ConfigItem.new(key: :channel,
|
|
249
|
+
env_name: "PGYER_SPECIFIED_CHANNEL",
|
|
250
|
+
description: "Need to update the specified channel of the download short link, can specify only one channel, string type, such as: ABCD",
|
|
251
|
+
optional: true,
|
|
252
|
+
type: String),
|
|
253
|
+
FastlaneCore::ConfigItem.new(key: :doh,
|
|
254
|
+
env_name: "PGYER_DOH",
|
|
255
|
+
description: "Use DNS over HTTPS (DoH) to resolve domain names, bypassing local DNS. Experimental feature",
|
|
256
|
+
optional: true,
|
|
257
|
+
default_value: false,
|
|
258
|
+
type: Boolean),
|
|
259
|
+
]
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
def self.is_supported?(platform)
|
|
263
|
+
# Adjust this if your plugin only works for a particular platform (iOS vs. Android, for example)
|
|
264
|
+
# See: https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Platforms.md
|
|
265
|
+
#
|
|
266
|
+
[:ios, :mac, :android].include?(platform)
|
|
267
|
+
true
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
private
|
|
271
|
+
|
|
272
|
+
def self.select_available_api_host(conn_options, request_params, use_doh = false)
|
|
273
|
+
# 如果启用 DoH,直接使用 DoH 解析 www.pgyer.com,跳过三个域名测试
|
|
274
|
+
if use_doh
|
|
275
|
+
return select_api_host_via_doh(conn_options, request_params)
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
# 尝试多个域名,防止 DNS 劫持
|
|
279
|
+
api_hosts = [
|
|
280
|
+
"https://www.pgyer.com/apiv2/app",
|
|
281
|
+
"https://www.xcxwo.com/apiv2/app",
|
|
282
|
+
"https://www.pgyerapp.com/apiv2/app",
|
|
283
|
+
]
|
|
284
|
+
|
|
285
|
+
api_host = nil
|
|
286
|
+
pgyer_client = nil
|
|
287
|
+
info = nil
|
|
288
|
+
|
|
289
|
+
api_hosts.each_with_index do |host, index|
|
|
290
|
+
UI.message "尝试使用域名 #{index + 1}/#{api_hosts.length}: #{host}"
|
|
291
|
+
|
|
292
|
+
begin
|
|
293
|
+
# 为域名检测设置 5 秒超时
|
|
294
|
+
test_conn_options = {
|
|
295
|
+
request: {
|
|
296
|
+
timeout: 5,
|
|
297
|
+
open_timeout: 5,
|
|
298
|
+
},
|
|
299
|
+
}
|
|
300
|
+
test_client = create_faraday_client(test_conn_options, nil)
|
|
301
|
+
|
|
302
|
+
# 使用超时控制,5 秒后如果还没响应就放弃
|
|
303
|
+
test_response = nil
|
|
304
|
+
test_info = nil
|
|
305
|
+
|
|
306
|
+
begin
|
|
307
|
+
Timeout.timeout(5) do
|
|
308
|
+
test_response = test_client.post "#{host}/getCOSToken", request_params
|
|
309
|
+
test_info = test_response.body
|
|
310
|
+
end
|
|
311
|
+
rescue Timeout::Error
|
|
312
|
+
UI.message "域名 #{host} 请求超时(5秒),切换到下一个域名"
|
|
313
|
+
next
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
# 检查响应是否有效:如果返回了有效的 JSON 且包含 code 字段,说明域名解析正常
|
|
317
|
+
if test_info && test_info.is_a?(Hash) && test_info.key?("code")
|
|
318
|
+
if test_info["code"] == 0
|
|
319
|
+
# API 调用成功,使用该域名
|
|
320
|
+
# 使用原始的超时设置重新创建客户端(用于后续上传)
|
|
321
|
+
api_host = host
|
|
322
|
+
pgyer_client = create_faraday_client(conn_options, nil)
|
|
323
|
+
info = test_info
|
|
324
|
+
UI.success "成功使用域名: #{host}"
|
|
325
|
+
break
|
|
326
|
+
else
|
|
327
|
+
# API 返回了业务错误,但域名解析正常
|
|
328
|
+
# 保存第一个可用的域名作为备选,继续尝试其他域名看是否有返回 code == 0 的
|
|
329
|
+
if api_host.nil?
|
|
330
|
+
api_host = host
|
|
331
|
+
# 使用原始的超时设置重新创建客户端
|
|
332
|
+
pgyer_client = create_faraday_client(conn_options, nil)
|
|
333
|
+
info = test_info
|
|
334
|
+
UI.message "域名 #{host} 解析正常,但 API 返回错误,保存为备选: #{test_info}"
|
|
335
|
+
else
|
|
336
|
+
UI.message "域名 #{host} 可用,但 API 返回错误: #{test_info}"
|
|
337
|
+
end
|
|
338
|
+
end
|
|
339
|
+
else
|
|
340
|
+
# 响应格式不正确,可能是 DNS 劫持
|
|
341
|
+
UI.message "域名 #{host} 返回的响应格式不正确,可能遭遇 DNS 劫持"
|
|
342
|
+
end
|
|
343
|
+
rescue => e
|
|
344
|
+
UI.message "域名 #{host} 测试失败(可能是 DNS 劫持或超时): #{e.message}"
|
|
345
|
+
next
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
if api_host.nil? || pgyer_client.nil? || info.nil?
|
|
350
|
+
UI.user_error!("所有域名都无法使用,可能都遭遇了 DNS 劫持。尝试的域名: #{api_hosts.join(', ')}")
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
return api_host, pgyer_client, info
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
# DoH 模式:使用 DoH 解析 www.pgyer.com(实验性功能)
|
|
357
|
+
def self.select_api_host_via_doh(conn_options, request_params)
|
|
358
|
+
UI.message "启用 DoH 模式,使用 DoH 解析 www.pgyer.com"
|
|
359
|
+
|
|
360
|
+
host = "https://www.pgyer.com/apiv2/app"
|
|
361
|
+
domain = "www.pgyer.com"
|
|
362
|
+
|
|
363
|
+
# 通过 DoH 解析域名
|
|
364
|
+
ip_address = resolve_domain_via_doh(domain)
|
|
365
|
+
|
|
366
|
+
if ip_address.nil?
|
|
367
|
+
UI.user_error!("DoH 解析失败,无法获取 www.pgyer.com 的 IP 地址")
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
UI.message "DoH 解析成功: #{domain} -> #{ip_address}"
|
|
371
|
+
|
|
372
|
+
# 使用 IP 地址替换域名,但保留 Host header
|
|
373
|
+
actual_url = host.gsub(domain, ip_address)
|
|
374
|
+
host_header = domain
|
|
375
|
+
|
|
376
|
+
begin
|
|
377
|
+
test_client = create_faraday_client(conn_options, host_header)
|
|
378
|
+
|
|
379
|
+
# 设置 Host header
|
|
380
|
+
request_headers = { "Host" => host_header }
|
|
381
|
+
|
|
382
|
+
test_response = test_client.post "#{actual_url}/getCOSToken", request_params, request_headers
|
|
383
|
+
test_info = test_response.body
|
|
384
|
+
|
|
385
|
+
if test_info && test_info.is_a?(Hash) && test_info.key?("code")
|
|
386
|
+
if test_info["code"] == 0
|
|
387
|
+
UI.success "DoH 模式:成功使用域名 #{host}"
|
|
388
|
+
return host, test_client, test_info
|
|
389
|
+
else
|
|
390
|
+
UI.user_error!("DoH 模式:API 返回错误: #{test_info}")
|
|
391
|
+
end
|
|
392
|
+
else
|
|
393
|
+
UI.user_error!("DoH 模式:返回的响应格式不正确: #{test_info}")
|
|
394
|
+
end
|
|
395
|
+
rescue => e
|
|
396
|
+
UI.user_error!("DoH 模式:请求失败: #{e.message}")
|
|
397
|
+
end
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
# DoH 相关方法(实验性功能)
|
|
401
|
+
def self.resolve_domain_via_doh(domain)
|
|
402
|
+
# 使用阿里云公共 DoH 服务
|
|
403
|
+
doh_url = "https://dns.alidns.com/resolve"
|
|
404
|
+
|
|
405
|
+
begin
|
|
406
|
+
doh_client = Faraday.new do |c|
|
|
407
|
+
c.request :url_encoded
|
|
408
|
+
c.response :json
|
|
409
|
+
c.adapter :net_http
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
response = doh_client.get(doh_url, { name: domain, type: "A" })
|
|
413
|
+
result = response.body
|
|
414
|
+
|
|
415
|
+
if result && result.is_a?(Hash) && result["Answer"]
|
|
416
|
+
# 获取第一个 A 记录
|
|
417
|
+
a_record = result["Answer"].find { |r| r["type"] == 1 }
|
|
418
|
+
if a_record && a_record["data"]
|
|
419
|
+
return a_record["data"]
|
|
420
|
+
end
|
|
421
|
+
end
|
|
422
|
+
rescue => e
|
|
423
|
+
UI.message "DoH 解析出错: #{e.message}"
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
return nil
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
def self.extract_domain_from_url(url)
|
|
430
|
+
# 从 URL 中提取域名
|
|
431
|
+
# 例如: https://www.pgyer.com/apiv2/app -> www.pgyer.com
|
|
432
|
+
uri = URI.parse(url)
|
|
433
|
+
return uri.host
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
def self.create_faraday_client(conn_options, host_header = nil)
|
|
437
|
+
# 创建基础的 Faraday 客户端
|
|
438
|
+
# Host header 将在请求时通过 headers 参数设置
|
|
439
|
+
# DoH 模式下禁用 SSL 证书验证(因为使用 IP 地址,证书绑定域名)
|
|
440
|
+
final_options = conn_options.dup
|
|
441
|
+
|
|
442
|
+
Faraday.new(nil, final_options) do |c|
|
|
443
|
+
c.request :multipart
|
|
444
|
+
c.request :url_encoded
|
|
445
|
+
c.response :json, content_type: /\bjson$/
|
|
446
|
+
c.adapter :net_http do |http|
|
|
447
|
+
if host_header
|
|
448
|
+
# DoH 模式:使用 IP 地址,禁用 SSL 证书验证
|
|
449
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
|
450
|
+
UI.message "DoH 模式:已禁用 SSL 证书验证(实验性功能)"
|
|
451
|
+
else
|
|
452
|
+
# 普通模式:使用默认 SSL 验证
|
|
453
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
|
454
|
+
end
|
|
455
|
+
end
|
|
456
|
+
end
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
def self.get_type(params)
|
|
460
|
+
type = params[:ipa].nil? ? "android" : "ios"
|
|
461
|
+
|
|
462
|
+
if !params[:hap].nil?
|
|
463
|
+
type = "hap"
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
type
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
def self.checkPublishStatus(client, api_host, api_key, buildKey, doh_info = nil)
|
|
470
|
+
# URL 保持使用域名(用于显示)
|
|
471
|
+
url = "#{api_host}/buildInfo"
|
|
472
|
+
UI.message "checkPublishStatus url: #{url}"
|
|
473
|
+
|
|
474
|
+
# 如果使用 DoH,实际请求时使用 IP 地址,但设置 Host header
|
|
475
|
+
actual_url = api_host
|
|
476
|
+
request_headers = {}
|
|
477
|
+
|
|
478
|
+
if doh_info && doh_info[:ip_address]
|
|
479
|
+
# 实际连接使用 IP 地址
|
|
480
|
+
actual_url = api_host.gsub(doh_info[:domain], doh_info[:ip_address])
|
|
481
|
+
# 设置 Host header 为原始域名
|
|
482
|
+
request_headers["Host"] = doh_info[:domain]
|
|
483
|
+
UI.message "DoH 模式:实际连接使用 IP 地址 #{doh_info[:ip_address]},Host header: #{doh_info[:domain]}"
|
|
484
|
+
end
|
|
485
|
+
|
|
486
|
+
response = client.post "#{actual_url}/buildInfo", { :_api_key => api_key, :buildKey => buildKey }, request_headers
|
|
487
|
+
info = response.body
|
|
488
|
+
code = info["code"]
|
|
489
|
+
if code == 0
|
|
490
|
+
UI.success "Upload success. BuildInfo is #{info["data"]}."
|
|
491
|
+
shortUrl = info["data"]["buildShortcutUrl"]
|
|
492
|
+
if shortUrl.nil? || shortUrl == ""
|
|
493
|
+
shortUrl = info["data"]["buildKey"]
|
|
494
|
+
end
|
|
495
|
+
info["data"]["fastlaneAddedWholeVisitUrl"] = "https://www.pgyer.com/#{shortUrl}"
|
|
496
|
+
UI.success "Upload success. Visit this URL to see: #{info["data"]["fastlaneAddedWholeVisitUrl"]}"
|
|
497
|
+
return info["data"]
|
|
498
|
+
elsif code == 1246 || code == 1247
|
|
499
|
+
sleep 3
|
|
500
|
+
self.checkPublishStatus(client, api_host, api_key, buildKey, doh_info)
|
|
501
|
+
else
|
|
502
|
+
UI.user_error!("PGYER Plugin Published Error: #{info} buildKey: #{buildKey}")
|
|
503
|
+
end
|
|
504
|
+
end
|
|
505
|
+
end
|
|
506
|
+
end
|
|
507
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require "fastlane_core/ui/ui"
|
|
2
|
+
|
|
3
|
+
module Fastlane
|
|
4
|
+
UI = FastlaneCore::UI unless Fastlane.const_defined?("UI")
|
|
5
|
+
|
|
6
|
+
module Helper
|
|
7
|
+
class PgyerHelper
|
|
8
|
+
# class methods that you define here become available in your action
|
|
9
|
+
# as `Helper::PgyerHelper.your_method`
|
|
10
|
+
#
|
|
11
|
+
def self.show_message
|
|
12
|
+
UI.message("Hello from the pgyer plugin helper!")
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require "fastlane/plugin/pgyer"
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require 'fastlane/plugin/pgyer/version'
|
|
2
|
+
|
|
3
|
+
module Fastlane
|
|
4
|
+
module Pgyer
|
|
5
|
+
# Return all .rb files inside the "actions" and "helper" directory
|
|
6
|
+
def self.all_classes
|
|
7
|
+
Dir[File.expand_path('**/{actions,helper}/*.rb', File.dirname(__FILE__))]
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# By default we want to import all available actions and helpers
|
|
13
|
+
# A plugin can contain any number of actions and plugins
|
|
14
|
+
Fastlane::Pgyer.all_classes.each do |current|
|
|
15
|
+
require current
|
|
16
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: fastlane-plugin-pgyersws
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.3.5
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- rexshi
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: faraday
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '1.10'
|
|
19
|
+
- - "<"
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '3.0'
|
|
22
|
+
type: :runtime
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
+
requirements:
|
|
26
|
+
- - ">="
|
|
27
|
+
- !ruby/object:Gem::Version
|
|
28
|
+
version: '1.10'
|
|
29
|
+
- - "<"
|
|
30
|
+
- !ruby/object:Gem::Version
|
|
31
|
+
version: '3.0'
|
|
32
|
+
- !ruby/object:Gem::Dependency
|
|
33
|
+
name: faraday-multipart
|
|
34
|
+
requirement: !ruby/object:Gem::Requirement
|
|
35
|
+
requirements:
|
|
36
|
+
- - ">="
|
|
37
|
+
- !ruby/object:Gem::Version
|
|
38
|
+
version: '1.0'
|
|
39
|
+
- - "<"
|
|
40
|
+
- !ruby/object:Gem::Version
|
|
41
|
+
version: '3.0'
|
|
42
|
+
type: :runtime
|
|
43
|
+
prerelease: false
|
|
44
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
45
|
+
requirements:
|
|
46
|
+
- - ">="
|
|
47
|
+
- !ruby/object:Gem::Version
|
|
48
|
+
version: '1.0'
|
|
49
|
+
- - "<"
|
|
50
|
+
- !ruby/object:Gem::Version
|
|
51
|
+
version: '3.0'
|
|
52
|
+
- !ruby/object:Gem::Dependency
|
|
53
|
+
name: bundler
|
|
54
|
+
requirement: !ruby/object:Gem::Requirement
|
|
55
|
+
requirements:
|
|
56
|
+
- - ">="
|
|
57
|
+
- !ruby/object:Gem::Version
|
|
58
|
+
version: '0'
|
|
59
|
+
type: :development
|
|
60
|
+
prerelease: false
|
|
61
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
62
|
+
requirements:
|
|
63
|
+
- - ">="
|
|
64
|
+
- !ruby/object:Gem::Version
|
|
65
|
+
version: '0'
|
|
66
|
+
- !ruby/object:Gem::Dependency
|
|
67
|
+
name: fastlane
|
|
68
|
+
requirement: !ruby/object:Gem::Requirement
|
|
69
|
+
requirements:
|
|
70
|
+
- - ">="
|
|
71
|
+
- !ruby/object:Gem::Version
|
|
72
|
+
version: 2.208.0
|
|
73
|
+
type: :development
|
|
74
|
+
prerelease: false
|
|
75
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
76
|
+
requirements:
|
|
77
|
+
- - ">="
|
|
78
|
+
- !ruby/object:Gem::Version
|
|
79
|
+
version: 2.208.0
|
|
80
|
+
- !ruby/object:Gem::Dependency
|
|
81
|
+
name: pry
|
|
82
|
+
requirement: !ruby/object:Gem::Requirement
|
|
83
|
+
requirements:
|
|
84
|
+
- - ">="
|
|
85
|
+
- !ruby/object:Gem::Version
|
|
86
|
+
version: '0'
|
|
87
|
+
type: :development
|
|
88
|
+
prerelease: false
|
|
89
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
90
|
+
requirements:
|
|
91
|
+
- - ">="
|
|
92
|
+
- !ruby/object:Gem::Version
|
|
93
|
+
version: '0'
|
|
94
|
+
- !ruby/object:Gem::Dependency
|
|
95
|
+
name: rake
|
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
|
97
|
+
requirements:
|
|
98
|
+
- - ">="
|
|
99
|
+
- !ruby/object:Gem::Version
|
|
100
|
+
version: '0'
|
|
101
|
+
type: :development
|
|
102
|
+
prerelease: false
|
|
103
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
104
|
+
requirements:
|
|
105
|
+
- - ">="
|
|
106
|
+
- !ruby/object:Gem::Version
|
|
107
|
+
version: '0'
|
|
108
|
+
- !ruby/object:Gem::Dependency
|
|
109
|
+
name: rspec
|
|
110
|
+
requirement: !ruby/object:Gem::Requirement
|
|
111
|
+
requirements:
|
|
112
|
+
- - ">="
|
|
113
|
+
- !ruby/object:Gem::Version
|
|
114
|
+
version: '0'
|
|
115
|
+
type: :development
|
|
116
|
+
prerelease: false
|
|
117
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
118
|
+
requirements:
|
|
119
|
+
- - ">="
|
|
120
|
+
- !ruby/object:Gem::Version
|
|
121
|
+
version: '0'
|
|
122
|
+
- !ruby/object:Gem::Dependency
|
|
123
|
+
name: rspec_junit_formatter
|
|
124
|
+
requirement: !ruby/object:Gem::Requirement
|
|
125
|
+
requirements:
|
|
126
|
+
- - ">="
|
|
127
|
+
- !ruby/object:Gem::Version
|
|
128
|
+
version: '0'
|
|
129
|
+
type: :development
|
|
130
|
+
prerelease: false
|
|
131
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
132
|
+
requirements:
|
|
133
|
+
- - ">="
|
|
134
|
+
- !ruby/object:Gem::Version
|
|
135
|
+
version: '0'
|
|
136
|
+
- !ruby/object:Gem::Dependency
|
|
137
|
+
name: rubocop
|
|
138
|
+
requirement: !ruby/object:Gem::Requirement
|
|
139
|
+
requirements:
|
|
140
|
+
- - '='
|
|
141
|
+
- !ruby/object:Gem::Version
|
|
142
|
+
version: 1.12.1
|
|
143
|
+
type: :development
|
|
144
|
+
prerelease: false
|
|
145
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
146
|
+
requirements:
|
|
147
|
+
- - '='
|
|
148
|
+
- !ruby/object:Gem::Version
|
|
149
|
+
version: 1.12.1
|
|
150
|
+
- !ruby/object:Gem::Dependency
|
|
151
|
+
name: rubocop-performance
|
|
152
|
+
requirement: !ruby/object:Gem::Requirement
|
|
153
|
+
requirements:
|
|
154
|
+
- - ">="
|
|
155
|
+
- !ruby/object:Gem::Version
|
|
156
|
+
version: '0'
|
|
157
|
+
type: :development
|
|
158
|
+
prerelease: false
|
|
159
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
160
|
+
requirements:
|
|
161
|
+
- - ">="
|
|
162
|
+
- !ruby/object:Gem::Version
|
|
163
|
+
version: '0'
|
|
164
|
+
- !ruby/object:Gem::Dependency
|
|
165
|
+
name: rubocop-require_tools
|
|
166
|
+
requirement: !ruby/object:Gem::Requirement
|
|
167
|
+
requirements:
|
|
168
|
+
- - ">="
|
|
169
|
+
- !ruby/object:Gem::Version
|
|
170
|
+
version: '0'
|
|
171
|
+
type: :development
|
|
172
|
+
prerelease: false
|
|
173
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
174
|
+
requirements:
|
|
175
|
+
- - ">="
|
|
176
|
+
- !ruby/object:Gem::Version
|
|
177
|
+
version: '0'
|
|
178
|
+
- !ruby/object:Gem::Dependency
|
|
179
|
+
name: simplecov
|
|
180
|
+
requirement: !ruby/object:Gem::Requirement
|
|
181
|
+
requirements:
|
|
182
|
+
- - ">="
|
|
183
|
+
- !ruby/object:Gem::Version
|
|
184
|
+
version: '0'
|
|
185
|
+
type: :development
|
|
186
|
+
prerelease: false
|
|
187
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
188
|
+
requirements:
|
|
189
|
+
- - ">="
|
|
190
|
+
- !ruby/object:Gem::Version
|
|
191
|
+
version: '0'
|
|
192
|
+
email: rexshi@pgyer.com
|
|
193
|
+
executables: []
|
|
194
|
+
extensions: []
|
|
195
|
+
extra_rdoc_files: []
|
|
196
|
+
files:
|
|
197
|
+
- LICENSE
|
|
198
|
+
- README.md
|
|
199
|
+
- lib/fastlane/plugin/pgyer.rb
|
|
200
|
+
- lib/fastlane/plugin/pgyer/actions/pgyer_action.rb
|
|
201
|
+
- lib/fastlane/plugin/pgyer/helper/pgyer_helper.rb
|
|
202
|
+
- lib/fastlane/plugin/pgyer/sws.rb
|
|
203
|
+
- lib/fastlane/plugin/pgyer/version.rb
|
|
204
|
+
- lib/fastlane/plugin/pgyersws.rb
|
|
205
|
+
homepage: https://github.com/shishirui/fastlane-plugin-pgyer
|
|
206
|
+
licenses:
|
|
207
|
+
- MIT
|
|
208
|
+
metadata: {}
|
|
209
|
+
rdoc_options: []
|
|
210
|
+
require_paths:
|
|
211
|
+
- lib
|
|
212
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
213
|
+
requirements:
|
|
214
|
+
- - ">="
|
|
215
|
+
- !ruby/object:Gem::Version
|
|
216
|
+
version: '2.6'
|
|
217
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
218
|
+
requirements:
|
|
219
|
+
- - ">="
|
|
220
|
+
- !ruby/object:Gem::Version
|
|
221
|
+
version: '0'
|
|
222
|
+
requirements: []
|
|
223
|
+
rubygems_version: 4.0.14
|
|
224
|
+
specification_version: 4
|
|
225
|
+
summary: distribute app to pgyer beta testing service
|
|
226
|
+
test_files: []
|