fastlane-plugin-firebase_app_distribution 0.8.1 → 0.9.0.pre.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_action.rb +146 -5
- data/lib/fastlane/plugin/firebase_app_distribution/helper/firebase_app_distribution_helper.rb +2 -2
- data/lib/fastlane/plugin/firebase_app_distribution/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 02dd5d9fe833cb902ea3f91b4124d4ba8ee7add6036e57da2cd16c6a79f7e503
|
4
|
+
data.tar.gz: b3c4d2740c8ab4a800554dae193068ffeea1d914f526005779be8792997a6d36
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 74bd1a05693eccb0c711208af34d8ae2d48bf3ed2cc623b754eb284c8337f6d78280583587e0ac5aaf892726ad9e266b160563eb8ae26df1fd4e4540b1c34dcc
|
7
|
+
data.tar.gz: d6de7b9d5154851e14ebba73a95ca98e2fab0bbf6895220715f5ee5ee089bb0cf4cdf5968f4d47b4c83b38dfcb7cde86228c250cfd68e1296e42685b0c1cc553
|
data/lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_action.rb
CHANGED
@@ -22,6 +22,8 @@ module Fastlane
|
|
22
22
|
DEFAULT_UPLOAD_TIMEOUT_SECONDS = 300
|
23
23
|
UPLOAD_MAX_POLLING_RETRIES = 60
|
24
24
|
UPLOAD_POLLING_INTERVAL_SECONDS = 5
|
25
|
+
TEST_MAX_POLLING_RETRIES = 25
|
26
|
+
TEST_POLLING_INTERVAL_SECONDS = 30
|
25
27
|
|
26
28
|
def self.run(params)
|
27
29
|
params.values # to validate all inputs before looking for the ipa/apk/aab
|
@@ -37,11 +39,13 @@ module Fastlane
|
|
37
39
|
binary_type = binary_type_from_path(binary_path)
|
38
40
|
|
39
41
|
# TODO(lkellogg): This sets the send timeout for all POST requests made by the client, but
|
40
|
-
#
|
42
|
+
# ideally the timeout should only apply to the binary upload
|
41
43
|
init_google_api_client(params[:debug], timeout)
|
42
44
|
authorization = get_authorization(params[:service_credentials_file], params[:firebase_cli_token], params[:service_credentials_json_data], params[:debug])
|
43
45
|
client = Google::Apis::FirebaseappdistributionV1::FirebaseAppDistributionService.new
|
44
46
|
client.authorization = authorization
|
47
|
+
alpha_client = Google::Apis::FirebaseappdistributionV1alpha::FirebaseAppDistributionService.new
|
48
|
+
alpha_client.authorization = authorization
|
45
49
|
|
46
50
|
# If binary is an AAB, get the AAB info for this app, which includes the integration state
|
47
51
|
# and certificate data
|
@@ -80,6 +84,16 @@ module Fastlane
|
|
80
84
|
release = update_release(client, release)
|
81
85
|
end
|
82
86
|
|
87
|
+
test_devices =
|
88
|
+
get_value_from_value_or_file(params[:test_devices], params[:test_devices_file])
|
89
|
+
if present?(test_devices)
|
90
|
+
UI.message("🤖 Starting automated tests.")
|
91
|
+
release_test = test_release(alpha_client, release, test_devices, params[:test_username], params[:test_password], params[:test_username_resource], params[:test_password_resource])
|
92
|
+
unless params[:test_async]
|
93
|
+
poll_test_finished(alpha_client, release_test.name)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
83
97
|
testers = get_value_from_value_or_file(params[:testers], params[:testers_file])
|
84
98
|
groups = get_value_from_value_or_file(params[:groups], params[:groups_file])
|
85
99
|
emails = string_to_array(testers)
|
@@ -260,7 +274,7 @@ module Fastlane
|
|
260
274
|
# it should return a long running operation object, so we make a
|
261
275
|
# standard http call instead and convert it to a long running object
|
262
276
|
# https://github.com/googleapis/google-api-ruby-client/blob/main/generated/google-apis-firebaseappdistribution_v1/lib/google/apis/firebaseappdistribution_v1/service.rb#L79
|
263
|
-
# TODO(kbolay) Prefer client.upload_medium
|
277
|
+
# TODO(kbolay): Prefer client.upload_medium
|
264
278
|
response = client.http(
|
265
279
|
:post,
|
266
280
|
"https://firebaseappdistribution.googleapis.com/upload/v1/#{app_name}/releases:upload",
|
@@ -318,6 +332,99 @@ module Fastlane
|
|
318
332
|
end
|
319
333
|
end
|
320
334
|
|
335
|
+
def self.test_release(alpha_client, release, test_devices, username = nil, password = nil, username_resource = nil, password_resource = nil)
|
336
|
+
if username_resource.nil? ^ password_resource.nil?
|
337
|
+
UI.user_error!("Username and password resource names for automated tests need to be specified together.")
|
338
|
+
end
|
339
|
+
field_hints = nil
|
340
|
+
if !username_resource.nil? && !password_resource.nil?
|
341
|
+
field_hints =
|
342
|
+
Google::Apis::FirebaseappdistributionV1alpha::GoogleFirebaseAppdistroV1alphaLoginCredentialFieldHints.new(
|
343
|
+
username_resource_name: username_resource,
|
344
|
+
password_resource_name: password_resource
|
345
|
+
)
|
346
|
+
end
|
347
|
+
|
348
|
+
if username.nil? ^ password.nil?
|
349
|
+
UI.user_error!("Username and password for automated tests need to be specified together.")
|
350
|
+
end
|
351
|
+
login_credential = nil
|
352
|
+
if !username.nil? && !password.nil?
|
353
|
+
login_credential =
|
354
|
+
Google::Apis::FirebaseappdistributionV1alpha::GoogleFirebaseAppdistroV1alphaLoginCredential.new(
|
355
|
+
username: username,
|
356
|
+
password: password,
|
357
|
+
field_hints: field_hints
|
358
|
+
)
|
359
|
+
else
|
360
|
+
unless field_hints.nil?
|
361
|
+
UI.user_error!("Must specify username and password for automated tests if resource names are set.")
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
device_executions = string_to_array(test_devices, ';').map do |td_string|
|
366
|
+
td_hash = parse_test_device_string(td_string)
|
367
|
+
Google::Apis::FirebaseappdistributionV1alpha::GoogleFirebaseAppdistroV1alphaDeviceExecution.new(
|
368
|
+
device: Google::Apis::FirebaseappdistributionV1alpha::GoogleFirebaseAppdistroV1alphaTestDevice.new(
|
369
|
+
model: td_hash['model'],
|
370
|
+
version: td_hash['version'],
|
371
|
+
orientation: td_hash['orientation'],
|
372
|
+
locale: td_hash['locale']
|
373
|
+
)
|
374
|
+
)
|
375
|
+
end
|
376
|
+
|
377
|
+
release_test =
|
378
|
+
Google::Apis::FirebaseappdistributionV1alpha::GoogleFirebaseAppdistroV1alphaReleaseTest.new(
|
379
|
+
login_credential: login_credential,
|
380
|
+
device_executions: device_executions
|
381
|
+
)
|
382
|
+
alpha_client.create_project_app_release_test(release.name, release_test)
|
383
|
+
rescue Google::Apis::Error => err
|
384
|
+
UI.crash!(err)
|
385
|
+
end
|
386
|
+
|
387
|
+
def self.poll_test_finished(alpha_client, release_test_name)
|
388
|
+
TEST_MAX_POLLING_RETRIES.times do
|
389
|
+
UI.message("⏳ Waiting for test(s) to complete…")
|
390
|
+
sleep(TEST_POLLING_INTERVAL_SECONDS)
|
391
|
+
release_test = alpha_client.get_project_app_release_test(release_test_name)
|
392
|
+
if release_test.device_executions.all? { |e| e.state == 'PASSED' }
|
393
|
+
UI.success("✅ Passed automated test(s).")
|
394
|
+
return
|
395
|
+
end
|
396
|
+
release_test.device_executions.each do |de|
|
397
|
+
case de.state
|
398
|
+
when 'PASSED', 'IN_PROGRESS'
|
399
|
+
next
|
400
|
+
when 'FAILED'
|
401
|
+
UI.test_failure!("Automated test failed for #{device_to_s(de.device)}: #{de.failed_reason}.")
|
402
|
+
when 'INCONCLUSIVE'
|
403
|
+
UI.test_failure!("Automated test inconclusive for #{device_to_s(de.device)}: #{de.inconclusive_reason}.")
|
404
|
+
else
|
405
|
+
UI.test_failure!("Unsupported automated test state for #{device_to_s(de.device)}: #{de.state}.")
|
406
|
+
end
|
407
|
+
end
|
408
|
+
end
|
409
|
+
UI.test_failure!("Tests are running longer than expected.")
|
410
|
+
end
|
411
|
+
|
412
|
+
def self.parse_test_device_string(td_string)
|
413
|
+
allowed_keys = %w[model version locale orientation]
|
414
|
+
key_value_pairs = td_string.split(',').map do |key_value_string|
|
415
|
+
key, value = key_value_string.split('=')
|
416
|
+
unless allowed_keys.include?(key)
|
417
|
+
UI.user_error!("Unrecognized key in test_devices. Can only contain keys #{allowed_keys.join(', ')}.")
|
418
|
+
end
|
419
|
+
[key, value]
|
420
|
+
end
|
421
|
+
Hash[key_value_pairs]
|
422
|
+
end
|
423
|
+
|
424
|
+
def self.device_to_s(device)
|
425
|
+
"#{device.model} (#{device.version}/#{device.orientation}/#{device.locale})"
|
426
|
+
end
|
427
|
+
|
321
428
|
def self.available_options
|
322
429
|
[
|
323
430
|
# iOS Specific
|
@@ -358,7 +465,7 @@ module Fastlane
|
|
358
465
|
FastlaneCore::ConfigItem.new(key: :firebase_cli_path,
|
359
466
|
deprecated: "This plugin no longer uses the Firebase CLI",
|
360
467
|
env_name: "FIREBASEAPPDISTRO_FIREBASE_CLI_PATH",
|
361
|
-
description: "
|
468
|
+
description: "Absolute path of the Firebase CLI command",
|
362
469
|
type: String),
|
363
470
|
FastlaneCore::ConfigItem.new(key: :debug,
|
364
471
|
description: "Print verbose debug output",
|
@@ -374,7 +481,7 @@ module Fastlane
|
|
374
481
|
type: Integer),
|
375
482
|
FastlaneCore::ConfigItem.new(key: :groups,
|
376
483
|
env_name: "FIREBASEAPPDISTRO_GROUPS",
|
377
|
-
description: "
|
484
|
+
description: "Group aliases used for distribution, separated by commas",
|
378
485
|
optional: true,
|
379
486
|
type: String),
|
380
487
|
FastlaneCore::ConfigItem.new(key: :groups_file,
|
@@ -403,6 +510,39 @@ module Fastlane
|
|
403
510
|
optional: true,
|
404
511
|
type: String),
|
405
512
|
|
513
|
+
# Release Testing
|
514
|
+
FastlaneCore::ConfigItem.new(key: :test_devices,
|
515
|
+
env_name: "FIREBASEAPPDISTRO_TEST_DEVICES",
|
516
|
+
description: "List of devices to run automated tests on, in the format 'model=<model-id>,version=<os-version-id>,locale=<locale>,orientation=<orientation>;model=<model-id>,...'. Run 'gcloud firebase test android|ios models list' to see available devices",
|
517
|
+
optional: true,
|
518
|
+
type: String),
|
519
|
+
FastlaneCore::ConfigItem.new(key: :test_devices_file,
|
520
|
+
env_name: "FIREBASEAPPDISTRO_TEST_DEVICES_FILE",
|
521
|
+
description: "Path to file containing a list of devices to run automated tests on, in the format 'model=<model-id>,version=<os-version-id>,locale=<locale>,orientation=<orientation>;model=<model-id>,...'. Run 'gcloud firebase test android|ios models list' to see available devices",
|
522
|
+
optional: true,
|
523
|
+
type: String),
|
524
|
+
FastlaneCore::ConfigItem.new(key: :test_username,
|
525
|
+
description: "Username for automatic login",
|
526
|
+
optional: true,
|
527
|
+
type: String),
|
528
|
+
FastlaneCore::ConfigItem.new(key: :test_password,
|
529
|
+
description: "Password for automatic login",
|
530
|
+
optional: true,
|
531
|
+
type: String),
|
532
|
+
FastlaneCore::ConfigItem.new(key: :test_username_resource,
|
533
|
+
description: "Resource name of the username field for automatic login",
|
534
|
+
optional: true,
|
535
|
+
type: String),
|
536
|
+
FastlaneCore::ConfigItem.new(key: :test_password_resource,
|
537
|
+
description: "Resource name of the password field for automatic login",
|
538
|
+
optional: true,
|
539
|
+
type: String),
|
540
|
+
FastlaneCore::ConfigItem.new(key: :test_async,
|
541
|
+
description: "Don't wait for automatic test results",
|
542
|
+
optional: false,
|
543
|
+
default_value: false,
|
544
|
+
type: Boolean),
|
545
|
+
|
406
546
|
# Auth
|
407
547
|
FastlaneCore::ConfigItem.new(key: :firebase_cli_token,
|
408
548
|
description: "Auth token generated using the Firebase CLI's login:ci command",
|
@@ -432,7 +572,8 @@ module Fastlane
|
|
432
572
|
<<-CODE
|
433
573
|
firebase_app_distribution(
|
434
574
|
app: "<your Firebase app ID>",
|
435
|
-
testers: "snatchev@google.com, rebeccahe@google.com"
|
575
|
+
testers: "snatchev@google.com, rebeccahe@google.com",
|
576
|
+
test_devices: "model=shiba,version=34,locale=en,orientation=portrait;model=b0q,version=33,locale=en,orientation=portrait",
|
436
577
|
)
|
437
578
|
CODE
|
438
579
|
]
|
data/lib/fastlane/plugin/firebase_app_distribution/helper/firebase_app_distribution_helper.rb
CHANGED
@@ -27,10 +27,10 @@ module Fastlane
|
|
27
27
|
|
28
28
|
# Returns the array representation of a string with trimmed comma
|
29
29
|
# seperated values.
|
30
|
-
def string_to_array(string)
|
30
|
+
def string_to_array(string, delimiter = ",")
|
31
31
|
return [] if string.nil?
|
32
32
|
# Strip string and then strip individual values
|
33
|
-
string.strip.split(
|
33
|
+
string.strip.split(delimiter).map(&:strip)
|
34
34
|
end
|
35
35
|
|
36
36
|
def parse_plist(path)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fastlane-plugin-firebase_app_distribution
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0.pre.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stefan Natchev
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2024-01-
|
13
|
+
date: 2024-01-29 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: google-apis-firebaseappdistribution_v1
|