fastlane-plugin-saucelabs_appdist 0.3.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 +7 -0
- data/LICENSE +21 -0
- data/README.md +89 -0
- data/lib/fastlane/plugin/saucelabs_appdist/actions/saucelabs_appdist_action.rb +305 -0
- data/lib/fastlane/plugin/saucelabs_appdist/helper/saucelabs_appdist_helper.rb +13 -0
- data/lib/fastlane/plugin/saucelabs_appdist/saucelabs_appdist.rb +13 -0
- data/lib/fastlane/plugin/saucelabs_appdist/version.rb +5 -0
- data/lib/fastlane/plugin/saucelabs_appdist.rb +1 -0
- metadata +162 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 6d3301d1ecefd85c6e0937b8ce1b7b1ff4b41c22cd28beb9f12ddb19e82ccdd4
|
|
4
|
+
data.tar.gz: eb8c4a6b0047a1a3c25fffcde4c607c4560b0f54eb858ed8d78a97ed0ad65ba5
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 85b35a83c6c41e678d0fec3dcfa42fcdb356265d6feabd2e50c190c73b046889a670e5d1ad60b5d47afb01ec27fec73058920ccc4e4973e9d851483839596c8b
|
|
7
|
+
data.tar.gz: 4726a9fe7be5c1aa5a26466b1c1f9b860d186a89205ac0e121dde48da2747d0999c07067d8c52eaae93e2d97ccf8f392a9bf5659e8a2f0332916b4c575a30442
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Simon Sarrafi
|
|
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,89 @@
|
|
|
1
|
+
# fastlane-plugin-saucelabs_appdist
|
|
2
|
+
|
|
3
|
+
[](https://rubygems.org/gems/fastlane-plugin-saucelabs_appdist)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
|
|
6
|
+
A [Sauce Labs](https://saucelabs.com) fastlane plugin for uploading builds to **Mobile App Distribution**.
|
|
7
|
+
|
|
8
|
+
For more information about Sauce Labs Mobile App Distribution, see the [product page](https://saucelabs.com/products/mobile-testing/app-betas).
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```sh
|
|
13
|
+
fastlane add_plugin saucelabs_appdist
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Or add the plugin manually to your project's `Pluginfile`:
|
|
17
|
+
|
|
18
|
+
```ruby
|
|
19
|
+
gem 'fastlane-plugin-saucelabs_appdist'
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
```ruby
|
|
25
|
+
saucelabs_appdist(
|
|
26
|
+
api_key: "your_api_key",
|
|
27
|
+
ipa: "./path/to/app.ipa",
|
|
28
|
+
comment: "Build #{lane_context[SharedValues::BUILD_NUMBER]}"
|
|
29
|
+
)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Parameters
|
|
33
|
+
|
|
34
|
+
| Key | Description | Default |
|
|
35
|
+
|-----|-------------|---------|
|
|
36
|
+
| `api_key` | API Key for Sauce Labs App Distribution | — |
|
|
37
|
+
| `ipa` | Path to your IPA file (iOS) | — |
|
|
38
|
+
| `apk` | Path to your APK file (Android) | — |
|
|
39
|
+
| `symbols_file` | Symbols mapping file | — |
|
|
40
|
+
| `upload_url` | API URL for App Distribution | `https://app.testfairy.com` |
|
|
41
|
+
| `testers_groups` | Array of tester groups | `[]` |
|
|
42
|
+
| `metrics` | Array of metrics to record | `[]` |
|
|
43
|
+
| `comment` | Additional release notes | `No comment provided` |
|
|
44
|
+
| `auto_update` | Auto-upgrade users (`on`/`off`) | `off` |
|
|
45
|
+
| `notify` | Send email to testers (`on`/`off`) | `off` |
|
|
46
|
+
| `options` | Array of options | `[]` |
|
|
47
|
+
| `custom` | Custom options string | `""` |
|
|
48
|
+
| `timeout` | Request timeout in seconds | — |
|
|
49
|
+
| `tags` | Custom tags for builds | `[]` |
|
|
50
|
+
| `folder_name` | Dashboard folder name | `""` |
|
|
51
|
+
| `landing_page_mode` | Landing page visibility (`open`/`closed`) | `open` |
|
|
52
|
+
| `upload_to_saucelabs` | Upload to Sauce Labs (`on`/`off`) | `off` |
|
|
53
|
+
| `platform` | Platform override | `""` |
|
|
54
|
+
|
|
55
|
+
## Response
|
|
56
|
+
|
|
57
|
+
The `SAUCELABS_APPDIST_UPLOAD_RESPONSE` shared value contains the full JSON response from the upload API. It is set in `lane_context` and can be accessed in subsequent lanes:
|
|
58
|
+
|
|
59
|
+
```ruby
|
|
60
|
+
lane_context[SharedValues::SAUCELABS_APPDIST_UPLOAD_RESPONSE]
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Example response:
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"status": "ok",
|
|
68
|
+
"build_id": "1",
|
|
69
|
+
"project_id": "1",
|
|
70
|
+
"app_name": "My Demo App",
|
|
71
|
+
"app_version": "2.0.2 - 2026-02-19 02:51:05",
|
|
72
|
+
"file_size": 2319620,
|
|
73
|
+
"build_url": "https://app.testfairy.com/projects/1/builds/1",
|
|
74
|
+
"download_page_url": "https://app.testfairy.com/join/xxxxxx",
|
|
75
|
+
"app_url": "https://app.testfairy.com/download/.../getapp",
|
|
76
|
+
"invite_testers_url": "https://app.testfairy.com/projects/1/builds/1/invite",
|
|
77
|
+
"icon_url": "https://app.testfairy.com/icons/.../icon.png",
|
|
78
|
+
"options": "video-quality=medium,screenshot-interval=1,session-length=60m,video,logcat,shake,cpu,memory,phone-signal,battery,wifi",
|
|
79
|
+
"platform": "iOS",
|
|
80
|
+
"tags": [],
|
|
81
|
+
"metadata": [],
|
|
82
|
+
"has_testfairy_sdk": true,
|
|
83
|
+
"symbols_download_url": null,
|
|
84
|
+
"attachments": null,
|
|
85
|
+
"landing_page_url": "https://app.testfairy.com/join/xxxxxx",
|
|
86
|
+
"build_specific_landing_page_url": "https://app.testfairy.com/join/xxxxxx?id=1",
|
|
87
|
+
"landing_page_mode": "closed"
|
|
88
|
+
}
|
|
89
|
+
```
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
module Fastlane
|
|
2
|
+
module Actions
|
|
3
|
+
module SharedValues
|
|
4
|
+
SAUCELABS_APPDIST_UPLOAD_RESPONSE = :SAUCELABS_APPDIST_UPLOAD_RESPONSE
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
class SaucelabsAppdistAction < Action
|
|
8
|
+
def self.upload_build(upload_url, ipa, options, timeout)
|
|
9
|
+
require 'faraday'
|
|
10
|
+
require 'faraday_middleware'
|
|
11
|
+
|
|
12
|
+
UI.success("Uploading to #{upload_url}...")
|
|
13
|
+
|
|
14
|
+
connection = Faraday.new(url: upload_url) do |builder|
|
|
15
|
+
builder.request(:multipart)
|
|
16
|
+
builder.request(:url_encoded)
|
|
17
|
+
builder.request(:retry, max: 3, interval: 5)
|
|
18
|
+
builder.response(:json, content_type: /\bjson$/)
|
|
19
|
+
builder.use(FaradayMiddleware::FollowRedirects)
|
|
20
|
+
builder.adapter(:net_http)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
options[:file] = Faraday::UploadIO.new(ipa, 'application/octet-stream') if ipa && File.exist?(ipa)
|
|
24
|
+
|
|
25
|
+
symbols_file = options.delete(:symbols_file)
|
|
26
|
+
if symbols_file
|
|
27
|
+
options[:symbols_file] = Faraday::UploadIO.new(symbols_file, 'application/octet-stream')
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
begin
|
|
31
|
+
connection.post do |req|
|
|
32
|
+
req.options.timeout = timeout
|
|
33
|
+
req.url("/api/upload/")
|
|
34
|
+
req.body = options
|
|
35
|
+
end
|
|
36
|
+
rescue Faraday::TimeoutError
|
|
37
|
+
UI.crash!("Uploading build to Sauce Labs App Distribution timed out ⏳")
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def self.run(params)
|
|
42
|
+
UI.success('Starting with ipa upload to Sauce Labs App Distribution...')
|
|
43
|
+
|
|
44
|
+
metrics_to_client = lambda do |metrics|
|
|
45
|
+
metrics.map do |metric|
|
|
46
|
+
case metric
|
|
47
|
+
when :cpu, :memory, :network, :gps, :battery, :mic, :wifi
|
|
48
|
+
metric.to_s
|
|
49
|
+
when :phone_signal
|
|
50
|
+
'phone-signal'
|
|
51
|
+
else
|
|
52
|
+
UI.user_error!("Unknown metric: #{metric}")
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
options_to_client = lambda do |options|
|
|
58
|
+
options.map do |option|
|
|
59
|
+
case option.to_sym
|
|
60
|
+
when :shake, :anonymous
|
|
61
|
+
option.to_s
|
|
62
|
+
when :video_only_wifi
|
|
63
|
+
'video-only-wifi'
|
|
64
|
+
else
|
|
65
|
+
UI.user_error!("Unknown option: #{option}")
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Rejecting key `upload_url` and `timeout` as we don't need it in options
|
|
71
|
+
client_options = Hash[params.values.reject do |key, value|
|
|
72
|
+
[:upload_url, :timeout].include?(key)
|
|
73
|
+
end.map do |key, value|
|
|
74
|
+
case key
|
|
75
|
+
when :api_key
|
|
76
|
+
[key, value]
|
|
77
|
+
when :ipa
|
|
78
|
+
[key, value]
|
|
79
|
+
when :apk
|
|
80
|
+
[key, value]
|
|
81
|
+
when :symbols_file
|
|
82
|
+
[key, value]
|
|
83
|
+
when :testers_groups
|
|
84
|
+
[key, value.join(',')]
|
|
85
|
+
when :metrics
|
|
86
|
+
[key, metrics_to_client.call(value).join(',')]
|
|
87
|
+
when :comment
|
|
88
|
+
[key, value]
|
|
89
|
+
when :auto_update
|
|
90
|
+
['auto-update', value]
|
|
91
|
+
when :notify
|
|
92
|
+
[key, value]
|
|
93
|
+
when :options
|
|
94
|
+
[key, options_to_client.call(value).join(',')]
|
|
95
|
+
when :custom
|
|
96
|
+
[key, value]
|
|
97
|
+
when :tags
|
|
98
|
+
[key, value.join(',')]
|
|
99
|
+
when :folder_name
|
|
100
|
+
[key, value]
|
|
101
|
+
when :landing_page_mode
|
|
102
|
+
[key, value]
|
|
103
|
+
when :upload_to_saucelabs
|
|
104
|
+
[key, value]
|
|
105
|
+
when :platform
|
|
106
|
+
[key, value]
|
|
107
|
+
else
|
|
108
|
+
UI.user_error!("Unknown parameter: #{key}")
|
|
109
|
+
end
|
|
110
|
+
end]
|
|
111
|
+
|
|
112
|
+
path = params[:ipa] || params[:apk]
|
|
113
|
+
UI.user_error!("No ipa or apk were given") unless path
|
|
114
|
+
|
|
115
|
+
return path if Helper.test?
|
|
116
|
+
|
|
117
|
+
response = self.upload_build(params[:upload_url], path, client_options, params[:timeout])
|
|
118
|
+
if parse_response(response)
|
|
119
|
+
UI.success("Build successfully uploaded to Sauce Labs App Distribution.")
|
|
120
|
+
UI.success("Response:\n#{JSON.pretty_generate(Actions.lane_context[SharedValues::SAUCELABS_APPDIST_UPLOAD_RESPONSE])}")
|
|
121
|
+
else
|
|
122
|
+
UI.user_error!("Error when trying to upload ipa to Sauce Labs App Distribution")
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def self.parse_response(response)
|
|
127
|
+
if response.body && response.body.key?('status') && response.body['status'] == 'ok'
|
|
128
|
+
Actions.lane_context[SharedValues::SAUCELABS_APPDIST_UPLOAD_RESPONSE] = response.body
|
|
129
|
+
|
|
130
|
+
return true
|
|
131
|
+
else
|
|
132
|
+
UI.error("Error uploading to Sauce Labs App Distribution: #{response.body}")
|
|
133
|
+
|
|
134
|
+
return false
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
private_class_method :parse_response
|
|
138
|
+
|
|
139
|
+
def self.description
|
|
140
|
+
'Upload a new build to Sauce Labs App Distribution'
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def self.details
|
|
144
|
+
'A Sauce Labs fastlane plugin for uploading iOS and Android builds to Mobile App Distribution (MAD).'
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def self.available_options
|
|
148
|
+
[
|
|
149
|
+
# required
|
|
150
|
+
FastlaneCore::ConfigItem.new(key: :api_key,
|
|
151
|
+
env_name: "FL_SAUCELABS_APPDIST_API_KEY",
|
|
152
|
+
description: "API Key for Sauce Labs App Distribution",
|
|
153
|
+
sensitive: true,
|
|
154
|
+
verify_block: proc do |value|
|
|
155
|
+
UI.user_error!("No API key for Sauce Labs App Distribution given, pass using `api_key: 'key'`") unless value.to_s.length > 0
|
|
156
|
+
end),
|
|
157
|
+
FastlaneCore::ConfigItem.new(key: :ipa,
|
|
158
|
+
env_name: 'SAUCELABS_APPDIST_IPA_PATH',
|
|
159
|
+
description: 'Path to your IPA file for iOS',
|
|
160
|
+
default_value: Actions.lane_context[SharedValues::IPA_OUTPUT_PATH],
|
|
161
|
+
default_value_dynamic: true,
|
|
162
|
+
optional: true,
|
|
163
|
+
conflicting_options: [:apk],
|
|
164
|
+
verify_block: proc do |value|
|
|
165
|
+
UI.user_error!("Couldn't find ipa file at path '#{value}'") unless File.exist?(value)
|
|
166
|
+
end),
|
|
167
|
+
FastlaneCore::ConfigItem.new(key: :apk,
|
|
168
|
+
env_name: 'SAUCELABS_APPDIST_APK_PATH',
|
|
169
|
+
description: 'Path to your APK file for Android',
|
|
170
|
+
default_value: Actions.lane_context[SharedValues::GRADLE_APK_OUTPUT_PATH],
|
|
171
|
+
default_value_dynamic: true,
|
|
172
|
+
optional: true,
|
|
173
|
+
conflicting_options: [:ipa],
|
|
174
|
+
verify_block: proc do |value|
|
|
175
|
+
UI.user_error!("Couldn't find apk file at path '#{value}'") unless File.exist?(value)
|
|
176
|
+
end),
|
|
177
|
+
# optional
|
|
178
|
+
FastlaneCore::ConfigItem.new(key: :symbols_file,
|
|
179
|
+
optional: true,
|
|
180
|
+
env_name: "FL_SAUCELABS_APPDIST_SYMBOLS_FILE",
|
|
181
|
+
description: "Symbols mapping file",
|
|
182
|
+
default_value: Actions.lane_context[SharedValues::DSYM_OUTPUT_PATH],
|
|
183
|
+
default_value_dynamic: true,
|
|
184
|
+
verify_block: proc do |value|
|
|
185
|
+
UI.user_error!("Couldn't find dSYM file at path '#{value}'") unless File.exist?(value)
|
|
186
|
+
end),
|
|
187
|
+
FastlaneCore::ConfigItem.new(key: :upload_url,
|
|
188
|
+
env_name: "FL_SAUCELABS_APPDIST_UPLOAD_URL",
|
|
189
|
+
description: "API URL for Sauce Labs App Distribution",
|
|
190
|
+
default_value: "https://app.testfairy.com",
|
|
191
|
+
optional: true),
|
|
192
|
+
FastlaneCore::ConfigItem.new(key: :testers_groups,
|
|
193
|
+
optional: true,
|
|
194
|
+
type: Array,
|
|
195
|
+
short_option: '-g',
|
|
196
|
+
env_name: "FL_SAUCELABS_APPDIST_TESTERS_GROUPS",
|
|
197
|
+
description: "Array of tester groups to be notified",
|
|
198
|
+
default_value: []),
|
|
199
|
+
FastlaneCore::ConfigItem.new(key: :metrics,
|
|
200
|
+
optional: true,
|
|
201
|
+
type: Array,
|
|
202
|
+
env_name: "FL_SAUCELABS_APPDIST_METRICS",
|
|
203
|
+
description: "Array of metrics to record (cpu,memory,network,phone_signal,gps,battery,mic,wifi)",
|
|
204
|
+
default_value: []),
|
|
205
|
+
FastlaneCore::ConfigItem.new(key: :comment,
|
|
206
|
+
optional: true,
|
|
207
|
+
env_name: "FL_SAUCELABS_APPDIST_COMMENT",
|
|
208
|
+
description: "Additional release notes for this upload. This text will be added to email notifications",
|
|
209
|
+
default_value: 'No comment provided'),
|
|
210
|
+
FastlaneCore::ConfigItem.new(key: :auto_update,
|
|
211
|
+
optional: true,
|
|
212
|
+
env_name: "FL_SAUCELABS_APPDIST_AUTO_UPDATE",
|
|
213
|
+
description: "Allows an easy upgrade of all users to the current version. To enable set to 'on'",
|
|
214
|
+
default_value: 'off'),
|
|
215
|
+
FastlaneCore::ConfigItem.new(key: :notify,
|
|
216
|
+
optional: true,
|
|
217
|
+
env_name: "FL_SAUCELABS_APPDIST_NOTIFY",
|
|
218
|
+
description: "Send email to testers",
|
|
219
|
+
default_value: 'off'),
|
|
220
|
+
FastlaneCore::ConfigItem.new(key: :options,
|
|
221
|
+
optional: true,
|
|
222
|
+
type: Array,
|
|
223
|
+
env_name: "FL_SAUCELABS_APPDIST_OPTIONS",
|
|
224
|
+
description: "Array of options (shake,video_only_wifi,anonymous)",
|
|
225
|
+
default_value: []),
|
|
226
|
+
FastlaneCore::ConfigItem.new(key: :custom,
|
|
227
|
+
optional: true,
|
|
228
|
+
env_name: "FL_SAUCELABS_APPDIST_CUSTOM",
|
|
229
|
+
description: "Array of custom options. Contact support for more information",
|
|
230
|
+
default_value: ''),
|
|
231
|
+
FastlaneCore::ConfigItem.new(key: :timeout,
|
|
232
|
+
env_name: "FL_SAUCELABS_APPDIST_TIMEOUT",
|
|
233
|
+
description: "Request timeout in seconds",
|
|
234
|
+
type: Integer,
|
|
235
|
+
optional: true),
|
|
236
|
+
FastlaneCore::ConfigItem.new(key: :tags,
|
|
237
|
+
optional: true,
|
|
238
|
+
env_name: "FL_SAUCELABS_APPDIST_TAGS",
|
|
239
|
+
description: "Custom tags that can be used to organize your builds",
|
|
240
|
+
type: Array,
|
|
241
|
+
default_value: []),
|
|
242
|
+
FastlaneCore::ConfigItem.new(key: :folder_name,
|
|
243
|
+
optional: true,
|
|
244
|
+
env_name: "FL_SAUCELABS_APPDIST_FOLDER_NAME",
|
|
245
|
+
description: "Name of the dashboard folder that contains this app",
|
|
246
|
+
default_value: ''),
|
|
247
|
+
FastlaneCore::ConfigItem.new(key: :landing_page_mode,
|
|
248
|
+
optional: true,
|
|
249
|
+
env_name: "FL_SAUCELABS_APPDIST_LANDING_PAGE_MODE",
|
|
250
|
+
description: "Visibility of build landing after upload. Can be 'open' or 'closed'",
|
|
251
|
+
default_value: 'open',
|
|
252
|
+
verify_block: proc do |value|
|
|
253
|
+
UI.user_error!("The landing page mode can only be open or closed") unless %w(open closed).include?(value)
|
|
254
|
+
end),
|
|
255
|
+
FastlaneCore::ConfigItem.new(key: :upload_to_saucelabs,
|
|
256
|
+
optional: true,
|
|
257
|
+
env_name: "FL_SAUCELABS_APPDIST_UPLOAD_TO_SAUCELABS",
|
|
258
|
+
description: "Upload file directly to Sauce Labs. It can be 'on' or 'off'",
|
|
259
|
+
default_value: 'off',
|
|
260
|
+
verify_block: proc do |value|
|
|
261
|
+
UI.user_error!("The upload to Sauce Labs can only be on or off") unless %w(on off).include?(value)
|
|
262
|
+
end),
|
|
263
|
+
FastlaneCore::ConfigItem.new(key: :platform,
|
|
264
|
+
optional: true,
|
|
265
|
+
env_name: "FL_SAUCELABS_APPDIST_PLATFORM",
|
|
266
|
+
description: "Use if upload build is not iOS or Android. Contact support for more information",
|
|
267
|
+
default_value: '')
|
|
268
|
+
]
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
def self.example_code
|
|
272
|
+
[
|
|
273
|
+
'saucelabs_appdist(
|
|
274
|
+
api_key: "...",
|
|
275
|
+
ipa: "./ipa_file.ipa",
|
|
276
|
+
comment: "Build #{lane_context[SharedValues::BUILD_NUMBER]}",
|
|
277
|
+
)',
|
|
278
|
+
'saucelabs_appdist(
|
|
279
|
+
api_key: "...",
|
|
280
|
+
apk: "../build/app/outputs/apk/qa/release/app-qa-release.apk",
|
|
281
|
+
comment: "Build #{lane_context[SharedValues::BUILD_NUMBER]}",
|
|
282
|
+
)'
|
|
283
|
+
]
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
def self.category
|
|
287
|
+
:beta
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
def self.output
|
|
291
|
+
[
|
|
292
|
+
['SAUCELABS_APPDIST_UPLOAD_RESPONSE', 'Full response from the upload API']
|
|
293
|
+
]
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
def self.authors
|
|
297
|
+
["Sauce Labs"]
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
def self.is_supported?(platform)
|
|
301
|
+
[:ios, :android].include?(platform)
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
end
|
|
305
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
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 SaucelabsAppdistHelper
|
|
8
|
+
def self.show_message
|
|
9
|
+
UI.message("Hello from the saucelabs_appdist plugin helper!")
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require 'fastlane/plugin/saucelabs_appdist/version'
|
|
2
|
+
|
|
3
|
+
module Fastlane
|
|
4
|
+
module SaucelabsAppdist
|
|
5
|
+
def self.all_classes
|
|
6
|
+
Dir[File.expand_path('**/{actions,helper}/*.rb', File.dirname(__FILE__))]
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
Fastlane::SaucelabsAppdist.all_classes.each do |current|
|
|
12
|
+
require current
|
|
13
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require 'fastlane/plugin/saucelabs_appdist/saucelabs_appdist'
|
metadata
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: fastlane-plugin-saucelabs_appdist
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.3.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Sauce Labs
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-02-19 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: faraday
|
|
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'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: faraday_middleware
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '1.0'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '1.0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: bundler
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ">="
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: fastlane
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '2.0'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '2.0'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: pry
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - ">="
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '0'
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - ">="
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '0'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: rake
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - ">="
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '0'
|
|
90
|
+
type: :development
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - ">="
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '0'
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: rspec
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - ">="
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '0'
|
|
104
|
+
type: :development
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - ">="
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: '0'
|
|
111
|
+
- !ruby/object:Gem::Dependency
|
|
112
|
+
name: rubocop
|
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
|
114
|
+
requirements:
|
|
115
|
+
- - '='
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: 1.50.2
|
|
118
|
+
type: :development
|
|
119
|
+
prerelease: false
|
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
+
requirements:
|
|
122
|
+
- - '='
|
|
123
|
+
- !ruby/object:Gem::Version
|
|
124
|
+
version: 1.50.2
|
|
125
|
+
description: A Sauce Labs fastlane plugin for uploading iOS and Android builds to
|
|
126
|
+
Mobile App Distribution.
|
|
127
|
+
email: mobileappdistribution@saucelabs.com
|
|
128
|
+
executables: []
|
|
129
|
+
extensions: []
|
|
130
|
+
extra_rdoc_files: []
|
|
131
|
+
files:
|
|
132
|
+
- LICENSE
|
|
133
|
+
- README.md
|
|
134
|
+
- lib/fastlane/plugin/saucelabs_appdist.rb
|
|
135
|
+
- lib/fastlane/plugin/saucelabs_appdist/actions/saucelabs_appdist_action.rb
|
|
136
|
+
- lib/fastlane/plugin/saucelabs_appdist/helper/saucelabs_appdist_helper.rb
|
|
137
|
+
- lib/fastlane/plugin/saucelabs_appdist/saucelabs_appdist.rb
|
|
138
|
+
- lib/fastlane/plugin/saucelabs_appdist/version.rb
|
|
139
|
+
homepage: https://saucelabs.com/products/mobile-testing/app-betas
|
|
140
|
+
licenses:
|
|
141
|
+
- MIT
|
|
142
|
+
metadata: {}
|
|
143
|
+
post_install_message:
|
|
144
|
+
rdoc_options: []
|
|
145
|
+
require_paths:
|
|
146
|
+
- lib
|
|
147
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
148
|
+
requirements:
|
|
149
|
+
- - ">="
|
|
150
|
+
- !ruby/object:Gem::Version
|
|
151
|
+
version: '2.6'
|
|
152
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
153
|
+
requirements:
|
|
154
|
+
- - ">="
|
|
155
|
+
- !ruby/object:Gem::Version
|
|
156
|
+
version: '0'
|
|
157
|
+
requirements: []
|
|
158
|
+
rubygems_version: 3.4.1
|
|
159
|
+
signing_key:
|
|
160
|
+
specification_version: 4
|
|
161
|
+
summary: Sauce Labs plugin for uploading builds to Mobile App Distribution
|
|
162
|
+
test_files: []
|