Skip to content

Commit 2b6d80b

Browse files
committed
Merge remote-tracking branch 'origin/trunk' into fix/metadata-length
2 parents 8dea555 + d527f50 commit 2b6d80b

27 files changed

Lines changed: 5792 additions & 11 deletions

.rubocop.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ Metrics/ClassLength:
6767
Max: 300
6868

6969
Metrics/MethodLength:
70-
Max: 100
70+
Max: 150
7171

7272
Metrics/ModuleLength:
7373
Max: 300

CHANGELOG.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,30 @@
66

77
### Breaking Changes
88

9+
_None_
10+
11+
### New Features
12+
13+
_None_
14+
15+
### Bug Fixes
16+
17+
_None_
18+
19+
### Internal Changes
20+
21+
_None_
22+
23+
## 5.0.0
24+
25+
### Breaking Changes
26+
927
* Update the version of Ruby required from `2.6.4` to `2.7.4`. [#377]
1028

1129
### New Features
1230

1331
* Introduce new `ios_send_app_size_metrics` and `android_send_app_size_metrics` actions. [#364] [#365]
32+
* Add the ability to run Firebase Test Lab tests. [#355]
1433

1534
### Bug Fixes
1635

Gemfile.lock

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
PATH
22
remote: .
33
specs:
4-
fastlane-plugin-wpmreleasetoolkit (4.2.0)
4+
fastlane-plugin-wpmreleasetoolkit (5.0.0)
55
activesupport (~> 5)
66
bigdecimal (~> 1.4)
77
buildkit (~> 1.5)
88
chroma (= 0.2.0)
99
diffy (~> 3.3)
1010
git (~> 1.3)
11+
google-cloud-storage (~> 1.31)
1112
jsonlint (~> 0.3)
1213
nokogiri (~> 1.11)
1314
octokit (~> 4.18)
@@ -281,13 +282,13 @@ GEM
281282
naturally (2.2.1)
282283
netrc (0.11.0)
283284
no_proxy_fix (0.1.2)
284-
nokogiri (1.13.6)
285+
nokogiri (1.13.7)
285286
mini_portile2 (~> 2.8.0)
286287
racc (~> 1.4)
287288
octokit (4.21.0)
288289
faraday (>= 0.9)
289290
sawyer (~> 0.8.0, >= 0.5.3)
290-
oj (3.13.11)
291+
oj (3.13.17)
291292
open4 (1.3.4)
292293
optimist (3.0.1)
293294
options (2.3.2)
@@ -307,7 +308,7 @@ GEM
307308
racc (1.6.0)
308309
rainbow (3.0.0)
309310
rake (13.0.6)
310-
rake-compiler (1.1.9)
311+
rake-compiler (1.2.0)
311312
rake
312313
rchardet (1.8.0)
313314
regexp_parser (2.1.1)
@@ -437,4 +438,4 @@ DEPENDENCIES
437438
yard
438439

439440
BUNDLED WITH
440-
2.3.16
441+
2.3.9

fastlane-plugin-wpmreleasetoolkit.gemspec

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ Gem::Specification.new do |spec|
3838
spec.add_dependency 'progress_bar', '~> 1.3'
3939
spec.add_dependency 'rake', '>= 12.3', '< 14.0'
4040
spec.add_dependency 'rake-compiler', '~> 1.0'
41+
42+
# `google-cloud-storage` is required by fastlane, but we pin it in case it's not in the future
43+
spec.add_dependency 'google-cloud-storage', '~> 1.31'
44+
4145
# Some of the upstream code uses `BigDecimal.new` which version 2.0 of the
4246
# `bigdecimal` gem removed. Until we'll find the time to identify the
4347
# dependencies and see if we can move them to something compatible with

lib/fastlane/plugin/wpmreleasetoolkit.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
module Fastlane
44
module Wpmreleasetoolkit
5-
# Return all .rb files inside the "actions" and "helper" directory
5+
# Return all .rb files inside the "actions", "helper" and "models" directories
66
def self.all_classes
7-
Dir[File.expand_path('**/{actions,helper}/**/*.rb', File.dirname(__FILE__))]
7+
Dir[File.expand_path('**/{actions,helper,models}/**/*.rb', File.dirname(__FILE__))]
88
end
99
end
1010
end
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
require 'securerandom'
2+
3+
module Fastlane
4+
module Actions
5+
module SharedValues
6+
FIREBASE_TEST_RESULT = :FIREBASE_TEST_LOG_FILE
7+
FIREBASE_TEST_LOG_FILE_PATH = :FIREBASE_TEST_LOG_FILE_PATH
8+
end
9+
10+
class AndroidFirebaseTestAction < Action
11+
def self.run(params)
12+
validate_options(params)
13+
14+
UI.user_error!('You must be logged in to Firebase prior to calling this action. Use the `FirebaseLogin` Action to log in if needed') unless Fastlane::FirebaseAccount.authenticated?
15+
16+
# Log in to Firebase (and validate credentials)
17+
run_uuid = params[:test_run_id] || SecureRandom.uuid
18+
test_dir = params[:results_output_dir] || File.join(Dir.tmpdir(), run_uuid)
19+
20+
# Set up the log file and output directory
21+
FileUtils.mkdir_p(test_dir)
22+
Fastlane::Actions.lane_context[:FIREBASE_TEST_LOG_FILE_PATH] = File.join(test_dir, 'output.log')
23+
24+
device = Fastlane::FirebaseDevice.new(
25+
model: params[:model],
26+
version: params[:version],
27+
locale: params[:locale],
28+
orientation: params[:orientation]
29+
)
30+
31+
result = FirebaseTestRunner.run_tests(
32+
project_id: params[:project_id],
33+
apk_path: params[:apk_path],
34+
test_apk_path: params[:test_apk_path],
35+
device: device,
36+
type: params[:type]
37+
)
38+
39+
# Download all of the outputs from the job to the local machine
40+
FirebaseTestRunner.download_result_files(
41+
result: result,
42+
destination: test_dir,
43+
project_id: params[:project_id],
44+
key_file_path: params[:key_file]
45+
)
46+
47+
FastlaneCore::UI.test_failure! "Firebase Tests failed – more information can be found at #{result.more_details_url}" unless result.success?
48+
49+
UI.success 'Firebase Tests Complete'
50+
end
51+
52+
# Fastlane doesn't eagerly validate options for us, so we'll do it first to have control over
53+
# when they're evalutated.
54+
def self.validate_options(params)
55+
available_options
56+
.reject { |opt| opt.optional || !opt.default_value.nil? }
57+
.map(&:key)
58+
.each { |k| params[k] }
59+
end
60+
61+
#####################################################
62+
# @!group Documentation
63+
#####################################################
64+
65+
def self.description
66+
'Runs the specified tests in Firebase Test Lab'
67+
end
68+
69+
def self.details
70+
description
71+
end
72+
73+
def self.available_options
74+
[
75+
FastlaneCore::ConfigItem.new(
76+
key: :project_id,
77+
# `env_name` comes from the Google Cloud default: https://cloud.google.com/functions/docs/configuring/env-var
78+
env_name: 'GCP_PROJECT',
79+
description: 'The Project ID to test in',
80+
type: String
81+
),
82+
FastlaneCore::ConfigItem.new(
83+
key: :key_file,
84+
description: 'The key file used to authorize with Google Cloud',
85+
type: String,
86+
verify_block: proc do |value|
87+
UI.user_error!('The `:key_file` parameter is required') if value.empty?
88+
UI.user_error!("No Google Cloud Key file found at: #{value}") unless File.exist?(value)
89+
end
90+
),
91+
FastlaneCore::ConfigItem.new(
92+
key: :apk_path,
93+
description: 'Path to the application APK on the local machine',
94+
type: String,
95+
verify_block: proc do |value|
96+
UI.user_error!('The `:apk_path` parameter is required') if value.empty?
97+
UI.user_error!("Invalid application APK: #{value}") unless File.exist?(value)
98+
end
99+
),
100+
FastlaneCore::ConfigItem.new(
101+
key: :test_apk_path,
102+
description: 'Path to the test bundle APK on the local machine',
103+
type: String,
104+
verify_block: proc do |value|
105+
UI.user_error!('The `:test_apk_path` parameter is required') if value.empty?
106+
UI.user_error!("Invalid test APK: #{value}") unless File.exist?(value)
107+
end
108+
),
109+
FastlaneCore::ConfigItem.new(
110+
key: :model,
111+
description: 'The device model to use to run the test',
112+
type: String,
113+
verify_block: proc do |value|
114+
UI.user_error!('The `:model` parameter is required') if value.empty?
115+
FirebaseTestRunner.verify_has_gcloud_binary!
116+
model_names = Fastlane::FirebaseDevice.valid_model_names
117+
UI.user_error!("Invalid Model Name: #{value}. Valid Model Names: #{model_names}") unless model_names.include?(value)
118+
end
119+
),
120+
FastlaneCore::ConfigItem.new(
121+
key: :version,
122+
description: 'The Android version (API Level) to use to run the test',
123+
type: Integer,
124+
verify_block: proc do |value|
125+
FirebaseTestRunner.verify_has_gcloud_binary!
126+
version_numbers = Fastlane::FirebaseDevice.valid_version_numbers
127+
UI.user_error!("Invalid Version Number: #{value}. Valid Version Numbers: #{version_numbers}") unless version_numbers.include?(value)
128+
end
129+
),
130+
FastlaneCore::ConfigItem.new(
131+
key: :locale,
132+
description: 'The locale code to use when running the test',
133+
type: String,
134+
default_value: 'en',
135+
verify_block: proc do |value|
136+
FirebaseTestRunner.verify_has_gcloud_binary!
137+
locale_codes = Fastlane::FirebaseDevice.valid_locales
138+
UI.user_error!("Invalid Locale: #{value}. Valid Locales: #{locale_codes}") unless locale_codes.include?(value)
139+
end
140+
),
141+
FastlaneCore::ConfigItem.new(
142+
key: :orientation,
143+
description: 'Which orientation to run the device in',
144+
type: String,
145+
default_value: 'portrait',
146+
verify_block: proc do |value|
147+
orientations = Fastlane::FirebaseDevice.valid_orientations
148+
UI.user_error!("Invalid Orientation: #{value}. Valid Orientations: #{orientations}") unless orientations.include?(value)
149+
end
150+
),
151+
FastlaneCore::ConfigItem.new(
152+
key: :type,
153+
description: 'The type of test to run (e.g. `instrumentation` or `robo`)',
154+
type: String,
155+
default_value: 'instrumentation',
156+
verify_block: proc do |value|
157+
types = Fastlane::FirebaseTestRunner::VALID_TEST_TYPES
158+
UI.user_error!("Invalid Test Type: #{value}. Valid Types: #{types}") unless types.include?(value)
159+
end
160+
),
161+
FastlaneCore::ConfigItem.new(
162+
key: :test_run_id,
163+
description: 'A unique ID used to identify this test run',
164+
default_value_dynamic: true,
165+
optional: true,
166+
type: String
167+
),
168+
FastlaneCore::ConfigItem.new(
169+
key: :results_output_dir,
170+
description: 'The path to the folder where we will store the results of this test run',
171+
default_value_dynamic: true,
172+
optional: true,
173+
type: String
174+
),
175+
]
176+
end
177+
178+
def self.authors
179+
['Automattic']
180+
end
181+
182+
def self.is_supported?(platform)
183+
platform == :android
184+
end
185+
end
186+
end
187+
end

lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_send_app_size_metrics.rb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,6 @@ def self.details
152152
DETAILS
153153
end
154154

155-
# rubocop:disable Metrics/MethodLength
156155
def self.available_options
157156
[
158157
FastlaneCore::ConfigItem.new(
@@ -259,7 +258,6 @@ def self.available_options
259258
),
260259
]
261260
end
262-
# rubocop:enable Metrics/MethodLength
263261

264262
def self.return_type
265263
:integer
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
require 'securerandom'
2+
3+
module Fastlane
4+
module Actions
5+
class FirebaseLoginAction < Action
6+
def self.run(params)
7+
Fastlane::FirebaseAccount.activate_service_account_with_key_file(params[:key_file])
8+
end
9+
10+
#####################################################
11+
# @!group Documentation
12+
#####################################################
13+
def self.description
14+
'Logs the local machine into Google Cloud using the provided key file'
15+
end
16+
17+
def self.details
18+
description
19+
end
20+
21+
def self.available_options
22+
[
23+
FastlaneCore::ConfigItem.new(
24+
key: :key_file,
25+
description: 'The key file used to authorize with Google Cloud',
26+
type: String,
27+
verify_block: proc do |value|
28+
UI.user_error!('The `:key_file` parameter is required') if value.empty?
29+
UI.user_error!("No Google Cloud Key file found at: #{value}") unless File.exist?(value)
30+
end
31+
),
32+
]
33+
end
34+
35+
def self.authors
36+
['Automattic']
37+
end
38+
39+
def self.is_supported?(platform)
40+
true
41+
end
42+
end
43+
end
44+
end
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
module Fastlane
2+
class FirebaseAccount
3+
def self.activate_service_account_with_key_file(key_file_path)
4+
Fastlane::Actions.sh('gcloud', 'auth', 'activate-service-account', '--key-file', key_file_path)
5+
end
6+
7+
def self.authenticated?
8+
auth_status = JSON.parse(auth_status_data)
9+
auth_status.any? do |account|
10+
account['status'] == 'ACTIVE'
11+
end
12+
end
13+
14+
# Lookup the current account authentication status
15+
def self.auth_status_data
16+
Fastlane::Actions.sh('gcloud', 'auth', 'list', '--format', 'json', log: false)
17+
end
18+
end
19+
end

0 commit comments

Comments
 (0)