fastlane-plugin-firebase_test_lab_integration 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 0e260d2fc23322a548223c3223978d2dc18176ced470e6f5c4d075e0fd989042
4
+ data.tar.gz: 30f8dd8a641044d1a7606786abcff2669cd3b8d290aa3a9d5d27033ce88647a9
5
+ SHA512:
6
+ metadata.gz: 36fb0a792efd8e09f04ae2bbd8065c2e86ab348f1e0f54ef69a189dade7e4f357683d51f6772405cd247f39ff403d67e7c529317537bb8eb81eb4c29b397a967
7
+ data.tar.gz: 86d9eb62f35adb45f2b1036c5cf5ea389b5e3622c43cbf9974259468d0092423096596e0781bb0f3f8c34b9b85f85abdae25a50f75973daac2562b3f9f790acf
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2023 Cristian Boarna <cristian.boarna@gmail.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,256 @@
1
+ <div align="center">
2
+ <div>
3
+ <h1>Fastlane</h1>
4
+ <img alt="logo" src="./docs/images/firebase_test_lab_logo.png" width="100%">
5
+ </div>
6
+ <h2>
7
+ <a href="https://rubygems.org/gems/fastlane-plugin-firebase_test_lab_integration">
8
+ <img alt="fastlane Plugin Badge" src="https://rawcdn.githack.com/fastlane/fastlane/master/fastlane/assets/plugin-badge.svg">
9
+ </a>
10
+ <a href="https://github.com/crisboarna/fastlane-plugin-firebase_test_lab_integration/actions/workflows/push_main.yaml">
11
+ <img alt="github action workflow" src="https://github.com/crisboarna/fastlane-plugin-firebase_test_lab_integration/actions/workflows/push_main.yaml/badge.svg">
12
+ </a>
13
+ <a href="https://snyk.io/test/github/crisboarna/fastlane-plugin-firebase_test_lab_integration">
14
+ <img alt="snyk" src="https://snyk.io/test/github/crisboarna/fastlane-plugin-firebase_test_lab_integration/badge.svg?targetFile=Gemfile">
15
+ </a>
16
+ <a href="https://codecov.io/gh/crisboarna/fastlane-plugin-firebase_test_lab_integration">
17
+ <img alt="codecov" src="https://img.shields.io/codecov/c/github/crisboarna/fastlane-plugin-firebase_test_lab_integration.svg">
18
+ </a>
19
+ <a href="https://rubygems.org/gems/fastlane-plugin-firebase_test_lab_integration">
20
+ <img alt="npm" src="https://img.shields.io/gem/v/fastlane-plugin-firebase_test_lab_integration.svg">
21
+ </a>
22
+ <a href="http://opensource.org/licenses/MIT">
23
+ <img alt="license" src="https://img.shields.io/github/license/crisboarna/fastlane-plugin-firebase_test_lab_integration">
24
+ </a>
25
+ <a href="https://github.com/semantic-release/semantic-release">
26
+ <img alt="semantic-release" src="https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg?style=flat-square)">
27
+ </a>
28
+ <img src="https://badges.frapsoft.com/os/v1/open-source.svg?v=103">
29
+ <a href="https://github.com/crisboarna/fastlane-plugin-firebase_test_lab_integration">
30
+ <img alt="stars" src="https://img.shields.io/github/stars/crisboarna/fastlane-plugin-firebase_test_lab_integration.svg">
31
+ </a>
32
+ <a href="https://github.com/crisboarna/fastlane-plugin-firebase_test_lab_integration">
33
+ <img alt="issues" src="https://img.shields.io/github/issues/crisboarna/fastlane-plugin-firebase_test_lab_integration.svg">
34
+ </a>
35
+ <a href="https://github.com/crisboarna">
36
+ <img alt="madeby" src="https://img.shields.io/badge/made%20by-crisboarna-blue.svg" >
37
+ </a>
38
+ <a href="https://github.com/crisboarna/react-skillbars/pulls">
39
+ <img alt="prs" src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat">
40
+ </a>
41
+ <br/>
42
+ <br/>
43
+ </h2>
44
+ Comprehensive and easy to use fastlane plugin for Firebase Test Lab integration. Supports both Android and iOS.
45
+ <p align="center">
46
+ <a href="#features">Features</a> |
47
+ <a href="#getting-started">Getting Started</a> |
48
+ <a href="#installation">Installation</a> |
49
+ <a href="#issues-and-feedback">Issues &amp; Feedback</a> |
50
+ <a href="#troubleshooting">Troubleshooting</a> |
51
+ <a href="#contributing">Contributing</a> |
52
+ <a href="#license">License</a>
53
+ </p>
54
+ <img src="docs/images/run_android.gif" />
55
+ </div>
56
+
57
+ ## Features
58
+
59
+ 1. Supports both Android and iOS with consistent API
60
+ 2. No gem dependencies (no issues in the future with incompatibility with other gem versions)
61
+ 3. Expandable API (you can add your own parameters to the plugin that are passed to underlying `gcloud` command)
62
+ 4. Unit(80%+) & Integration tests on Firebase Test Lab for Android/iOS
63
+ 5. Post test results as a comment to Github PRs ([example PR](https://github.com/crisboarna/fastlane-plugin-firebase_test_lab_integration/pull/1))
64
+
65
+ This fastlane plugin includes the following actions:
66
+
67
+ | Action | Description | Supported Platforms |
68
+ |:-------------------------------------------------------------------------------------|:--------------------------------------------------|--------------------:|
69
+ | `firebase_test_lab_android` | Runs Firebase Test Lab for Android APK | android |
70
+ | `firebase_test_lab_ios` | Runs Firebase Test Lab for iOS XCTest ad XCUITest | ios |
71
+
72
+ ### Parameters
73
+
74
+ Here is the list of all existing parameters for the actions:
75
+
76
+ #### `firebase_test_lab_android`
77
+
78
+ | Key & Env Var | Description |
79
+ |------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------|
80
+ | `gcp_project` <br/> `FIREBASE_TEST_LAB_INTEGRATION_GCP_PROJECT` | Google Cloud Platform project ID |
81
+ | `gcp_key_file` <br/> `FIREBASE_TEST_LAB_INTEGRATION_GCP_KEY_FILE` | Google Cloud Platform authentication key file path |
82
+ | `gcloud_channel` <br/> `FIREBASE_TEST_LAB_INTEGRATION_GCP_CHANNEL` | If you use beta or alpha channel. Defaults to stable (alpha/beta) |
83
+ | `gcloud_results_bucket` <br/> `FIREBASE_TEST_LAB_INTEGRATION_GCP_RESULTS_BUCKET` | Name of Google Storage for Firebase Test Lab results bucket. Defaults to '`gcp_project`_firebase_testlab' |
84
+ | `gcloud_results_dir` <br/> `FIREBASE_TEST_LAB_INTEGRATION_GCP_RESULTS_DIR` | Name of Google Storage for Firebase Test Lab results directory. Defaults to firebase_test_lab_result_#{DateTime.now.strftime('%Y-%m-%d-%H:%M:%S')} |
85
+ | `results_download_dir` <br/> `FIREBASE_TEST_LAB_INTEGRATION_RESULTS_DOWNLOAD_DIR` | Target directory to download screenshots from Firebase. |
86
+ | `results_log_file_name` <br/> `FIREBASE_TEST_LAB_INTEGRATION_OUTPUT_LOG_FILE_NAME` | The filename to save the output results. Default: ./firebase_test_lab_integration.log |
87
+ | `timeout` <br/> `FIREBASE_TEST_LAB_INTEGRATION_TIMEOUT` | The max time this test execution can run before it is cancelled. Default: 5m (this value must be greater than or equal to 1m) |
88
+ | `type` <br/> `FIREBASE_TEST_LAB_INTEGRATION_TYPE` | The type of the test, one of: instrumentation, robo, game-loop, or xctest. |
89
+ | `quiet` <br/> `FIREBASE_TEST_LAB_INTEGRATION_QUIET` | Mutes all potentially sensitive `gcloud`, `gsutil` output |
90
+ | `app_path` <br/> `FIREBASE_TEST_LAB_INTEGRATION_APP_PATH` | The path to the app to be tested. |
91
+ | `app_path_test` <br/> `FIREBASE_TEST_LAB_INTEGRATION_APP_PATH_TEST` | The path for your Android test APK. If not present assuming robo test if no type parameter specified. |
92
+ | `devices` <br/>` | List of devices to test. Defaults to `{model: "redfin",version: "30",locale: "en_US",orientation: "portrait"}` |
93
+ | `github_owner` <br/> `GH_OWNER` | Github Owner name of the repo |
94
+ | `github_repository` <br/> `GH_REPOSITORY` | Github Repository name |
95
+ | `github_pr_number` <br/> `GH_PR_NUMBER` | Github Pull request number |
96
+ | `github_api_token` <br/> `GH_API_TOKEN` | GitHub API Token |
97
+ | `extra_options` <br/> `FIREBASE_TEST_LAB_INTEGRATION_EXTRA_OPTIONS` | Extra options that you may pass directly to the `gcloud` command. Default: empty string" |
98
+
99
+ #### `firebase_test_lab_android`
100
+
101
+ | Key & Env Var | Description |
102
+ |----------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
103
+ | `gcp_project` <br/> `FIREBASE_TEST_LAB_INTEGRATION_GCP_PROJECT` | Google Cloud Platform project ID |
104
+ | `gcp_key_file` <br/> `FIREBASE_TEST_LAB_INTEGRATION_GCP_KEY_FILE` | Google Cloud Platform authentication key file path |
105
+ | `gcloud_channel` <br/> `FIREBASE_TEST_LAB_INTEGRATION_GCP_CHANNEL` | If you use beta or alpha channel. Defaults to stable (alpha/beta) |
106
+ | `gcloud_results_bucket` <br/> `FIREBASE_TEST_LAB_INTEGRATION_GCP_RESULTS_BUCKET` | Name of Google Storage for Firebase Test Lab results bucket. Defaults to '`gcp_project`_firebase_testlab' |
107
+ | `gcloud_results_dir` <br/> `FIREBASE_TEST_LAB_INTEGRATION_GCP_RESULTS_DIR` | Name of Google Storage for Firebase Test Lab results directory |
108
+ | `results_download_dir` <br/> `FIREBASE_TEST_LAB_INTEGRATION_RESULTS_DOWNLOAD_DIR` | Target directory to download screenshots from Firebase. |
109
+ | `results_log_file_name` <br/> `FIREBASE_TEST_LAB_INTEGRATION_OUTPUT_LOG_FILE_NAME` | The filename to save the output results. Default: ./firebase_test_lab_integration.log |
110
+ | `timeout` <br/> `FIREBASE_TEST_LAB_INTEGRATION_TIMEOUT` | The max time this test execution can run before it is cancelled. Default: 5m (this value must be greater than or equal to 1m) |
111
+ | `type` <br/> `FIREBASE_TEST_LAB_INTEGRATION_TYPE` | The type of the test, one of: instrumentation, robo, game-loop, or xctest. |
112
+ | `quiet` <br/> `FIREBASE_TEST_LAB_INTEGRATION_QUIET` | Mutes all potentially sensitive `gcloud`, `gsutil` output. If you want to mute `gcloud firebase test` command as well pass `extra_options: --no-user-output-enabled`. |
113
+ | `app_path` <br/> `FIREBASE_TEST_LAB_INTEGRATION_APP_PATH` | The path to the app to be tested. |
114
+ | `devices` <br/>` | List of devices to test Defaults to `{model: "iphone13pro",version: "15.2",locale: "en_US",orientation: "portrait"}` |
115
+ | `github_owner` <br/> `GH_OWNER` | Github Owner name of the repo |
116
+ | `github_repository` <br/> `GH_REPOSITORY` | Github Repository name |
117
+ | `github_pr_number` <br/> `GH_PR_NUMBER` | Github Pull request number |
118
+ | `github_api_token` <br/> `GH_API_TOKEN` | GitHub API Token |
119
+ | `extra_options` <br/> `FIREBASE_TEST_LAB_INTEGRATION_EXTRA_OPTIONS` | Extra options that you may pass directly to the `gcloud` command allowing full customization of what is executed beyond provided parameters. Default: empty string" |
120
+
121
+ ## Getting Started
122
+ ### Step 1. Enable required Google Cloud API's
123
+ You need to grant the following two API's to your Google Cloud project:
124
+ - [Cloud Testing API](https://console.cloud.google.com/apis/library/testing.googleapis.com)
125
+ - [Cloud Tool Results API](https://console.cloud.google.com/apis/library/toolresults.googleapis.com)
126
+
127
+ ### Step 2. Create Google Cloud Service Account & Key
128
+ You need to create a Google Cloud Service Account with the *Editor* role and download the JSON key file.
129
+ - [Create Service Account](https://cloud.google.com/iam/docs/creating-managing-service-accounts)
130
+ - [Create Service Account Key](https://cloud.google.com/iam/docs/creating-managing-service-account-keys)
131
+ - [Grant Service Account Permissions](https://cloud.google.com/iam/docs/granting-roles-to-service-accounts)
132
+
133
+ ### Step 3. Add the Service Account Key to your project
134
+ Add the Service Account Key to your project by adding the following line to your `Fastfile`:
135
+ ```ruby
136
+ firebase_test_lab_android(
137
+ ...
138
+ gcp_key_file: "path/to/service_account_key.json"
139
+ ...
140
+ )
141
+ ```
142
+
143
+ ### Step 4. Add gcloud CLI in your environment
144
+ You need to add the gcloud CLI in your environment.
145
+ You can either install it manually or use prebuild actions available in your CI environment.
146
+
147
+ For example in `GitHub Actions` you can use the following action:
148
+ ```yaml
149
+ - name: Setup gcloud CLI
150
+ uses: google-github-actions/setup-gcloud@master
151
+ with:
152
+ version: 'latest'
153
+ service_account_key: ${{ secrets.GCP_SA_KEY }}
154
+ project_id: ${{ secrets.GCP_PROJECT_ID }}
155
+ ```
156
+
157
+ or manually follow steps below
158
+
159
+ - [Install gcloud CLI](https://cloud.google.com/sdk/docs/install-sdk)
160
+
161
+ ### Step 5. Enable billing for your Google Cloud project in Firebase
162
+ You need to upgrade from basic `Spark` plan in Firebase on your project to be able to use all the required API components for `Firebase Test Lab` (such as `Google Cloud Storage`)
163
+
164
+ ### Step 6. Add plugin to your project
165
+ This project is a [_fastlane_](https://github.com/fastlane/fastlane) plugin. To get started
166
+ with `fastlane-plugin-firebase_test_lab_integration`, add it to your project by running:
167
+
168
+ ```bash
169
+ fastlane add_plugin firebase_test_lab_integration
170
+ ```
171
+
172
+ ### Step 7. Find device model names
173
+ You can find the device model names as follows:
174
+
175
+ For Android `firebase_test_lab_android` command:
176
+ ```bash
177
+ gcloud firebase test android models list
178
+ ```
179
+ Alternatively you can see the list of devices [here](https://firebase.google.com/docs/test-lab/android/available-testing-devices)
180
+
181
+ For iOS `firebase_test_lab_ios` command:
182
+ ```bash
183
+ gcloud firebase test ios models list
184
+ ```
185
+ Alternatively you can see the list of devices [here](https://firebase.google.com/docs/test-lab/ios/available-testing-devices)
186
+
187
+ ## Installation
188
+
189
+ This project is a [_fastlane_](https://github.com/fastlane/fastlane) plugin. To get started with `fastlane-plugin-test_center`, add it to your project by running:
190
+
191
+ ```bash
192
+ fastlane add_plugin firebase_test_lab_integration
193
+ ```
194
+
195
+ ## Example
196
+
197
+ Check out the [example `Fastfile`](fastlane/Fastfile) to see how to use this plugin. Try it by cloning the repo,
198
+ running `bundle exec fastlane install_plugins` and `bundle exec fastlane test`.
199
+
200
+ ## Run tests for this plugin
201
+
202
+ To run both the tests, and code style validation, run
203
+
204
+ ```bash
205
+ bundle exec rake
206
+ ```
207
+
208
+ To automatically fix many of the styling issues, use
209
+
210
+ ```
211
+ bundle exec rubocop -a
212
+ ```
213
+
214
+ ## Issues and Feedback
215
+
216
+ For any other issues and feedback about this plugin, please submit it to this repository.
217
+
218
+ ## Troubleshooting
219
+
220
+ If you have trouble using plugins, check out
221
+ the [Plugins Troubleshooting](https://docs.fastlane.tools/plugins/plugins-troubleshooting/) guide.
222
+
223
+ ## Using _fastlane_ Plugins
224
+
225
+ For more information about how the `fastlane` plugin system works, check out
226
+ the [Plugins documentation](https://docs.fastlane.tools/plugins/create-plugin/).
227
+
228
+ ## About _fastlane_
229
+
230
+ _fastlane_ is the easiest way to automate beta deployments and releases for your iOS and Android apps. To learn more,
231
+ check out [fastlane.tools](https://fastlane.tools).
232
+
233
+ ## Contributing
234
+
235
+ 1. Clone repo and create a new branch:
236
+
237
+ ```shell
238
+ git checkout https://github.com/crisboarna/react-skillbars -b name_for_new_branch`.
239
+ ````
240
+
241
+ 2. Make changes and test
242
+ 3. Submit Pull Request with comprehensive description of changes
243
+
244
+ ## Bots used
245
+
246
+ To facilitate development the following bots are integrated into the repository:
247
+
248
+ 1. [Request Info](https://github.com/behaviorbot/request-info)
249
+ 2. [Semantic Pull Requests](https://github.com/apps/semantic-pull-requests)
250
+ 3. [Welcome](https://github.com/apps/welcome)
251
+ 4. [Snyk](https://github.com/marketplace/snyk)
252
+ 5. [Todo](https://github.com/apps/todo)
253
+ 6. [Codecov](https://github.com/apps/codecov)
254
+
255
+ ## Credits
256
+ Inspired from existing plugin with similar functionality for Android by @wasabeef.
@@ -0,0 +1,48 @@
1
+ require 'fastlane/action'
2
+ require 'fastlane_core/ui/ui'
3
+ require_relative '../helper/integration_helper'
4
+ require_relative '../helper/options'
5
+
6
+ module Fastlane
7
+ module Actions
8
+ class FirebaseTestLabAndroidAction < Action
9
+ # This method is called by fastlane integration as entrypoint of plugin action
10
+ # It is responsible for calling the actual action logic
11
+ # and handling any errors
12
+ #
13
+ # @param [Hash] options
14
+ def self.run(params)
15
+ FastlaneCore::UI.message("Starting Firebase Test Lab Integration for Android.")
16
+ integration_helper = ::FirebaseTestLabIntegration::Helper::IntegrationHelper.new(:android)
17
+ integration_helper.run(params)
18
+ FastlaneCore::UI.message("Completed Firebase Test Lab Integration for Android.")
19
+ end
20
+
21
+ # This method is called by fastlane to display plugin information
22
+ def self.description
23
+ ::FirebaseTestLabIntegration::Helper::Options.description("Android")
24
+ end
25
+
26
+ # This method is called by fastlane to display plugin authors
27
+ def self.authors
28
+ ::FirebaseTestLabIntegration::Helper::Options.authors
29
+ end
30
+
31
+ def self.return_value
32
+ # If your method provides a return value, you can describe here what it does
33
+ end
34
+
35
+ def self.details
36
+ ::FirebaseTestLabIntegration::Helper::Options.details
37
+ end
38
+
39
+ def self.available_options
40
+ ::FirebaseTestLabIntegration::Helper::Options.available_options_android
41
+ end
42
+
43
+ def self.is_supported?(platform)
44
+ [:android].include?(platform)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,48 @@
1
+ require 'fastlane/action'
2
+ require 'fastlane_core/ui/ui'
3
+ require_relative '../helper/integration_helper'
4
+ require_relative '../helper/options'
5
+
6
+ module Fastlane
7
+ module Actions
8
+ class FirebaseTestLabIosAction < Action
9
+ # This method is called by fastlane integration as entrypoint of plugin action
10
+ # It is responsible for calling the actual action logic
11
+ # and handling any errors
12
+ #
13
+ # @param [Hash] options
14
+ def self.run(params)
15
+ FastlaneCore::UI.message("Starting Firebase Test Lab Integration for iOS.")
16
+ integration_helper = ::FirebaseTestLabIntegration::Helper::IntegrationHelper.new(:ios)
17
+ integration_helper.run(params)
18
+ FastlaneCore::UI.message("Completed Firebase Test Lab Integration for iOS.")
19
+ end
20
+
21
+ # This method is called by fastlane to display plugin information
22
+ def self.description
23
+ ::FirebaseTestLabIntegration::Helper::Options.description("iOS")
24
+ end
25
+
26
+ # This method is called by fastlane to display plugin authors
27
+ def self.authors
28
+ ::FirebaseTestLabIntegration::Helper::Options.authors
29
+ end
30
+
31
+ def self.return_value
32
+ # If your method provides a return value, you can describe here what it does
33
+ end
34
+
35
+ def self.details
36
+ ::FirebaseTestLabIntegration::Helper::Options.details
37
+ end
38
+
39
+ def self.available_options
40
+ ::FirebaseTestLabIntegration::Helper::Options.available_options_ios
41
+ end
42
+
43
+ def self.is_supported?(platform)
44
+ [:ios].include?(platform)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,110 @@
1
+ require 'fastlane_core/ui/ui'
2
+ require 'fastlane/action'
3
+ require 'json'
4
+ require 'fileutils'
5
+
6
+ module FirebaseTestLabIntegration
7
+ module Helper
8
+ class GcloudHelper
9
+ attr_reader :results_bucket, :results_dir
10
+
11
+ def initialize(platform, project_id, gcloud_key_file, gcloud_channel, results_bucket, results_dir, log_file_name, download_dir, timeout, quiet)
12
+ @platform = platform
13
+ @project_id = project_id
14
+ @gcloud_key_file = gcloud_key_file
15
+ @gcloud_channel = gcloud_channel
16
+ @results_bucket = results_bucket || "#{project_id}_firebase_testlab"
17
+ @results_dir = results_dir
18
+ @log_file_name = log_file_name
19
+ @download_dir = download_dir
20
+ @timeout = timeout
21
+ @quiet = quiet
22
+
23
+ self.authenticate
24
+ end
25
+
26
+ # This method is one that perfroms the core action of running the test suite on Firebase Test Lab
27
+ def run_tests(type, app_path, app_path_test, devices, extra_options)
28
+ FastlaneCore::UI.message("Running tests.")
29
+ arguments = "#{"--type #{type} " unless type.nil?}" \
30
+ "#{"--app #{app_path} " unless app_path.nil?}" \
31
+ "#{"--test #{app_path_test} " unless app_path_test.nil?}" \
32
+ "#{devices.map { |d| "--device model=#{d[:model]},version=#{d[:version]},locale=#{d[:locale]},orientation=#{d[:orientation]} " }.join}" \
33
+ "--timeout #{@timeout} " \
34
+ "--results-bucket #{@results_bucket} " \
35
+ "--results-dir #{@results_dir} " \
36
+ "#{extra_options} " \
37
+ "--format=json 1>#{generate_directory(@log_file_name)}"
38
+ Fastlane::Action.sh("set +e; gcloud #{@gcloud_channel unless @gcloud_channel == 'stable'} firebase test #{@platform} run #{arguments}; set -e")
39
+ FastlaneCore::UI.message("Testing completed.")
40
+ end
41
+
42
+ # This method is one that perfroms the core action of downloading the test results from Firebase Test Lab that were uploaded to Google Cloud Storage
43
+ # It also sets results as public to be accessible from outside
44
+ # It also returns the URL to the results to be used in Github PR comment
45
+ def download_test_results
46
+ if @download_dir
47
+ FastlaneCore::UI.message("Fetch results from Firebase Test Lab results bucket")
48
+ json = JSON.parse(File.read(@log_file_name))
49
+ json.each do |status|
50
+ axis = status["axis_value"]
51
+ generate_directory("#{@download_dir}/#{axis}")
52
+ download_from_gc_storage("#{@results_bucket}/#{@results_dir}/#{axis}", @download_dir)
53
+ gcloud_storage_path_public("#{@results_bucket}/#{@results_dir}/#{axis}")
54
+ end
55
+ else
56
+ FastlaneCore::UI.message("Not fetching results from Firebase Test Lab results bucket")
57
+ end
58
+ end
59
+
60
+ def self.gcloud_result_bucket_url(bucket, dir)
61
+ "https://console.developers.google.com/storage/browser/#{bucket}/#{CGI.escape(dir)}"
62
+ end
63
+
64
+ def self.gcloud_bucket_object_url(bucket, path)
65
+ "https://storage.googleapis.com/#{bucket}/#{CGI.escape(path)}"
66
+ end
67
+
68
+ def self.firebase_test_lab_history_url(project_id)
69
+ "https://console.firebase.google.com/u/0/project/#{project_id}/testlab/histories/"
70
+ end
71
+
72
+ # Performs gcloud authentication and project setup
73
+ def authenticate
74
+ FastlaneCore::UI.message("Configuring GCP project.")
75
+ Fastlane::Action.sh("gcloud config set project #{@project_id}")
76
+ FastlaneCore::UI.message("Configured GCP project.")
77
+
78
+ FastlaneCore::UI.message("Authenticating with GCP.")
79
+ Fastlane::Action.sh("gcloud auth activate-service-account --key-file #{@gcloud_key_file} #{'--no-user-output-enabled' if @quiet}")
80
+ FastlaneCore::UI.message("Authenticated with GCP.")
81
+ end
82
+
83
+ # Generates results output directory for artifacts
84
+ def generate_directory(path)
85
+ dirname = File.dirname(path)
86
+ unless File.directory?(dirname)
87
+ FastlaneCore::UI.message("Creating output directory: #{dirname}.")
88
+ FileUtils.mkdir_p(dirname)
89
+ FastlaneCore::UI.message("Created output directory: #{dirname}.")
90
+ end
91
+ path
92
+ end
93
+
94
+ # Downloads artifacts from Google Cloud Storage
95
+ def download_from_gc_storage(bucket_and_path, copy_to)
96
+ FastlaneCore::UI.message("Copy from gs://#{bucket_and_path}")
97
+ Fastlane::Action.sh("gsutil -m #{'-q' if @quiet} cp -r gs://#{bucket_and_path} #{copy_to}")
98
+ end
99
+
100
+ # Sets Google Cloud Storage bucket object as public
101
+ def gcloud_storage_path_public(bucket_and_path)
102
+ FastlaneCore::UI.message("Set public for reading gs://#{bucket_and_path} ")
103
+ Fastlane::Action.sh("gsutil -m #{'-q' if @quiet} acl -r set public-read gs://#{bucket_and_path}")
104
+ end
105
+
106
+ private :generate_directory, :download_from_gc_storage, :gcloud_storage_path_public
107
+ private_instance_methods :authenticate
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,165 @@
1
+ require 'fastlane_core/ui/ui'
2
+ require 'json'
3
+ require_relative './gcloud_helper'
4
+
5
+ module FirebaseTestLabIntegration
6
+ module Helper
7
+ class GithubHelper
8
+ PASSED = 'Passed'
9
+ FAILED = 'Failed'
10
+ SKIPPED = 'Skipped'
11
+ INCONCLUSIVE = 'Inconclusive'
12
+
13
+ def initialize(owner, repository, api_token)
14
+ @owner = owner
15
+ @repository = repository
16
+ @api_token = api_token
17
+ end
18
+
19
+ def valid_params?(pr_number)
20
+ !@owner.nil? && !@owner.empty? && !@repository.nil? && !@repository.empty? && !pr_number.nil? && !pr_number.empty? && !@api_token.nil? && !@api_token.empty?
21
+ end
22
+
23
+ def fold_comments(github_pr_number, comment_prefix, summary)
24
+ res = get_comments(github_pr_number)
25
+ JSON.parse(res.body)
26
+ .select { |comment| comment["body"].start_with?(comment_prefix) }
27
+ .each do |comment|
28
+ body = "<details><summary>#{summary}</summary>\n\n#{comment['body']}\n\n</details>\n"
29
+ patch_comment(comment["id"], body)
30
+ end
31
+ end
32
+
33
+ def delete_comments(github_pr_number, comment_prefix)
34
+ FastlaneCore::UI.message("Deleting old Github comments.")
35
+ res = get_comments(github_pr_number)
36
+ JSON.parse(res.body)
37
+ .select { |comment| comment["body"].start_with?(comment_prefix) }
38
+ .each { |comment| delete_comment(comment["id"]) }
39
+ end
40
+
41
+ def get_comments(github_pr_number)
42
+ api_url = "https://api.github.com/repos/#{@owner}/#{@repository}/issues/#{github_pr_number}/comments"
43
+ FastlaneCore::UI.message("get comments #{api_url}")
44
+
45
+ uri = URI.parse(api_url)
46
+ req = Net::HTTP::Get.new(uri)
47
+ req["Content-Type"] = "application/json"
48
+ req["Authorization"] = "token #{@api_token}"
49
+
50
+ res = Net::HTTP.start(uri.hostname, uri.port, { use_ssl: uri.scheme = "https" }) { |http| http.request(req) }
51
+ FastlaneCore::UI.message("#{res.code}\n#{res.body}")
52
+
53
+ res
54
+ end
55
+
56
+ def put_comment(github_pr_number, body)
57
+ FastlaneCore::UI.message("Adding Github comments.")
58
+ api_url = "https://api.github.com/repos/#{@owner}/#{@repository}/issues/#{github_pr_number}/comments"
59
+ FastlaneCore::UI.message("put comment #{api_url}")
60
+
61
+ uri = URI.parse(api_url)
62
+ req = Net::HTTP::Post.new(uri)
63
+ req["Content-Type"] = "application/json"
64
+ req["Authorization"] = "token #{@api_token}"
65
+ req.body = { body: body }.to_json
66
+
67
+ res = Net::HTTP.start(uri.hostname, uri.port, { use_ssl: uri.scheme = "https" }) { |http| http.request(req) }
68
+ FastlaneCore::UI.message("#{res.code}\n#{res.body}")
69
+
70
+ res
71
+ end
72
+
73
+ def patch_comment(comment_id, body)
74
+ api_url = "https://api.github.com/repos/#{@owner}/#{@repository}/issues/comments/#{comment_id}"
75
+ FastlaneCore::UI.message("patch comment #{api_url}")
76
+
77
+ uri = URI.parse(api_url)
78
+ req = Net::HTTP::Patch.new(uri)
79
+ req["Content-Type"] = "application/json"
80
+ req["Authorization"] = "token #{@api_token}"
81
+ req.body = { body: body }.to_json
82
+
83
+ res = Net::HTTP.start(uri.hostname, uri.port, { use_ssl: uri.scheme = "https" }) { |http| http.request(req) }
84
+ FastlaneCore::UI.message("#{res.code}\n#{res.body}")
85
+
86
+ res
87
+ end
88
+
89
+ def delete_comment(comment_id)
90
+ api_url = "https://api.github.com/repos/#{@owner}/#{@repository}/issues/comments/#{comment_id}"
91
+ FastlaneCore::UI.message("Deleting Github comment #{api_url}")
92
+
93
+ uri = URI.parse(api_url)
94
+ req = Net::HTTP::Delete.new(uri)
95
+ req["Content-Type"] = "application/json"
96
+ req["Authorization"] = "token #{@api_token}"
97
+
98
+ res = Net::HTTP.start(uri.hostname, uri.port, { use_ssl: uri.scheme = "https" }) { |http| http.request(req) }
99
+ FastlaneCore::UI.message("#{res.code}\n#{res.body}")
100
+
101
+ res
102
+ end
103
+
104
+ def generate_comment_content(json, project_id, bucket, dir, platform, test_type)
105
+ prefix = "<img alt=\"#{platform}\" src=\"https://github.com/crisboarna/fastlane-plugin-firebase_test_lab_integration/blob/main/docs/images/firebase_test_lab_logo.png?raw=true\" width=\"65%\" loading=\"lazy\" />"
106
+ cells = json.map do |data|
107
+ axis = data["axis_value"]
108
+ device = split_device_name(axis)
109
+ outcome = data["outcome"]
110
+ status = "#{emoji_status(outcome)} #{outcome}"
111
+ message = data["test_details"]
112
+ logcat = "<a href=\"#{::FirebaseTestLabIntegration::Helper::GcloudHelper.gcloud_bucket_object_url(bucket, "#{dir}/#{axis}/logcat")}\" target=\"_blank\" >#{random_emoji_cat}</a>"
113
+ if platform == :android
114
+ if test_type == "robo"
115
+ sitemp = "<img src=\"#{::FirebaseTestLabIntegration::Helper::GcloudHelper.gcloud_bucket_object_url(bucket, "#{dir}/#{axis}/artifacts/sitemap.png")}\" height=\"64px\" loading=\"lazy\" target=\"_blank\" />"
116
+ else
117
+ sitemp = "--"
118
+ end
119
+ end
120
+
121
+ "| **#{device}** | #{status} | #{message} | #{logcat} | #{"#{sitemp} |" unless platform == 'ios'} |\n"
122
+ end.inject(&:+)
123
+ comment = <<~EOS
124
+ #{prefix}
125
+
126
+ ### Results
127
+ Firebase console: [#{project_id}](#{::FirebaseTestLabIntegration::Helper::GcloudHelper.firebase_test_lab_history_url(project_id)})#{' '}
128
+ Test results: [#{dir}](#{::FirebaseTestLabIntegration::Helper::GcloudHelper.gcloud_result_bucket_url(bucket, dir)})
129
+
130
+ | :iphone: Device | :thermometer: Status | :memo: Message | :eyes: Logcat | :japan: Sitemap |#{' '}
131
+ | --- | :---: | --- | :---: | :---: |
132
+ #{cells}
133
+ EOS
134
+ return prefix, comment
135
+ end
136
+
137
+ def split_device_name(axis_value)
138
+ # Sample Nexus6P-23-ja_JP-portrait
139
+ array = axis_value.split("-")
140
+ "#{array[0]} (API #{array[1]})"
141
+ end
142
+
143
+ def emoji_status(outcome)
144
+ return case outcome
145
+ when PASSED
146
+ ":tada:"
147
+ when FAILED
148
+ ":fire:"
149
+ when INCONCLUSIVE
150
+ ":warning:"
151
+ when SKIPPED
152
+ ":expressionless:"
153
+ else
154
+ ":question:"
155
+ end
156
+ end
157
+
158
+ def random_emoji_cat
159
+ %w(:smiley_cat: :smile_cat: :joy_cat: :heart_eyes_cat: :smirk_cat: :kissing_cat:).sample
160
+ end
161
+
162
+ private :split_device_name, :emoji_status, :random_emoji_cat
163
+ end
164
+ end
165
+ end
@@ -0,0 +1,50 @@
1
+ require 'fastlane_core/ui/ui'
2
+ require 'fileutils'
3
+ require_relative './gcloud_helper'
4
+ require_relative './github_helper'
5
+
6
+ module FirebaseTestLabIntegration
7
+ module Helper
8
+ class IntegrationHelper
9
+ def initialize(platform)
10
+ @platform = platform
11
+ end
12
+
13
+ # Performs the actual test run
14
+ def run(params)
15
+ gcloud_helper = ::FirebaseTestLabIntegration::Helper::GcloudHelper.new(@platform, params[:gcp_project], params[:gcp_key_file], params[:gcloud_channel], params[:gcloud_results_bucket], params[:gcloud_results_dir], params[:results_log_file_name], params[:results_download_dir], params[:timeout], params[:quiet])
16
+ gcloud_helper.run_tests(params[:type], params[:app_path], params[:app_path_test], params[:devices], params[:extra_options])
17
+ json = get_test_outcome(params[:results_log_file_name])
18
+ gcloud_helper.download_test_results
19
+ post_github_comment(json, gcloud_helper, params)
20
+ end
21
+
22
+ # Prints to terminal outcome of the test run
23
+ def get_test_outcome(log_file_name)
24
+ json = File.read(log_file_name)
25
+ FastlaneCore::UI.message("Test outcome: #{json}")
26
+ JSON.parse(json)
27
+ end
28
+
29
+ # Posts a comment to Github PR with the test results
30
+ def post_github_comment(json, gcloud_helper, params)
31
+ owner = params[:github_owner]
32
+ repository = params[:github_repository]
33
+ pr_number = params[:github_pr_number]
34
+ api_token = params[:github_api_token]
35
+ github_helper = ::FirebaseTestLabIntegration::Helper::GithubHelper.new(owner, repository, api_token)
36
+
37
+ if github_helper.valid_params?(pr_number)
38
+ FastlaneCore::UI.message("Adding Github comment.")
39
+ prefix, comment = github_helper.generate_comment_content(json, params[:gcp_project], gcloud_helper.results_bucket, gcloud_helper.results_dir, @platform, params[:type])
40
+ github_helper.delete_comments(pr_number, prefix)
41
+ github_helper.put_comment(pr_number, comment)
42
+ else
43
+ FastlaneCore::UI.message("Skipping Github commenting.")
44
+ end
45
+ end
46
+
47
+ private :get_test_outcome, :post_github_comment
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,235 @@
1
+ require 'fastlane_core/ui/ui'
2
+ require 'fastlane_core/configuration/config_item'
3
+
4
+ module FirebaseTestLabIntegration
5
+ module Helper
6
+ class Options
7
+ def self.description(platform)
8
+ "Run #{platform} integration tests on Firebase Test Lab"
9
+ end
10
+
11
+ def self.details
12
+ "Test your app on Firebase Test Lab with ease using fastlane"
13
+ end
14
+
15
+ def self.authors
16
+ ["Cristian Boarna"]
17
+ end
18
+
19
+ def self.available_options_common
20
+ [
21
+ FastlaneCore::ConfigItem.new(
22
+ key: :gcp_project,
23
+ description: "Google Cloud Platform project ID",
24
+ optional: false,
25
+ type: String,
26
+ env_name: "FIREBASE_TEST_LAB_INTEGRATION_GCP_PROJECT"
27
+ ),
28
+ FastlaneCore::ConfigItem.new(
29
+ key: :gcp_key_file,
30
+ description: "Google Cloud Platform authentication key file path",
31
+ optional: false,
32
+ type: String,
33
+ env_name: "FIREBASE_TEST_LAB_INTEGRATION_GCP_KEY_FILE"
34
+ ),
35
+ FastlaneCore::ConfigItem.new(
36
+ key: :gcloud_channel,
37
+ description: "If you use beta or alpha channel. Defaults to stable (alpha/beta)",
38
+ optional: true,
39
+ type: String,
40
+ env_name: "FIREBASE_TEST_LAB_INTEGRATION_GCP_CHANNEL",
41
+ default_value: "stable"
42
+ ),
43
+ FastlaneCore::ConfigItem.new(
44
+ key: :gcloud_results_bucket,
45
+ description: "Name of Google Storage for Firebase Test Lab results bucket. Defaults to '`gcp_project`_firebase_testlab'",
46
+ optional: true,
47
+ type: String,
48
+ env_name: "FIREBASE_TEST_LAB_INTEGRATION_GCP_RESULTS_BUCKET",
49
+ default_value: nil
50
+ ),
51
+ FastlaneCore::ConfigItem.new(
52
+ key: :gcloud_results_dir,
53
+ description: "Name of Google Storage for Firebase Test Lab results directory",
54
+ optional: true,
55
+ type: String,
56
+ env_name: "FIREBASE_TEST_LAB_INTEGRATION_GCP_RESULTS_DIR",
57
+ default_value: "firebase_test_lab_result_#{DateTime.now.strftime('%Y-%m-%d-%H:%M:%S')}"
58
+ ),
59
+ FastlaneCore::ConfigItem.new(
60
+ key: :timeout,
61
+ description: "The max time this test execution can run before it is cancelled. Default: 5m (this value must be greater than or equal to 1m)",
62
+ optional: true,
63
+ type: String,
64
+ env_name: "FIREBASE_TEST_LAB_INTEGRATION_TIMEOUT",
65
+ default_value: "5m"
66
+ ),
67
+ FastlaneCore::ConfigItem.new(
68
+ key: :quiet,
69
+ description: "Mutes all potentially sensitive `gcloud`, `gsutil` output",
70
+ optional: true,
71
+ env_name: "FIREBASE_TEST_LAB_INTEGRATION_QUIET",
72
+ default_value: false,
73
+ is_string: false
74
+ ),
75
+ FastlaneCore::ConfigItem.new(
76
+ key: :app_path_test,
77
+ env_name: "FIREBASE_TEST_LAB_INTEGRATION_APP_PATH_TEST",
78
+ description: "The path for your Android test APK. If not present assuming robo test",
79
+ type: String,
80
+ optional: true,
81
+ default_value: nil
82
+ ),
83
+ FastlaneCore::ConfigItem.new(
84
+ key: :type,
85
+ env_name: "FIREBASE_TEST_LAB_INTEGRATION_TYPE",
86
+ description: "The type of the test, one of: instrumentation, robo, game-loop, or xctest. Default: depends on platform",
87
+ type: String,
88
+ optional: true,
89
+ verify_block: proc do |value|
90
+ if !value.nil? && value != "robo" && value != "instrumentation" && value != "game-loop" && value != "xctest"
91
+ FastlaneCore::UI.user_error!("Only robo, instrumentation, xctest and game-loop are supported")
92
+ end
93
+ end
94
+ ),
95
+ FastlaneCore::ConfigItem.new(
96
+ key: :results_download_dir,
97
+ description: "Target directory to download screenshots from Firebase",
98
+ optional: true,
99
+ type: String,
100
+ env_name: "FIREBASE_TEST_LAB_INTEGRATION_RESULTS_DOWNLOAD_DIR",
101
+ default_value: nil
102
+ ),
103
+ FastlaneCore::ConfigItem.new(
104
+ key: :results_log_file_name,
105
+ description: "The filename to save the output results. Default: ./firebase_test_lab_integration.log",
106
+ optional: true,
107
+ type: String,
108
+ env_name: "FIREBASE_TEST_LAB_INTEGRATION_OUTPUT_LOG_FILE_NAME",
109
+ default_value: "./firebase_test_lab_integration.log"
110
+ ),
111
+ FastlaneCore::ConfigItem.new(
112
+ key: :github_owner,
113
+ description: "Github Owner name of the repo",
114
+ optional: true,
115
+ type: String,
116
+ env_name: "GH_OWNER",
117
+ default_value: nil
118
+ ),
119
+ FastlaneCore::ConfigItem.new(
120
+ key: :github_repository,
121
+ description: "Github Repository name",
122
+ optional: true,
123
+ type: String,
124
+ env_name: "GH_REPOSITORY",
125
+ default_value: nil
126
+ ),
127
+ FastlaneCore::ConfigItem.new(
128
+ key: :github_pr_number,
129
+ description: "Github Pull request number",
130
+ optional: true,
131
+ type: String,
132
+ env_name: "GH_PR_NUMBER",
133
+ default_value: nil
134
+ ),
135
+ FastlaneCore::ConfigItem.new(
136
+ key: :github_api_token,
137
+ description: "GitHub API Token",
138
+ optional: true,
139
+ type: String,
140
+ env_name: "GH_API_TOKEN",
141
+ default_value: nil
142
+ ),
143
+ FastlaneCore::ConfigItem.new(
144
+ key: :extra_options,
145
+ description: "Extra options that you may pass directly to the `gcloud` command. Default: empty string",
146
+ optional: true,
147
+ type: String,
148
+ env_name: "FIREBASE_TEST_LAB_INTEGRATION_EXTRA_OPTIONS",
149
+ default_value: ""
150
+ )
151
+ ]
152
+ end
153
+
154
+ def self.available_options_android
155
+ self.available_options_common + [
156
+ FastlaneCore::ConfigItem.new(
157
+ key: :app_path,
158
+ env_name: "FIREBASE_TEST_LAB_INTEGRATION_APP_PATH",
159
+ description: "The path to the app to be tested",
160
+ type: String,
161
+ optional: false
162
+ ),
163
+ FastlaneCore::ConfigItem.new(
164
+ key: :devices,
165
+ description: "Devices to test the app on",
166
+ optional: true,
167
+ type: Array,
168
+ default_value: [{
169
+ model: "redfin",
170
+ version: "30",
171
+ locale: "en_US",
172
+ orientation: "portrait"
173
+ }],
174
+ verify_block: proc do |value|
175
+ verify_devices(value)
176
+ end
177
+ )
178
+ ]
179
+ end
180
+
181
+ def self.available_options_ios
182
+ self.available_options_common + [
183
+ FastlaneCore::ConfigItem.new(
184
+ key: :app_path,
185
+ env_name: "FIREBASE_TEST_LAB_INTEGRATION_APP_PATH",
186
+ description: "The path to the app to be tested",
187
+ type: String,
188
+ optional: true
189
+ ),
190
+ FastlaneCore::ConfigItem.new(
191
+ key: :devices,
192
+ description: "Devices to test the app on",
193
+ optional: true,
194
+ type: Array,
195
+ default_value: [{
196
+ model: "iphone13pro",
197
+ version: "15.2",
198
+ locale: "en_US",
199
+ orientation: "portrait"
200
+ }],
201
+ verify_block: proc do |value|
202
+ verify_devices(value)
203
+ end
204
+ )
205
+ ]
206
+ end
207
+
208
+ def self.verify_devices(value)
209
+ if value.empty?
210
+ FastlaneCore::UI.user_error!("Devices cannot be empty")
211
+ end
212
+ value.each do |current|
213
+ if current.class != Hash
214
+ FastlaneCore::UI.user_error!("Each device must be represented by a Hash object, " \
215
+ "#{current.class} found")
216
+ end
217
+ check_has_property(current, :model)
218
+ check_has_property(current, :version)
219
+ set_default_property(current, :locale, "en_US")
220
+ set_default_property(current, :orientation, "portrait")
221
+ end
222
+ end
223
+
224
+ def self.check_has_property(hash_obj, property)
225
+ FastlaneCore::UI.user_error!("Each device must have #{property} property") unless hash_obj.key?(property)
226
+ end
227
+
228
+ def self.set_default_property(hash_obj, property, default)
229
+ unless hash_obj.key?(property)
230
+ hash_obj[property] = default
231
+ end
232
+ end
233
+ end
234
+ end
235
+ end
@@ -0,0 +1,5 @@
1
+ module Fastlane
2
+ module FirebaseTestLabIntegration
3
+ VERSION = "1.0.0"
4
+ end
5
+ end
@@ -0,0 +1,16 @@
1
+ require 'fastlane/plugin/firebase_test_lab_integration/version'
2
+
3
+ module Fastlane
4
+ module FirebaseTestLabIntegration
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::FirebaseTestLabIntegration.all_classes.each do |current|
15
+ require current
16
+ end
metadata ADDED
@@ -0,0 +1,291 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fastlane-plugin-firebase_test_lab_integration
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Cristian Boarna
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-01-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: dotenv
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: fastlane
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 2.211.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 2.211.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: pre-commit
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '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: rspec_junit_formatter
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rspec-mocks
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: rubocop
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - '='
144
+ - !ruby/object:Gem::Version
145
+ version: 1.43.0
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - '='
151
+ - !ruby/object:Gem::Version
152
+ version: 1.43.0
153
+ - !ruby/object:Gem::Dependency
154
+ name: rubocop-performance
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: rubocop-rake
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: rubocop-require_tools
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
195
+ - !ruby/object:Gem::Dependency
196
+ name: rubocop-rspec
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
209
+ - !ruby/object:Gem::Dependency
210
+ name: simplecov
211
+ requirement: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - ">="
214
+ - !ruby/object:Gem::Version
215
+ version: '0'
216
+ type: :development
217
+ prerelease: false
218
+ version_requirements: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - ">="
221
+ - !ruby/object:Gem::Version
222
+ version: '0'
223
+ - !ruby/object:Gem::Dependency
224
+ name: simplecov-html
225
+ requirement: !ruby/object:Gem::Requirement
226
+ requirements:
227
+ - - ">="
228
+ - !ruby/object:Gem::Version
229
+ version: '0'
230
+ type: :development
231
+ prerelease: false
232
+ version_requirements: !ruby/object:Gem::Requirement
233
+ requirements:
234
+ - - ">="
235
+ - !ruby/object:Gem::Version
236
+ version: '0'
237
+ - !ruby/object:Gem::Dependency
238
+ name: simplecov-lcov
239
+ requirement: !ruby/object:Gem::Requirement
240
+ requirements:
241
+ - - ">="
242
+ - !ruby/object:Gem::Version
243
+ version: '0'
244
+ type: :development
245
+ prerelease: false
246
+ version_requirements: !ruby/object:Gem::Requirement
247
+ requirements:
248
+ - - ">="
249
+ - !ruby/object:Gem::Version
250
+ version: '0'
251
+ description:
252
+ email: cristian.boarna@gmail.com
253
+ executables: []
254
+ extensions: []
255
+ extra_rdoc_files: []
256
+ files:
257
+ - LICENSE
258
+ - README.md
259
+ - lib/fastlane/plugin/firebase_test_lab_integration.rb
260
+ - lib/fastlane/plugin/firebase_test_lab_integration/actions/firebase_test_lab_android.rb
261
+ - lib/fastlane/plugin/firebase_test_lab_integration/actions/firebase_test_lab_ios.rb
262
+ - lib/fastlane/plugin/firebase_test_lab_integration/helper/gcloud_helper.rb
263
+ - lib/fastlane/plugin/firebase_test_lab_integration/helper/github_helper.rb
264
+ - lib/fastlane/plugin/firebase_test_lab_integration/helper/integration_helper.rb
265
+ - lib/fastlane/plugin/firebase_test_lab_integration/helper/options.rb
266
+ - lib/fastlane/plugin/firebase_test_lab_integration/version.rb
267
+ homepage: https://github.com/crisboarna/fastlane-plugin-firebase_test_lab_integration
268
+ licenses:
269
+ - MIT
270
+ metadata:
271
+ rubygems_mfa_required: 'true'
272
+ post_install_message:
273
+ rdoc_options: []
274
+ require_paths:
275
+ - lib
276
+ required_ruby_version: !ruby/object:Gem::Requirement
277
+ requirements:
278
+ - - ">="
279
+ - !ruby/object:Gem::Version
280
+ version: '2.6'
281
+ required_rubygems_version: !ruby/object:Gem::Requirement
282
+ requirements:
283
+ - - ">="
284
+ - !ruby/object:Gem::Version
285
+ version: '0'
286
+ requirements: []
287
+ rubygems_version: 3.0.3.1
288
+ signing_key:
289
+ specification_version: 4
290
+ summary: Run Android/iOS integration tests on Firebase Test Lab
291
+ test_files: []