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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7e6ae8a63559822e0869de05d3b6239991ef11e137cfcaab8632bfcb5ebc131b
4
- data.tar.gz: b4cc1e7840dc3a8a4b42bfeafa0da86d2ef6c6d2520dec19d1ac00bcb85a93f8
3
+ metadata.gz: 02dd5d9fe833cb902ea3f91b4124d4ba8ee7add6036e57da2cd16c6a79f7e503
4
+ data.tar.gz: b3c4d2740c8ab4a800554dae193068ffeea1d914f526005779be8792997a6d36
5
5
  SHA512:
6
- metadata.gz: c0ad2e974069de4be2bf38ca52f0d4c8d2a5569bb2e2673332207be9d417dd8aaf779bddf34ee04eb8b78e612a26d02a5c74668be6fc590b06470c60274a6f3d
7
- data.tar.gz: 50bd7ff6e1fef81db8a695f5e3c6239c0170842efb0db85c0e025f9362c5b47ded84b555718cfb661e14952c44725b33fb9af2f49a6321e7e5e1cd546f9806f9
6
+ metadata.gz: 74bd1a05693eccb0c711208af34d8ae2d48bf3ed2cc623b754eb284c8337f6d78280583587e0ac5aaf892726ad9e266b160563eb8ae26df1fd4e4540b1c34dcc
7
+ data.tar.gz: d6de7b9d5154851e14ebba73a95ca98e2fab0bbf6895220715f5ee5ee089bb0cf4cdf5968f4d47b4c83b38dfcb7cde86228c250cfd68e1296e42685b0c1cc553
@@ -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
- # ideally the timeout should only apply to the binary upload
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: "The absolute path of the firebase cli command",
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: "The group aliases used for distribution, separated by commas",
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
  ]
@@ -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(",").map(&:strip)
33
+ string.strip.split(delimiter).map(&:strip)
34
34
  end
35
35
 
36
36
  def parse_plist(path)
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
2
  module FirebaseAppDistribution
3
- VERSION = "0.8.1"
3
+ VERSION = "0.9.0.pre.1"
4
4
  end
5
5
  end
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.8.1
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-15 00:00:00.000000000 Z
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