fastlane-plugin-testingbot 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 69119bf112788b514fc5b4a0b2eb3c24505f1f5b30cd2017355843ad8a844b47
4
+ data.tar.gz: 581d283e00ca2e607bb31d816f57fce730ab15dde7c406c4bbff998c31f2af23
5
+ SHA512:
6
+ metadata.gz: 89d617bbd6961baf8f8e82aa72502e7bd5ff2797c0ced4c53e196d4dd15f6bd14a31614f2b6bfc20195bc03f5e8c81a897b6c0e54e0025cfa48fc993f505476e
7
+ data.tar.gz: 19c19c0dc321c48939e2ba6342c4506e64b352127abd8c948df5a11190bf7e33594be57cfdc0f50884e69eff2362c70ac6dbb3056e10e13691532edf7a358f49
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 TestingBot
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,161 @@
1
+ # fastlane-plugin-testingbot
2
+
3
+ [![fastlane Plugin Badge](https://rawcdn.githack.com/fastlane/fastlane/master/fastlane/assets/plugin-badge.svg)](https://rubygems.org/gems/fastlane-plugin-testingbot)
4
+
5
+ A [_fastlane_](https://fastlane.tools) plugin that uploads your mobile app builds to [TestingBot Storage](https://testingbot.com/support/api#upload),
6
+ so they can be used for automated (App Automate) and manual (App Live) testing on TestingBot's real devices and emulators/simulators.
7
+
8
+ ## Getting Started
9
+
10
+ Add the plugin to your project:
11
+
12
+ ```bash
13
+ fastlane add_plugin testingbot
14
+ ```
15
+
16
+ This adds the plugin to your `fastlane/Pluginfile` and installs it. Commit the updated `Gemfile`, `Gemfile.lock`, and `fastlane/Pluginfile`.
17
+
18
+ ## Credentials
19
+
20
+ The plugin authenticates with your **TestingBot API Key** and **API Secret**, which you can find in your
21
+ [TestingBot account](https://testingbot.com/members/user/edit). The recommended way to provide them is via environment variables,
22
+ which the plugin picks up automatically:
23
+
24
+ ```bash
25
+ export TESTINGBOT_KEY="your-api-key"
26
+ export TESTINGBOT_SECRET="your-api-secret"
27
+ ```
28
+
29
+ ## Usage
30
+
31
+ ### Upload a local app file
32
+
33
+ ```ruby
34
+ upload_to_testingbot(
35
+ file_path: "./app/build/outputs/apk/debug/app-debug.apk"
36
+ )
37
+ ```
38
+
39
+ `file_path` is optional — if omitted, the plugin uses the output of a preceding `gym` (iOS `IPA_OUTPUT_PATH`) or
40
+ `gradle` (`GRADLE_APK_OUTPUT_PATH` / `GRADLE_AAB_OUTPUT_PATH`) action in the same lane:
41
+
42
+ ```ruby
43
+ gradle(task: "assembleDebug")
44
+ upload_to_testingbot # automatically uploads the freshly built APK
45
+ ```
46
+
47
+ Supported formats: `.apk` and `.aab` (Android), `.ipa` (iOS real devices), and `.zip` (iOS simulator builds).
48
+
49
+ ### Upload from a remote URL
50
+
51
+ Have TestingBot fetch the binary server-side instead of uploading bytes from the CI machine:
52
+
53
+ ```ruby
54
+ upload_to_testingbot(
55
+ remote_url: "https://example.com/MyApp.ipa"
56
+ )
57
+ ```
58
+
59
+ ### Replace a build in place (stable identifier)
60
+
61
+ Pass an existing `app_url` to overwrite the binary while keeping the same `tb://` identifier — useful when your test
62
+ configuration references a fixed id across CI runs:
63
+
64
+ ```ruby
65
+ upload_to_testingbot(
66
+ file_path: "./MyApp.ipa",
67
+ app_url: "tb://abc123"
68
+ )
69
+ ```
70
+
71
+ ## Output
72
+
73
+ On success the action returns the `tb://<appkey>` app URL and exposes it for downstream lanes/processes:
74
+
75
+ | Source | Value |
76
+ |---|---|
77
+ | return value | `tb://<appkey>` |
78
+ | `lane_context[SharedValues::TESTINGBOT_APP_URL]` | `tb://<appkey>` |
79
+ | `lane_context[SharedValues::TESTINGBOT_APP_KEY]` | `<appkey>` (scheme stripped) |
80
+ | `lane_context[SharedValues::TESTINGBOT_STORAGE_RESPONSE]` | full parsed JSON response |
81
+ | `ENV["TESTINGBOT_APP_URL"]` / `ENV["TESTINGBOT_APP_KEY"]` | same values, for external test processes |
82
+
83
+ Use the `tb://` app URL as the Appium `appium:app` (legacy `app`) capability when starting your test session, e.g.:
84
+
85
+ ```ruby
86
+ app = lane_context[SharedValues::TESTINGBOT_APP_URL]
87
+ # capabilities["appium:app"] = app
88
+ ```
89
+
90
+ > **Note:** Uploaded apps are automatically deleted by TestingBot after 62 days. For a long-lived, stable reference,
91
+ > re-upload using the `app_url` (replace) option so the `tb://` identifier stays the same.
92
+
93
+ ## Action options
94
+
95
+ | Option | Environment variable | Required | Description |
96
+ |---|---|---|---|
97
+ | `testingbot_key` | `TESTINGBOT_KEY` | yes | Your TestingBot API key |
98
+ | `testingbot_secret` | `TESTINGBOT_SECRET` | yes | Your TestingBot API secret |
99
+ | `file_path` | `TESTINGBOT_FILE_PATH` | no | Local app file to upload (auto-resolved from gym/gradle if omitted) |
100
+ | `remote_url` | `TESTINGBOT_REMOTE_URL` | no | Remote URL for TestingBot to fetch (mutually exclusive with `file_path`) |
101
+ | `app_url` | `TESTINGBOT_REPLACE_APP_URL` | no | Existing `tb://...` app to replace in place |
102
+
103
+ Run `fastlane action upload_to_testingbot` to see this list from the command line.
104
+
105
+ ## Run tests for this plugin
106
+
107
+ To run both the tests, and code style validation, run
108
+
109
+ ```bash
110
+ bundle install
111
+ bundle exec rake
112
+ ```
113
+
114
+ ## Releasing
115
+
116
+ Releases are published to [RubyGems.org](https://rubygems.org/gems/fastlane-plugin-testingbot) automatically by the
117
+ [`Publish gem`](.github/workflows/publish.yml) GitHub Action whenever a `v*` tag is pushed. It uses
118
+ [RubyGems Trusted Publishing](https://guides.rubygems.org/trusted-publishing/) (OIDC), so **no API key secret is stored**
119
+ — which is required because this gem sets `rubygems_mfa_required`.
120
+
121
+ **One-time setup on RubyGems.org** (per gem):
122
+
123
+ 1. Sign in to RubyGems.org and open **Trusted Publishers** (under your profile, or the gem's settings once it exists).
124
+ 2. Add a new GitHub Actions trusted publisher with:
125
+ - **Repository owner / name:** `testingbot/testingbot-fastlane-plugin`
126
+ - **Workflow filename:** `publish.yml`
127
+ - **Environment:** `rubygems.org`
128
+ For a brand-new gem that isn't on RubyGems yet, create it as a *pending* trusted publisher.
129
+
130
+ **To cut a release:**
131
+
132
+ ```bash
133
+ # bump VERSION in lib/fastlane/plugin/testingbot/version.rb first
134
+ git commit -am "Release v0.1.0"
135
+ git tag v0.1.0
136
+ git push origin main --tags
137
+ ```
138
+
139
+ The workflow runs the test suite + RuboCop, then builds and pushes the gem.
140
+
141
+ ## Contributing
142
+
143
+ Bug reports and pull requests are welcome. Please read [CONTRIBUTING.md](CONTRIBUTING.md) to get started, and note
144
+ that this project follows a [Code of Conduct](CODE_OF_CONDUCT.md). For security issues, follow the private process in
145
+ [SECURITY.md](SECURITY.md).
146
+
147
+ ## Issues and Feedback
148
+
149
+ For any other issues and feedback about this plugin, please submit it to this repository.
150
+
151
+ ## Using _fastlane_ Plugins
152
+
153
+ For more information about how the `fastlane` plugin system works, check out the [Plugins documentation](https://docs.fastlane.tools/plugins/create-plugin/).
154
+
155
+ ## About _fastlane_
156
+
157
+ _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).
158
+
159
+ ## License
160
+
161
+ MIT
@@ -0,0 +1,197 @@
1
+ require 'fastlane/action'
2
+ require_relative '../helper/testingbot_helper'
3
+
4
+ module Fastlane
5
+ module Actions
6
+ module SharedValues
7
+ TESTINGBOT_APP_URL ||= :TESTINGBOT_APP_URL
8
+ TESTINGBOT_APP_KEY ||= :TESTINGBOT_APP_KEY
9
+ TESTINGBOT_STORAGE_RESPONSE ||= :TESTINGBOT_STORAGE_RESPONSE
10
+ end
11
+
12
+ class UploadToTestingbotAction < Action
13
+ UPLOAD_API_PATH = '/v1/storage'.freeze
14
+ SUPPORTED_FILE_EXTENSIONS = %w[apk aab ipa zip].freeze
15
+
16
+ def self.run(params)
17
+ file_path, remote_url = resolve_source(params[:file_path], params[:remote_url])
18
+ validate_file_path!(file_path) if file_path
19
+
20
+ path = upload_path(params[:app_url])
21
+
22
+ UI.message("Uploading to TestingBot Storage #{file_path ? "(#{File.basename(file_path)})" : "from #{remote_url}"} ...")
23
+
24
+ response = Helper::TestingbotHelper.upload(
25
+ params[:testingbot_key],
26
+ params[:testingbot_secret],
27
+ path,
28
+ file_path: file_path,
29
+ remote_url: remote_url
30
+ )
31
+
32
+ publish_result(response)
33
+ end
34
+
35
+ # Decide what to upload, enforcing that exactly one source is used.
36
+ # An explicit remote_url takes precedence over the auto-resolved default file path.
37
+ def self.resolve_source(file_path, remote_url)
38
+ file_path = presence(file_path)
39
+ remote_url = presence(remote_url)
40
+
41
+ UI.user_error!('Provide either `file_path` or `remote_url`, not both.') if file_path && remote_url
42
+
43
+ file_path = presence(default_file_path) if file_path.nil? && remote_url.nil?
44
+
45
+ UI.user_error!('No app to upload. Provide `file_path` (a local .apk/.aab/.ipa/.zip) or `remote_url`.') if file_path.nil? && remote_url.nil?
46
+
47
+ [file_path, remote_url]
48
+ end
49
+
50
+ def self.publish_result(response)
51
+ app_url = response['app_url']
52
+ UI.user_error!("TestingBot did not return an app_url. Response: #{response}") if presence(app_url).nil?
53
+
54
+ app_key = strip_scheme(app_url)
55
+ Actions.lane_context[SharedValues::TESTINGBOT_APP_URL] = app_url
56
+ Actions.lane_context[SharedValues::TESTINGBOT_APP_KEY] = app_key
57
+ Actions.lane_context[SharedValues::TESTINGBOT_STORAGE_RESPONSE] = response
58
+ ENV['TESTINGBOT_APP_URL'] = app_url
59
+ ENV['TESTINGBOT_APP_KEY'] = app_key
60
+
61
+ UI.success("Successfully uploaded app to TestingBot: #{app_url}")
62
+ app_url
63
+ end
64
+
65
+ def self.upload_path(app_url)
66
+ return UPLOAD_API_PATH if presence(app_url).nil?
67
+
68
+ "#{UPLOAD_API_PATH}/#{strip_scheme(app_url)}"
69
+ end
70
+
71
+ # Strip only the leading "tb://" scheme, preserving any remaining path.
72
+ def self.strip_scheme(app_url)
73
+ app_url.to_s.sub(%r{\Atb://}, '')
74
+ end
75
+
76
+ # Resolve a sensible default app path from earlier build actions in the same lane.
77
+ def self.default_file_path
78
+ if Actions.lane_context[SharedValues::PLATFORM_NAME] == :ios
79
+ Actions.lane_context[SharedValues::IPA_OUTPUT_PATH]
80
+ else
81
+ Actions.lane_context[SharedValues::GRADLE_APK_OUTPUT_PATH] ||
82
+ Actions.lane_context[SharedValues::GRADLE_AAB_OUTPUT_PATH]
83
+ end
84
+ end
85
+
86
+ def self.validate_file_path!(file_path)
87
+ UI.user_error!("Couldn't find file at path '#{file_path}'") unless File.exist?(file_path)
88
+
89
+ extension = File.extname(file_path).delete('.').downcase
90
+ return if SUPPORTED_FILE_EXTENSIONS.include?(extension)
91
+
92
+ supported = SUPPORTED_FILE_EXTENSIONS.map { |ext| ".#{ext}" }.join(', ')
93
+ UI.user_error!("Unsupported file type '.#{extension}'. TestingBot supports: #{supported}")
94
+ end
95
+
96
+ def self.presence(value)
97
+ value.to_s.empty? ? nil : value
98
+ end
99
+
100
+ #####################################################
101
+ # @!group Documentation
102
+ #####################################################
103
+
104
+ def self.description
105
+ 'Uploads an app (.apk/.aab/.ipa/.zip) to TestingBot Storage'
106
+ end
107
+
108
+ def self.details
109
+ [
110
+ 'Uploads a local app file or a remote app URL to TestingBot Storage so it can be used in App Automate / App Live test runs.',
111
+ 'On success the returned `tb://<appkey>` identifier is stored in the lane context (`SharedValues::TESTINGBOT_APP_URL`) and in `ENV`, ready to be used as the Appium `appium:app` capability.',
112
+ 'Pass an existing `app_url` to replace the binary in place while keeping the same `tb://` identifier (handy for stable CI references).'
113
+ ].join("\n")
114
+ end
115
+
116
+ def self.authors
117
+ ['TestingBot']
118
+ end
119
+
120
+ def self.return_value
121
+ 'The TestingBot app_url of the uploaded app (e.g. "tb://abc123"). Also exposed via lane_context[SharedValues::TESTINGBOT_APP_URL] and ENV["TESTINGBOT_APP_URL"].'
122
+ end
123
+
124
+ def self.available_options
125
+ [
126
+ FastlaneCore::ConfigItem.new(key: :testingbot_key,
127
+ env_name: 'TESTINGBOT_KEY',
128
+ description: 'Your TestingBot API key (find it at https://testingbot.com/members/user/edit)',
129
+ sensitive: true,
130
+ optional: false,
131
+ type: String,
132
+ verify_block: proc do |value|
133
+ UI.user_error!('No TestingBot API key given, pass using `testingbot_key:` or the TESTINGBOT_KEY environment variable') if value.to_s.empty?
134
+ end),
135
+ FastlaneCore::ConfigItem.new(key: :testingbot_secret,
136
+ env_name: 'TESTINGBOT_SECRET',
137
+ description: 'Your TestingBot API secret (find it at https://testingbot.com/members/user/edit)',
138
+ sensitive: true,
139
+ optional: false,
140
+ type: String,
141
+ verify_block: proc do |value|
142
+ UI.user_error!('No TestingBot API secret given, pass using `testingbot_secret:` or the TESTINGBOT_SECRET environment variable') if value.to_s.empty?
143
+ end),
144
+ FastlaneCore::ConfigItem.new(key: :file_path,
145
+ env_name: 'TESTINGBOT_FILE_PATH',
146
+ description: 'Path to the local app file (.apk, .aab, .ipa or .zip) to upload. Defaults to the output of a preceding gym/gradle build',
147
+ optional: true,
148
+ type: String),
149
+ FastlaneCore::ConfigItem.new(key: :remote_url,
150
+ env_name: 'TESTINGBOT_REMOTE_URL',
151
+ description: 'A publicly accessible URL to the app file; TestingBot downloads it server-side (mutually exclusive with file_path)',
152
+ optional: true,
153
+ type: String),
154
+ FastlaneCore::ConfigItem.new(key: :app_url,
155
+ env_name: 'TESTINGBOT_REPLACE_APP_URL',
156
+ description: 'An existing TestingBot app_url (tb://...) to replace in place, keeping the same identifier',
157
+ optional: true,
158
+ type: String)
159
+ ]
160
+ end
161
+
162
+ def self.output
163
+ [
164
+ ['TESTINGBOT_APP_URL', 'The tb:// app_url of the uploaded app'],
165
+ ['TESTINGBOT_APP_KEY', 'The app key (app_url without the tb:// scheme)'],
166
+ ['TESTINGBOT_STORAGE_RESPONSE', 'The full parsed JSON response from TestingBot Storage']
167
+ ]
168
+ end
169
+
170
+ def self.category
171
+ :testing
172
+ end
173
+
174
+ def self.example_code
175
+ [
176
+ 'upload_to_testingbot(
177
+ testingbot_key: ENV["TESTINGBOT_KEY"],
178
+ testingbot_secret: ENV["TESTINGBOT_SECRET"],
179
+ file_path: "./app/build/outputs/apk/debug/app-debug.apk"
180
+ )',
181
+ 'upload_to_testingbot(
182
+ remote_url: "https://example.com/MyApp.ipa"
183
+ )',
184
+ '# Replace an existing build in place (keeps the same tb:// identifier)
185
+ upload_to_testingbot(
186
+ file_path: "./MyApp.ipa",
187
+ app_url: "tb://abc123"
188
+ )'
189
+ ]
190
+ end
191
+
192
+ def self.is_supported?(platform)
193
+ %i[ios android mac].include?(platform)
194
+ end
195
+ end
196
+ end
197
+ end
@@ -0,0 +1,68 @@
1
+ require 'fastlane_core/ui/ui'
2
+ require 'rest-client'
3
+ require 'json'
4
+
5
+ module Fastlane
6
+ UI = FastlaneCore::UI unless Fastlane.const_defined?(:UI)
7
+
8
+ module Helper
9
+ class TestingbotHelper
10
+ API_BASE_URL = 'https://api.testingbot.com'.freeze
11
+
12
+ # App binaries can be large; mirror the official TestingBot Ruby client's generous read timeout.
13
+ UPLOAD_TIMEOUT = 600
14
+ OPEN_TIMEOUT = 30
15
+
16
+ # Uploads (or replaces) an app on TestingBot Storage.
17
+ #
18
+ # @param key [String] TestingBot API key (used as the HTTP Basic auth username)
19
+ # @param secret [String] TestingBot API secret (used as the HTTP Basic auth password)
20
+ # @param path [String] the request path, e.g. "/v1/storage" or "/v1/storage/<appkey>"
21
+ # @param file_path [String, nil] a local app file to upload via multipart/form-data
22
+ # @param remote_url [String, nil] a publicly reachable URL for TestingBot to fetch server-side
23
+ # @return [Hash] the parsed JSON response, e.g. {"app_url" => "tb://<appkey>"}
24
+ def self.upload(key, secret, path, file_path: nil, remote_url: nil)
25
+ file = file_path ? File.new(file_path, 'rb') : nil
26
+ payload = file ? { multipart: true, file: file } : { url: remote_url }
27
+
28
+ response = RestClient::Request.execute(
29
+ method: :post,
30
+ url: "#{API_BASE_URL}#{path}",
31
+ user: key,
32
+ password: secret,
33
+ payload: payload,
34
+ headers: { 'User-Agent' => "fastlane-plugin-testingbot/#{Fastlane::Testingbot::VERSION}" },
35
+ timeout: UPLOAD_TIMEOUT,
36
+ open_timeout: OPEN_TIMEOUT
37
+ )
38
+
39
+ parse_success(response)
40
+ rescue RestClient::ExceptionWithResponse => e
41
+ UI.user_error!("App upload to TestingBot failed: #{error_reason(e.response)}")
42
+ rescue StandardError => e
43
+ UI.user_error!("App upload to TestingBot failed: #{e.message}")
44
+ ensure
45
+ file&.close
46
+ end
47
+
48
+ def self.parse_success(response)
49
+ body = parse_json(response.body)
50
+ UI.user_error!('App upload to TestingBot failed: could not parse the server response') unless body.is_a?(Hash)
51
+
52
+ body
53
+ end
54
+
55
+ def self.error_reason(response)
56
+ body = response ? parse_json(response.body) : nil
57
+ message = body.is_a?(Hash) && (body['error'] || body['message'])
58
+ message || (response && "HTTP #{response.code}") || 'unknown error'
59
+ end
60
+
61
+ def self.parse_json(raw)
62
+ JSON.parse(raw.to_s)
63
+ rescue JSON::ParserError
64
+ nil
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,5 @@
1
+ module Fastlane
2
+ module Testingbot
3
+ VERSION = '0.1.0'.freeze
4
+ end
5
+ end
@@ -0,0 +1,16 @@
1
+ require 'fastlane/plugin/testingbot/version'
2
+
3
+ module Fastlane
4
+ module Testingbot
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::Testingbot.all_classes.each do |current|
15
+ require current
16
+ end
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fastlane-plugin-testingbot
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - TestingBot
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-06-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rest-client
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 2.0.2
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '2.0'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 2.0.2
33
+ description:
34
+ email: info@testingbot.com
35
+ executables: []
36
+ extensions: []
37
+ extra_rdoc_files: []
38
+ files:
39
+ - LICENSE
40
+ - README.md
41
+ - lib/fastlane/plugin/testingbot.rb
42
+ - lib/fastlane/plugin/testingbot/actions/upload_to_testingbot_action.rb
43
+ - lib/fastlane/plugin/testingbot/helper/testingbot_helper.rb
44
+ - lib/fastlane/plugin/testingbot/version.rb
45
+ homepage: https://github.com/testingbot/testingbot-fastlane-plugin
46
+ licenses:
47
+ - MIT
48
+ metadata:
49
+ rubygems_mfa_required: 'true'
50
+ source_code_uri: https://github.com/testingbot/testingbot-fastlane-plugin
51
+ bug_tracker_uri: https://github.com/testingbot/testingbot-fastlane-plugin/issues
52
+ changelog_uri: https://github.com/testingbot/testingbot-fastlane-plugin/blob/main/CHANGELOG.md
53
+ post_install_message:
54
+ rdoc_options: []
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ requirements: []
68
+ rubygems_version: 3.5.3
69
+ signing_key:
70
+ specification_version: 4
71
+ summary: Uploads .apk/.aab/.ipa/.zip files to TestingBot Storage for mobile app testing
72
+ test_files: []