fastlane 2.205.1 → 2.206.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +88 -88
  3. data/cert/lib/cert/runner.rb +15 -7
  4. data/deliver/lib/deliver/options.rb +5 -0
  5. data/deliver/lib/deliver/runner.rb +45 -0
  6. data/{frameit/lib/frameit/.offsets.rb.swp → fastlane/lib/fastlane/actions/.supply.rb.swp} +0 -0
  7. data/fastlane/lib/fastlane/actions/danger.rb +14 -0
  8. data/fastlane/lib/fastlane/actions/run_tests.rb +1 -7
  9. data/fastlane/lib/fastlane/actions/setup_ci.rb +13 -4
  10. data/fastlane/lib/fastlane/actions/update_project_provisioning.rb +9 -0
  11. data/fastlane/lib/fastlane/cli_tools_distributor.rb +20 -0
  12. data/fastlane/lib/fastlane/version.rb +1 -1
  13. data/fastlane/swift/Deliverfile.swift +1 -1
  14. data/fastlane/swift/DeliverfileProtocol.swift +5 -1
  15. data/fastlane/swift/Fastlane.swift +39 -3
  16. data/fastlane/swift/Gymfile.swift +1 -1
  17. data/fastlane/swift/GymfileProtocol.swift +1 -1
  18. data/fastlane/swift/Matchfile.swift +1 -1
  19. data/fastlane/swift/MatchfileProtocol.swift +5 -1
  20. data/fastlane/swift/Precheckfile.swift +1 -1
  21. data/fastlane/swift/PrecheckfileProtocol.swift +1 -1
  22. data/fastlane/swift/Scanfile.swift +1 -1
  23. data/fastlane/swift/ScanfileProtocol.swift +1 -1
  24. data/fastlane/swift/Screengrabfile.swift +1 -1
  25. data/fastlane/swift/ScreengrabfileProtocol.swift +1 -1
  26. data/fastlane/swift/Snapshotfile.swift +1 -1
  27. data/fastlane/swift/SnapshotfileProtocol.swift +1 -1
  28. data/fastlane/swift/formatting/Brewfile.lock.json +13 -13
  29. data/fastlane_core/lib/fastlane_core/itunes_transporter.rb +90 -0
  30. data/frameit/lib/frameit/device_types.rb +7 -0
  31. data/match/lib/match/importer.rb +3 -1
  32. data/match/lib/match/options.rb +5 -0
  33. data/match/lib/match/runner.rb +9 -3
  34. data/match/lib/match/storage/google_cloud_storage.rb +7 -6
  35. data/scan/lib/scan/options.rb +6 -1
  36. data/scan/lib/scan/runner.rb +10 -2
  37. data/sigh/lib/sigh/runner.rb +2 -1
  38. data/spaceship/lib/spaceship/connect_api/api_client.rb +10 -5
  39. data/spaceship/lib/spaceship/connect_api/models/app.rb +1 -2
  40. data/spaceship/lib/spaceship/connect_api/models/build_delivery.rb +2 -1
  41. data/spaceship/lib/spaceship/connect_api/models/certificate.rb +1 -0
  42. data/spaceship/lib/spaceship/connect_api/models/user.rb +5 -0
  43. data/spaceship/lib/spaceship/connect_api/testflight/testflight.rb +24 -2
  44. data/spaceship/lib/spaceship/connect_api/token.rb +5 -2
  45. metadata +23 -28
  46. data/frameit/lib/frameit/.device.rb.swp +0 -0
  47. data/frameit/lib/frameit/.device_types.rb.swp +0 -0
  48. data/frameit/lib/frameit/.editor.rb.swp +0 -0
  49. data/frameit/lib/frameit/.runner.rb.swp +0 -0
  50. data/frameit/lib/frameit/.screenshot.rb.swp +0 -0
@@ -663,6 +663,7 @@ public func appledoc(input: [String],
663
663
  - overwriteScreenshots: Clear all previously uploaded screenshots before uploading the new ones
664
664
  - syncScreenshots: Sync screenshots with local ones. This is currently beta optionso set true to 'FASTLANE_ENABLE_BETA_DELIVER_SYNC_SCREENSHOTS' environment variable as well
665
665
  - submitForReview: Submit the new version for Review after uploading everything
666
+ - verifyOnly: Verifies archive with App Store Connect without uploading
666
667
  - rejectIfPossible: Rejects the previously submitted build if it's in a state where it's possible
667
668
  - automaticRelease: Should the app be automatically released once it's approved? (Can not be used together with `auto_release_date`)
668
669
  - autoReleaseDate: Date in milliseconds for automatically releasing on pending approval (Can not be used together with `automatic_release`)
@@ -734,6 +735,7 @@ public func appstore(apiKeyPath: OptionalConfigValue<String?> = .fastlaneDefault
734
735
  overwriteScreenshots: OptionalConfigValue<Bool> = .fastlaneDefault(false),
735
736
  syncScreenshots: OptionalConfigValue<Bool> = .fastlaneDefault(false),
736
737
  submitForReview: OptionalConfigValue<Bool> = .fastlaneDefault(false),
738
+ verifyOnly: OptionalConfigValue<Bool> = .fastlaneDefault(false),
737
739
  rejectIfPossible: OptionalConfigValue<Bool> = .fastlaneDefault(false),
738
740
  automaticRelease: OptionalConfigValue<Bool?> = .fastlaneDefault(nil),
739
741
  autoReleaseDate: OptionalConfigValue<Int?> = .fastlaneDefault(nil),
@@ -798,6 +800,7 @@ public func appstore(apiKeyPath: OptionalConfigValue<String?> = .fastlaneDefault
798
800
  let overwriteScreenshotsArg = overwriteScreenshots.asRubyArgument(name: "overwrite_screenshots", type: nil)
799
801
  let syncScreenshotsArg = syncScreenshots.asRubyArgument(name: "sync_screenshots", type: nil)
800
802
  let submitForReviewArg = submitForReview.asRubyArgument(name: "submit_for_review", type: nil)
803
+ let verifyOnlyArg = verifyOnly.asRubyArgument(name: "verify_only", type: nil)
801
804
  let rejectIfPossibleArg = rejectIfPossible.asRubyArgument(name: "reject_if_possible", type: nil)
802
805
  let automaticReleaseArg = automaticRelease.asRubyArgument(name: "automatic_release", type: nil)
803
806
  let autoReleaseDateArg = autoReleaseDate.asRubyArgument(name: "auto_release_date", type: nil)
@@ -861,6 +864,7 @@ public func appstore(apiKeyPath: OptionalConfigValue<String?> = .fastlaneDefault
861
864
  overwriteScreenshotsArg,
862
865
  syncScreenshotsArg,
863
866
  submitForReviewArg,
867
+ verifyOnlyArg,
864
868
  rejectIfPossibleArg,
865
869
  automaticReleaseArg,
866
870
  autoReleaseDateArg,
@@ -3550,6 +3554,8 @@ public func createXcframework(frameworks: OptionalConfigValue<[String]?> = .fast
3550
3554
  - dangerId: The identifier of this Danger instance
3551
3555
  - dangerfile: The location of your Dangerfile
3552
3556
  - githubApiToken: GitHub API token for danger
3557
+ - githubEnterpriseHost: GitHub host URL for GitHub Enterprise
3558
+ - githubEnterpriseApiBaseUrl: GitHub API base URL for GitHub Enterprise
3553
3559
  - failOnErrors: Should always fail the build process, defaults to false
3554
3560
  - newComment: Makes Danger post a new comment instead of editing its previous one
3555
3561
  - removePreviousComments: Makes Danger remove all previous comment and create a new one in the end of the list
@@ -3566,6 +3572,8 @@ public func danger(useBundleExec: OptionalConfigValue<Bool> = .fastlaneDefault(t
3566
3572
  dangerId: OptionalConfigValue<String?> = .fastlaneDefault(nil),
3567
3573
  dangerfile: OptionalConfigValue<String?> = .fastlaneDefault(nil),
3568
3574
  githubApiToken: OptionalConfigValue<String?> = .fastlaneDefault(nil),
3575
+ githubEnterpriseHost: OptionalConfigValue<String?> = .fastlaneDefault(nil),
3576
+ githubEnterpriseApiBaseUrl: OptionalConfigValue<String?> = .fastlaneDefault(nil),
3569
3577
  failOnErrors: OptionalConfigValue<Bool> = .fastlaneDefault(false),
3570
3578
  newComment: OptionalConfigValue<Bool> = .fastlaneDefault(false),
3571
3579
  removePreviousComments: OptionalConfigValue<Bool> = .fastlaneDefault(false),
@@ -3579,6 +3587,8 @@ public func danger(useBundleExec: OptionalConfigValue<Bool> = .fastlaneDefault(t
3579
3587
  let dangerIdArg = dangerId.asRubyArgument(name: "danger_id", type: nil)
3580
3588
  let dangerfileArg = dangerfile.asRubyArgument(name: "dangerfile", type: nil)
3581
3589
  let githubApiTokenArg = githubApiToken.asRubyArgument(name: "github_api_token", type: nil)
3590
+ let githubEnterpriseHostArg = githubEnterpriseHost.asRubyArgument(name: "github_enterprise_host", type: nil)
3591
+ let githubEnterpriseApiBaseUrlArg = githubEnterpriseApiBaseUrl.asRubyArgument(name: "github_enterprise_api_base_url", type: nil)
3582
3592
  let failOnErrorsArg = failOnErrors.asRubyArgument(name: "fail_on_errors", type: nil)
3583
3593
  let newCommentArg = newComment.asRubyArgument(name: "new_comment", type: nil)
3584
3594
  let removePreviousCommentsArg = removePreviousComments.asRubyArgument(name: "remove_previous_comments", type: nil)
@@ -3591,6 +3601,8 @@ public func danger(useBundleExec: OptionalConfigValue<Bool> = .fastlaneDefault(t
3591
3601
  dangerIdArg,
3592
3602
  dangerfileArg,
3593
3603
  githubApiTokenArg,
3604
+ githubEnterpriseHostArg,
3605
+ githubEnterpriseApiBaseUrlArg,
3594
3606
  failOnErrorsArg,
3595
3607
  newCommentArg,
3596
3608
  removePreviousCommentsArg,
@@ -3671,6 +3683,7 @@ public func deleteKeychain(name: OptionalConfigValue<String?> = .fastlaneDefault
3671
3683
  - overwriteScreenshots: Clear all previously uploaded screenshots before uploading the new ones
3672
3684
  - syncScreenshots: Sync screenshots with local ones. This is currently beta optionso set true to 'FASTLANE_ENABLE_BETA_DELIVER_SYNC_SCREENSHOTS' environment variable as well
3673
3685
  - submitForReview: Submit the new version for Review after uploading everything
3686
+ - verifyOnly: Verifies archive with App Store Connect without uploading
3674
3687
  - rejectIfPossible: Rejects the previously submitted build if it's in a state where it's possible
3675
3688
  - automaticRelease: Should the app be automatically released once it's approved? (Can not be used together with `auto_release_date`)
3676
3689
  - autoReleaseDate: Date in milliseconds for automatically releasing on pending approval (Can not be used together with `automatic_release`)
@@ -3742,6 +3755,7 @@ public func deliver(apiKeyPath: OptionalConfigValue<String?> = .fastlaneDefault(
3742
3755
  overwriteScreenshots: OptionalConfigValue<Bool> = .fastlaneDefault(deliverfile.overwriteScreenshots),
3743
3756
  syncScreenshots: OptionalConfigValue<Bool> = .fastlaneDefault(deliverfile.syncScreenshots),
3744
3757
  submitForReview: OptionalConfigValue<Bool> = .fastlaneDefault(deliverfile.submitForReview),
3758
+ verifyOnly: OptionalConfigValue<Bool> = .fastlaneDefault(deliverfile.verifyOnly),
3745
3759
  rejectIfPossible: OptionalConfigValue<Bool> = .fastlaneDefault(deliverfile.rejectIfPossible),
3746
3760
  automaticRelease: OptionalConfigValue<Bool?> = .fastlaneDefault(deliverfile.automaticRelease),
3747
3761
  autoReleaseDate: OptionalConfigValue<Int?> = .fastlaneDefault(deliverfile.autoReleaseDate),
@@ -3806,6 +3820,7 @@ public func deliver(apiKeyPath: OptionalConfigValue<String?> = .fastlaneDefault(
3806
3820
  let overwriteScreenshotsArg = overwriteScreenshots.asRubyArgument(name: "overwrite_screenshots", type: nil)
3807
3821
  let syncScreenshotsArg = syncScreenshots.asRubyArgument(name: "sync_screenshots", type: nil)
3808
3822
  let submitForReviewArg = submitForReview.asRubyArgument(name: "submit_for_review", type: nil)
3823
+ let verifyOnlyArg = verifyOnly.asRubyArgument(name: "verify_only", type: nil)
3809
3824
  let rejectIfPossibleArg = rejectIfPossible.asRubyArgument(name: "reject_if_possible", type: nil)
3810
3825
  let automaticReleaseArg = automaticRelease.asRubyArgument(name: "automatic_release", type: nil)
3811
3826
  let autoReleaseDateArg = autoReleaseDate.asRubyArgument(name: "auto_release_date", type: nil)
@@ -3869,6 +3884,7 @@ public func deliver(apiKeyPath: OptionalConfigValue<String?> = .fastlaneDefault(
3869
3884
  overwriteScreenshotsArg,
3870
3885
  syncScreenshotsArg,
3871
3886
  submitForReviewArg,
3887
+ verifyOnlyArg,
3872
3888
  rejectIfPossibleArg,
3873
3889
  automaticReleaseArg,
3874
3890
  autoReleaseDateArg,
@@ -6633,6 +6649,7 @@ public func makeChangelogFromJenkins(fallbackChangelog: String = "",
6633
6649
  - googleCloudBucketName: Name of the Google Cloud Storage bucket to use
6634
6650
  - googleCloudKeysFile: Path to the gc_keys.json file
6635
6651
  - googleCloudProjectId: ID of the Google Cloud project to use for authentication
6652
+ - skipGoogleCloudAccountConfirmation: Skips confirming to use the system google account
6636
6653
  - s3Region: Name of the S3 region
6637
6654
  - s3AccessKey: S3 access key
6638
6655
  - s3SecretAccessKey: S3 secret access key
@@ -6683,6 +6700,7 @@ public func match(type: String = matchfile.type,
6683
6700
  googleCloudBucketName: OptionalConfigValue<String?> = .fastlaneDefault(matchfile.googleCloudBucketName),
6684
6701
  googleCloudKeysFile: OptionalConfigValue<String?> = .fastlaneDefault(matchfile.googleCloudKeysFile),
6685
6702
  googleCloudProjectId: OptionalConfigValue<String?> = .fastlaneDefault(matchfile.googleCloudProjectId),
6703
+ skipGoogleCloudAccountConfirmation: OptionalConfigValue<Bool> = .fastlaneDefault(matchfile.skipGoogleCloudAccountConfirmation),
6686
6704
  s3Region: OptionalConfigValue<String?> = .fastlaneDefault(matchfile.s3Region),
6687
6705
  s3AccessKey: OptionalConfigValue<String?> = .fastlaneDefault(matchfile.s3AccessKey),
6688
6706
  s3SecretAccessKey: OptionalConfigValue<String?> = .fastlaneDefault(matchfile.s3SecretAccessKey),
@@ -6731,6 +6749,7 @@ public func match(type: String = matchfile.type,
6731
6749
  let googleCloudBucketNameArg = googleCloudBucketName.asRubyArgument(name: "google_cloud_bucket_name", type: nil)
6732
6750
  let googleCloudKeysFileArg = googleCloudKeysFile.asRubyArgument(name: "google_cloud_keys_file", type: nil)
6733
6751
  let googleCloudProjectIdArg = googleCloudProjectId.asRubyArgument(name: "google_cloud_project_id", type: nil)
6752
+ let skipGoogleCloudAccountConfirmationArg = skipGoogleCloudAccountConfirmation.asRubyArgument(name: "skip_google_cloud_account_confirmation", type: nil)
6734
6753
  let s3RegionArg = s3Region.asRubyArgument(name: "s3_region", type: nil)
6735
6754
  let s3AccessKeyArg = s3AccessKey.asRubyArgument(name: "s3_access_key", type: nil)
6736
6755
  let s3SecretAccessKeyArg = s3SecretAccessKey.asRubyArgument(name: "s3_secret_access_key", type: nil)
@@ -6778,6 +6797,7 @@ public func match(type: String = matchfile.type,
6778
6797
  googleCloudBucketNameArg,
6779
6798
  googleCloudKeysFileArg,
6780
6799
  googleCloudProjectIdArg,
6800
+ skipGoogleCloudAccountConfirmationArg,
6781
6801
  s3RegionArg,
6782
6802
  s3AccessKeyArg,
6783
6803
  s3SecretAccessKeyArg,
@@ -6836,6 +6856,7 @@ public func match(type: String = matchfile.type,
6836
6856
  - googleCloudBucketName: Name of the Google Cloud Storage bucket to use
6837
6857
  - googleCloudKeysFile: Path to the gc_keys.json file
6838
6858
  - googleCloudProjectId: ID of the Google Cloud project to use for authentication
6859
+ - skipGoogleCloudAccountConfirmation: Skips confirming to use the system google account
6839
6860
  - s3Region: Name of the S3 region
6840
6861
  - s3AccessKey: S3 access key
6841
6862
  - s3SecretAccessKey: S3 secret access key
@@ -6890,6 +6911,7 @@ public func matchNuke(type: String = "development",
6890
6911
  googleCloudBucketName: OptionalConfigValue<String?> = .fastlaneDefault(nil),
6891
6912
  googleCloudKeysFile: OptionalConfigValue<String?> = .fastlaneDefault(nil),
6892
6913
  googleCloudProjectId: OptionalConfigValue<String?> = .fastlaneDefault(nil),
6914
+ skipGoogleCloudAccountConfirmation: OptionalConfigValue<Bool> = .fastlaneDefault(false),
6893
6915
  s3Region: OptionalConfigValue<String?> = .fastlaneDefault(nil),
6894
6916
  s3AccessKey: OptionalConfigValue<String?> = .fastlaneDefault(nil),
6895
6917
  s3SecretAccessKey: OptionalConfigValue<String?> = .fastlaneDefault(nil),
@@ -6938,6 +6960,7 @@ public func matchNuke(type: String = "development",
6938
6960
  let googleCloudBucketNameArg = googleCloudBucketName.asRubyArgument(name: "google_cloud_bucket_name", type: nil)
6939
6961
  let googleCloudKeysFileArg = googleCloudKeysFile.asRubyArgument(name: "google_cloud_keys_file", type: nil)
6940
6962
  let googleCloudProjectIdArg = googleCloudProjectId.asRubyArgument(name: "google_cloud_project_id", type: nil)
6963
+ let skipGoogleCloudAccountConfirmationArg = skipGoogleCloudAccountConfirmation.asRubyArgument(name: "skip_google_cloud_account_confirmation", type: nil)
6941
6964
  let s3RegionArg = s3Region.asRubyArgument(name: "s3_region", type: nil)
6942
6965
  let s3AccessKeyArg = s3AccessKey.asRubyArgument(name: "s3_access_key", type: nil)
6943
6966
  let s3SecretAccessKeyArg = s3SecretAccessKey.asRubyArgument(name: "s3_secret_access_key", type: nil)
@@ -6985,6 +7008,7 @@ public func matchNuke(type: String = "development",
6985
7008
  googleCloudBucketNameArg,
6986
7009
  googleCloudKeysFileArg,
6987
7010
  googleCloudProjectIdArg,
7011
+ skipGoogleCloudAccountConfirmationArg,
6988
7012
  s3RegionArg,
6989
7013
  s3AccessKeyArg,
6990
7014
  s3SecretAccessKeyArg,
@@ -9662,6 +9686,7 @@ public func setPodKey(useBundleExec: OptionalConfigValue<Bool> = .fastlaneDefaul
9662
9686
  - parameters:
9663
9687
  - force: Force setup, even if not executed by CI
9664
9688
  - provider: CI provider. If none is set, the provider is detected automatically
9689
+ - timeout: Set a custom timeout in seconds for keychain. Set `0` if you want to specify 'no time-out'
9665
9690
 
9666
9691
  - Creates a new temporary keychain for use with match|
9667
9692
  - Switches match to `readonly` mode to not create new profiles/cert on CI|
@@ -9670,12 +9695,15 @@ public func setPodKey(useBundleExec: OptionalConfigValue<Bool> = .fastlaneDefaul
9670
9695
  This action helps with CI integration. Add this to the top of your Fastfile if you use CI.
9671
9696
  */
9672
9697
  public func setupCi(force: OptionalConfigValue<Bool> = .fastlaneDefault(false),
9673
- provider: OptionalConfigValue<String?> = .fastlaneDefault(nil))
9698
+ provider: OptionalConfigValue<String?> = .fastlaneDefault(nil),
9699
+ timeout: Int = 3600)
9674
9700
  {
9675
9701
  let forceArg = force.asRubyArgument(name: "force", type: nil)
9676
9702
  let providerArg = provider.asRubyArgument(name: "provider", type: nil)
9703
+ let timeoutArg = RubyCommand.Argument(name: "timeout", value: timeout, type: nil)
9677
9704
  let array: [RubyCommand.Argument?] = [forceArg,
9678
- providerArg]
9705
+ providerArg,
9706
+ timeoutArg]
9679
9707
  let args: [RubyCommand.Argument] = array
9680
9708
  .filter { $0?.value != nil }
9681
9709
  .compactMap { $0 }
@@ -11026,6 +11054,7 @@ public func swiftlint(mode: String = "lint",
11026
11054
  - googleCloudBucketName: Name of the Google Cloud Storage bucket to use
11027
11055
  - googleCloudKeysFile: Path to the gc_keys.json file
11028
11056
  - googleCloudProjectId: ID of the Google Cloud project to use for authentication
11057
+ - skipGoogleCloudAccountConfirmation: Skips confirming to use the system google account
11029
11058
  - s3Region: Name of the S3 region
11030
11059
  - s3AccessKey: S3 access key
11031
11060
  - s3SecretAccessKey: S3 secret access key
@@ -11076,6 +11105,7 @@ public func syncCodeSigning(type: String = "development",
11076
11105
  googleCloudBucketName: OptionalConfigValue<String?> = .fastlaneDefault(nil),
11077
11106
  googleCloudKeysFile: OptionalConfigValue<String?> = .fastlaneDefault(nil),
11078
11107
  googleCloudProjectId: OptionalConfigValue<String?> = .fastlaneDefault(nil),
11108
+ skipGoogleCloudAccountConfirmation: OptionalConfigValue<Bool> = .fastlaneDefault(false),
11079
11109
  s3Region: OptionalConfigValue<String?> = .fastlaneDefault(nil),
11080
11110
  s3AccessKey: OptionalConfigValue<String?> = .fastlaneDefault(nil),
11081
11111
  s3SecretAccessKey: OptionalConfigValue<String?> = .fastlaneDefault(nil),
@@ -11124,6 +11154,7 @@ public func syncCodeSigning(type: String = "development",
11124
11154
  let googleCloudBucketNameArg = googleCloudBucketName.asRubyArgument(name: "google_cloud_bucket_name", type: nil)
11125
11155
  let googleCloudKeysFileArg = googleCloudKeysFile.asRubyArgument(name: "google_cloud_keys_file", type: nil)
11126
11156
  let googleCloudProjectIdArg = googleCloudProjectId.asRubyArgument(name: "google_cloud_project_id", type: nil)
11157
+ let skipGoogleCloudAccountConfirmationArg = skipGoogleCloudAccountConfirmation.asRubyArgument(name: "skip_google_cloud_account_confirmation", type: nil)
11127
11158
  let s3RegionArg = s3Region.asRubyArgument(name: "s3_region", type: nil)
11128
11159
  let s3AccessKeyArg = s3AccessKey.asRubyArgument(name: "s3_access_key", type: nil)
11129
11160
  let s3SecretAccessKeyArg = s3SecretAccessKey.asRubyArgument(name: "s3_secret_access_key", type: nil)
@@ -11171,6 +11202,7 @@ public func syncCodeSigning(type: String = "development",
11171
11202
  googleCloudBucketNameArg,
11172
11203
  googleCloudKeysFileArg,
11173
11204
  googleCloudProjectIdArg,
11205
+ skipGoogleCloudAccountConfirmationArg,
11174
11206
  s3RegionArg,
11175
11207
  s3AccessKeyArg,
11176
11208
  s3SecretAccessKeyArg,
@@ -12214,6 +12246,7 @@ public func uploadSymbolsToSentry(apiHost: String = "https://app.getsentry.com/a
12214
12246
  - overwriteScreenshots: Clear all previously uploaded screenshots before uploading the new ones
12215
12247
  - syncScreenshots: Sync screenshots with local ones. This is currently beta optionso set true to 'FASTLANE_ENABLE_BETA_DELIVER_SYNC_SCREENSHOTS' environment variable as well
12216
12248
  - submitForReview: Submit the new version for Review after uploading everything
12249
+ - verifyOnly: Verifies archive with App Store Connect without uploading
12217
12250
  - rejectIfPossible: Rejects the previously submitted build if it's in a state where it's possible
12218
12251
  - automaticRelease: Should the app be automatically released once it's approved? (Can not be used together with `auto_release_date`)
12219
12252
  - autoReleaseDate: Date in milliseconds for automatically releasing on pending approval (Can not be used together with `automatic_release`)
@@ -12285,6 +12318,7 @@ public func uploadToAppStore(apiKeyPath: OptionalConfigValue<String?> = .fastlan
12285
12318
  overwriteScreenshots: OptionalConfigValue<Bool> = .fastlaneDefault(false),
12286
12319
  syncScreenshots: OptionalConfigValue<Bool> = .fastlaneDefault(false),
12287
12320
  submitForReview: OptionalConfigValue<Bool> = .fastlaneDefault(false),
12321
+ verifyOnly: OptionalConfigValue<Bool> = .fastlaneDefault(false),
12288
12322
  rejectIfPossible: OptionalConfigValue<Bool> = .fastlaneDefault(false),
12289
12323
  automaticRelease: OptionalConfigValue<Bool?> = .fastlaneDefault(nil),
12290
12324
  autoReleaseDate: OptionalConfigValue<Int?> = .fastlaneDefault(nil),
@@ -12349,6 +12383,7 @@ public func uploadToAppStore(apiKeyPath: OptionalConfigValue<String?> = .fastlan
12349
12383
  let overwriteScreenshotsArg = overwriteScreenshots.asRubyArgument(name: "overwrite_screenshots", type: nil)
12350
12384
  let syncScreenshotsArg = syncScreenshots.asRubyArgument(name: "sync_screenshots", type: nil)
12351
12385
  let submitForReviewArg = submitForReview.asRubyArgument(name: "submit_for_review", type: nil)
12386
+ let verifyOnlyArg = verifyOnly.asRubyArgument(name: "verify_only", type: nil)
12352
12387
  let rejectIfPossibleArg = rejectIfPossible.asRubyArgument(name: "reject_if_possible", type: nil)
12353
12388
  let automaticReleaseArg = automaticRelease.asRubyArgument(name: "automatic_release", type: nil)
12354
12389
  let autoReleaseDateArg = autoReleaseDate.asRubyArgument(name: "auto_release_date", type: nil)
@@ -12412,6 +12447,7 @@ public func uploadToAppStore(apiKeyPath: OptionalConfigValue<String?> = .fastlan
12412
12447
  overwriteScreenshotsArg,
12413
12448
  syncScreenshotsArg,
12414
12449
  submitForReviewArg,
12450
+ verifyOnlyArg,
12415
12451
  rejectIfPossibleArg,
12416
12452
  automaticReleaseArg,
12417
12453
  autoReleaseDateArg,
@@ -13430,4 +13466,4 @@ public let snapshotfile: Snapshotfile = .init()
13430
13466
 
13431
13467
  // Please don't remove the lines below
13432
13468
  // They are used to detect outdated files
13433
- // FastlaneRunnerAPIVersion [0.9.154]
13469
+ // FastlaneRunnerAPIVersion [0.9.157]
@@ -17,4 +17,4 @@ public class Gymfile: GymfileProtocol {
17
17
  // during the `init` process, and you won't see this message
18
18
  }
19
19
 
20
- // Generated with fastlane 2.205.1
20
+ // Generated with fastlane 2.206.1
@@ -204,4 +204,4 @@ public extension GymfileProtocol {
204
204
 
205
205
  // Please don't remove the lines below
206
206
  // They are used to detect outdated files
207
- // FastlaneRunnerAPIVersion [0.9.104]
207
+ // FastlaneRunnerAPIVersion [0.9.107]
@@ -17,4 +17,4 @@ public class Matchfile: MatchfileProtocol {
17
17
  // during the `init` process, and you won't see this message
18
18
  }
19
19
 
20
- // Generated with fastlane 2.205.1
20
+ // Generated with fastlane 2.206.1
@@ -74,6 +74,9 @@ public protocol MatchfileProtocol: AnyObject {
74
74
  /// ID of the Google Cloud project to use for authentication
75
75
  var googleCloudProjectId: String? { get }
76
76
 
77
+ /// Skips confirming to use the system google account
78
+ var skipGoogleCloudAccountConfirmation: Bool { get }
79
+
77
80
  /// Name of the S3 region
78
81
  var s3Region: String? { get }
79
82
 
@@ -169,6 +172,7 @@ public extension MatchfileProtocol {
169
172
  var googleCloudBucketName: String? { return nil }
170
173
  var googleCloudKeysFile: String? { return nil }
171
174
  var googleCloudProjectId: String? { return nil }
175
+ var skipGoogleCloudAccountConfirmation: Bool { return false }
172
176
  var s3Region: String? { return nil }
173
177
  var s3AccessKey: String? { return nil }
174
178
  var s3SecretAccessKey: String? { return nil }
@@ -196,4 +200,4 @@ public extension MatchfileProtocol {
196
200
 
197
201
  // Please don't remove the lines below
198
202
  // They are used to detect outdated files
199
- // FastlaneRunnerAPIVersion [0.9.98]
203
+ // FastlaneRunnerAPIVersion [0.9.101]
@@ -17,4 +17,4 @@ public class Precheckfile: PrecheckfileProtocol {
17
17
  // during the `init` process, and you won't see this message
18
18
  }
19
19
 
20
- // Generated with fastlane 2.205.1
20
+ // Generated with fastlane 2.206.1
@@ -52,4 +52,4 @@ public extension PrecheckfileProtocol {
52
52
 
53
53
  // Please don't remove the lines below
54
54
  // They are used to detect outdated files
55
- // FastlaneRunnerAPIVersion [0.9.97]
55
+ // FastlaneRunnerAPIVersion [0.9.100]
@@ -17,4 +17,4 @@ public class Scanfile: ScanfileProtocol {
17
17
  // during the `init` process, and you won't see this message
18
18
  }
19
19
 
20
- // Generated with fastlane 2.205.1
20
+ // Generated with fastlane 2.206.1
@@ -312,4 +312,4 @@ public extension ScanfileProtocol {
312
312
 
313
313
  // Please don't remove the lines below
314
314
  // They are used to detect outdated files
315
- // FastlaneRunnerAPIVersion [0.9.109]
315
+ // FastlaneRunnerAPIVersion [0.9.112]
@@ -17,4 +17,4 @@ public class Screengrabfile: ScreengrabfileProtocol {
17
17
  // during the `init` process, and you won't see this message
18
18
  }
19
19
 
20
- // Generated with fastlane 2.205.1
20
+ // Generated with fastlane 2.206.1
@@ -96,4 +96,4 @@ public extension ScreengrabfileProtocol {
96
96
 
97
97
  // Please don't remove the lines below
98
98
  // They are used to detect outdated files
99
- // FastlaneRunnerAPIVersion [0.9.99]
99
+ // FastlaneRunnerAPIVersion [0.9.102]
@@ -17,4 +17,4 @@ public class Snapshotfile: SnapshotfileProtocol {
17
17
  // during the `init` process, and you won't see this message
18
18
  }
19
19
 
20
- // Generated with fastlane 2.205.1
20
+ // Generated with fastlane 2.206.1
@@ -204,4 +204,4 @@ public extension SnapshotfileProtocol {
204
204
 
205
205
  // Please don't remove the lines below
206
206
  // They are used to detect outdated files
207
- // FastlaneRunnerAPIVersion [0.9.93]
207
+ // FastlaneRunnerAPIVersion [0.9.96]
@@ -2,35 +2,35 @@
2
2
  "entries": {
3
3
  "brew": {
4
4
  "swiftformat": {
5
- "version": "0.49.6",
5
+ "version": "0.49.9",
6
6
  "bottle": {
7
7
  "rebuild": 0,
8
8
  "root_url": "https://ghcr.io/v2/homebrew/core",
9
9
  "files": {
10
10
  "arm64_monterey": {
11
11
  "cellar": ":any_skip_relocation",
12
- "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:0e8e1fe019fd98a5cb6d75e31130eedcb65546693eb385a06948b940da7125d3",
13
- "sha256": "0e8e1fe019fd98a5cb6d75e31130eedcb65546693eb385a06948b940da7125d3"
12
+ "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:bacd0dc8f488fd7909252467eaf16dcd339468857aea13a3643f7e0efd7715f8",
13
+ "sha256": "bacd0dc8f488fd7909252467eaf16dcd339468857aea13a3643f7e0efd7715f8"
14
14
  },
15
15
  "arm64_big_sur": {
16
16
  "cellar": ":any_skip_relocation",
17
- "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:916c5eaf7600aa9a6bf7fc4d3998b1b165b5b354de260ce6e13bbc4ff3167ff1",
18
- "sha256": "916c5eaf7600aa9a6bf7fc4d3998b1b165b5b354de260ce6e13bbc4ff3167ff1"
17
+ "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:7bc39a57d110f727993aa556cca5cba5549d536367bc12f25b56e25c4fdfa194",
18
+ "sha256": "7bc39a57d110f727993aa556cca5cba5549d536367bc12f25b56e25c4fdfa194"
19
19
  },
20
20
  "monterey": {
21
21
  "cellar": ":any_skip_relocation",
22
- "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:8ddd11b5e105b148b8919e9c44d851e845e9c31ed7cf8a9b92b2369bd0df98d5",
23
- "sha256": "8ddd11b5e105b148b8919e9c44d851e845e9c31ed7cf8a9b92b2369bd0df98d5"
22
+ "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:739d230372dd797d5cf5a0586156068ecb5965878550a67b5ca56ccdf2799557",
23
+ "sha256": "739d230372dd797d5cf5a0586156068ecb5965878550a67b5ca56ccdf2799557"
24
24
  },
25
25
  "big_sur": {
26
26
  "cellar": ":any_skip_relocation",
27
- "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:c1fd4ae18452ea62e6d33ca0554fa4df5f646a22abffe7f5d489c397945b7ea9",
28
- "sha256": "c1fd4ae18452ea62e6d33ca0554fa4df5f646a22abffe7f5d489c397945b7ea9"
27
+ "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:22080bdc75b03f5926d68fb248fc401d6a94876205ce03663a8950644b0e41e6",
28
+ "sha256": "22080bdc75b03f5926d68fb248fc401d6a94876205ce03663a8950644b0e41e6"
29
29
  },
30
30
  "catalina": {
31
31
  "cellar": ":any_skip_relocation",
32
- "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:f1ffad5c8bbfe80659f51b7cc54062c736fed1ff79b71b8f648d8e4552d8b752",
33
- "sha256": "f1ffad5c8bbfe80659f51b7cc54062c736fed1ff79b71b8f648d8e4552d8b752"
32
+ "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:d4cda88cf3bef7b18e960197b8db4826f234e3b3434ba902c3924c37b9040fe8",
33
+ "sha256": "d4cda88cf3bef7b18e960197b8db4826f234e3b3434ba902c3924c37b9040fe8"
34
34
  }
35
35
  }
36
36
  }
@@ -56,9 +56,9 @@
56
56
  "macOS": "11.0.1"
57
57
  },
58
58
  "monterey": {
59
- "HOMEBREW_VERSION": "3.4.3-43-g6e1b6a3",
59
+ "HOMEBREW_VERSION": "3.4.11-87-g555cf33",
60
60
  "HOMEBREW_PREFIX": "/opt/homebrew",
61
- "Homebrew/homebrew-core": "2b1ab33f1beebecfdf4b584992272417d9492167",
61
+ "Homebrew/homebrew-core": "ef68d97eded78385ebe5ca6d988e84976c47eb41",
62
62
  "CLT": "13.2.0.0.1.1638488800",
63
63
  "Xcode": "13.2.1",
64
64
  "macOS": "12.2.1"
@@ -223,6 +223,20 @@ module FastlaneCore
223
223
  ].compact.join(' ')
224
224
  end
225
225
 
226
+ def build_verify_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil)
227
+ use_jwt = !jwt.to_s.empty?
228
+ [
229
+ '"' + Helper.transporter_path + '"',
230
+ '-m verify',
231
+ ("-u #{username.shellescape}" unless use_jwt),
232
+ ("-p #{shell_escaped_password(password)}" unless use_jwt),
233
+ ("-jwt #{jwt}" if use_jwt),
234
+ "-f #{source.shellescape}",
235
+ ("-WONoPause true" if Helper.windows?), # Windows only: process instantly returns instead of waiting for key press
236
+ ("-itc_provider #{provider_short_name}" if jwt.nil? && !provider_short_name.to_s.empty?)
237
+ ].compact.join(' ')
238
+ end
239
+
226
240
  def handle_error(password)
227
241
  # rubocop:disable Style/CaseEquality
228
242
  # rubocop:disable Style/YodaCondition
@@ -304,6 +318,42 @@ module FastlaneCore
304
318
  end
305
319
  end
306
320
 
321
+ def build_verify_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil)
322
+ use_jwt = !jwt.to_s.empty?
323
+ if !Helper.user_defined_itms_path? && Helper.mac? && Helper.xcode_at_least?(11)
324
+ [
325
+ ("ITMS_TRANSPORTER_PASSWORD=#{password.shellescape}" unless use_jwt),
326
+ 'xcrun iTMSTransporter',
327
+ '-m verify',
328
+ ("-u #{username.shellescape}" unless use_jwt),
329
+ ("-p @env:ITMS_TRANSPORTER_PASSWORD" unless use_jwt),
330
+ ("-jwt #{jwt}" if use_jwt),
331
+ "-f #{source.shellescape}",
332
+ ("-itc_provider #{provider_short_name}" if jwt.nil? && !provider_short_name.to_s.empty?),
333
+ '2>&1' # cause stderr to be written to stdout
334
+ ].compact.join(' ') # compact gets rid of the possibly nil ENV value
335
+ else
336
+ [
337
+ Helper.transporter_java_executable_path.shellescape,
338
+ "-Djava.ext.dirs=#{Helper.transporter_java_ext_dir.shellescape}",
339
+ '-XX:NewSize=2m',
340
+ '-Xms32m',
341
+ '-Xmx1024m',
342
+ '-Xms1024m',
343
+ '-Djava.awt.headless=true',
344
+ '-Dsun.net.http.retryPost=false',
345
+ java_code_option,
346
+ '-m verify',
347
+ ("-u #{username.shellescape}" unless use_jwt),
348
+ ("-p #{password.shellescape}" unless use_jwt),
349
+ ("-jwt #{jwt}" if use_jwt),
350
+ "-f #{source.shellescape}",
351
+ ("-itc_provider #{provider_short_name}" if jwt.nil? && !provider_short_name.to_s.empty?),
352
+ '2>&1' # cause stderr to be written to stdout
353
+ ].compact.join(' ') # compact gets rid of the possibly nil ENV value
354
+ end
355
+ end
356
+
307
357
  def build_download_command(username, password, apple_id, destination = "/tmp", provider_short_name = "", jwt = nil)
308
358
  use_jwt = !jwt.to_s.empty?
309
359
  if !Helper.user_defined_itms_path? && Helper.mac? && Helper.xcode_at_least?(11)
@@ -540,6 +590,46 @@ module FastlaneCore
540
590
  return result
541
591
  end
542
592
 
593
+ # Verifies the given binary with App Store Connect
594
+ # @param app_id [Integer] The unique App ID
595
+ # @param dir [String] the path in which the package file is located
596
+ # @param package_path [String] the path to the package file (used instead of app_id and dir)
597
+ # @return (Bool) True if everything worked fine
598
+ # @raise [Deliver::TransporterTransferError] when something went wrong
599
+ # when transferring
600
+ def verify(app_id = nil, dir = nil, package_path: nil)
601
+ raise "Either a combination of app id and directory or a package_path are required" if (app_id.nil? || dir.nil?) && package_path.nil?
602
+
603
+ actual_dir = if package_path
604
+ package_path
605
+ else
606
+ File.join(dir, "#{app_id}.itmsp")
607
+ end
608
+
609
+ password_placeholder = @jwt.nil? ? 'YourPassword' : nil
610
+ jwt_placeholder = @jwt.nil? ? nil : 'YourJWT'
611
+
612
+ command = @transporter_executor.build_verify_command(@user, @password, actual_dir, @provider_short_name, @jwt)
613
+ UI.verbose(@transporter_executor.build_verify_command(@user, password_placeholder, actual_dir, @provider_short_name, jwt_placeholder))
614
+
615
+ begin
616
+ result = @transporter_executor.execute(command, ItunesTransporter.hide_transporter_output?)
617
+ rescue TransporterRequiresApplicationSpecificPasswordError => ex
618
+ handle_two_step_failure(ex)
619
+ return verify(app_id, dir, package_path: package_path)
620
+ end
621
+
622
+ if result
623
+ UI.header("Successfully verified package on App Store Connect")
624
+
625
+ FileUtils.rm_rf(actual_dir) unless Helper.test? # we don't need the package any more, since the upload was successful
626
+ else
627
+ handle_error(@password)
628
+ end
629
+
630
+ return result
631
+ end
632
+
543
633
  def displayable_errors
544
634
  @transporter_executor.displayable_errors
545
635
  end
@@ -47,6 +47,9 @@ module Frameit
47
47
  PURPLE ||= "Purple"
48
48
  GRAPHITE ||= "Graphite"
49
49
  PACIFIC_BLUE ||= "Pacific Blue"
50
+ MIDNIGHT ||= "Midnight"
51
+ STARLIGHT ||= "Starlight"
52
+ SIERRA ||= "Sierra"
50
53
 
51
54
  def self.all_colors
52
55
  Color.constants.map { |c| Color.const_get(c).upcase.gsub(' ', '_') }
@@ -124,6 +127,10 @@ module Frameit
124
127
  IPHONE_12_PRO ||= Frameit::Device.new("iphone-12-pro", "Apple iPhone 12 Pro", 10, [[1170, 2532], [2532, 1170]], 460, Color::SPACE_GRAY, Platform::IOS)
125
128
  IPHONE_12_PRO_MAX ||= Frameit::Device.new("iphone12-pro-max", "Apple iPhone 12 Pro Max", 10, [[1284, 2778], [2778, 1284]], 458, Color::GRAPHITE, Platform::IOS)
126
129
  IPHONE_12_MINI ||= Frameit::Device.new("iphone-12-mini", "Apple iPhone 12 Mini", 10, [[1125, 2436], [2436, 1125]], 476, Color::BLACK, Platform::IOS)
130
+ IPHONE_13 ||= Frameit::Device.new("iphone-13", "Apple iPhone 13", 11, [[1170, 2532], [2532, 1170]], 460, Color::MIDNIGHT, Platform::IOS)
131
+ IPHONE_13_PRO ||= Frameit::Device.new("iphone-13-pro", "Apple iPhone 13 Pro", 11, [[1170, 2532], [2532, 1170]], 460, Color::GRAPHITE, Platform::IOS)
132
+ IPHONE_13_PRO_MAX ||= Frameit::Device.new("iphone13-pro-max", "Apple iPhone 13 Pro Max", 11, [[1284, 2778], [2778, 1284]], 458, Color::GRAPHITE, Platform::IOS)
133
+ IPHONE_13_MINI ||= Frameit::Device.new("iphone-13-mini", "Apple iPhone 13 Mini", 11, [[1080, 2340], [2340, 1080]], 476, Color::MIDNIGHT, Platform::IOS)
127
134
  IPAD_10_2 ||= Frameit::Device.new("ipad-10-2", "Apple iPad 10.2", 1, [[1620, 2160], [2160, 1620]], 264, Color::SPACE_GRAY, Platform::IOS)
128
135
  IPAD_AIR_2 ||= Frameit::Device.new("ipad-air-2", "Apple iPad Air 2", 1, [[1536, 2048], [2048, 1536]], 264, Color::SPACE_GRAY, Platform::IOS, Deliver::AppScreenshot::ScreenSize::IOS_IPAD)
129
136
  IPAD_AIR_2019 ||= Frameit::Device.new("ipad-air-2019", "Apple iPad Air (2019)", 2, [[1668, 2224], [2224, 1668]], 265, Color::SPACE_GRAY, Platform::IOS)
@@ -31,6 +31,7 @@ module Match
31
31
  google_cloud_bucket_name: params[:google_cloud_bucket_name].to_s,
32
32
  google_cloud_keys_file: params[:google_cloud_keys_file].to_s,
33
33
  google_cloud_project_id: params[:google_cloud_project_id].to_s,
34
+ skip_google_cloud_account_confirmation: params[:skip_google_cloud_account_confirmation],
34
35
  s3_bucket: params[:s3_bucket],
35
36
  s3_region: params[:s3_region],
36
37
  s3_access_key: params[:s3_access_key],
@@ -71,7 +72,8 @@ module Match
71
72
  ].join(',')
72
73
  when :developer_id_application
73
74
  certificate_type = [
74
- Spaceship::ConnectAPI::Certificate::CertificateType::DEVELOPER_ID_APPLICATION
75
+ Spaceship::ConnectAPI::Certificate::CertificateType::DEVELOPER_ID_APPLICATION,
76
+ Spaceship::ConnectAPI::Certificate::CertificateType::DEVELOPER_ID_APPLICATION_G2
75
77
  ].join(',')
76
78
  when :mac_installer_distribution
77
79
  certificate_type = [
@@ -194,6 +194,11 @@ module Match
194
194
  env_name: "MATCH_GOOGLE_CLOUD_PROJECT_ID",
195
195
  description: "ID of the Google Cloud project to use for authentication",
196
196
  optional: true),
197
+ FastlaneCore::ConfigItem.new(key: :skip_google_cloud_account_confirmation,
198
+ env_name: "MATCH_SKIP_GOOGLE_CLOUD_ACCOUNT_CONFIRMATION",
199
+ description: "Skips confirming to use the system google account",
200
+ type: Boolean,
201
+ default_value: false),
197
202
 
198
203
  # Storage: S3
199
204
  FastlaneCore::ConfigItem.new(key: :s3_region,
@@ -48,6 +48,7 @@ module Match
48
48
  google_cloud_bucket_name: params[:google_cloud_bucket_name].to_s,
49
49
  google_cloud_keys_file: params[:google_cloud_keys_file].to_s,
50
50
  google_cloud_project_id: params[:google_cloud_project_id].to_s,
51
+ skip_google_cloud_account_confirmation: params[:skip_google_cloud_account_confirmation],
51
52
  s3_region: params[:s3_region],
52
53
  s3_access_key: params[:s3_access_key],
53
54
  s3_secret_access_key: params[:s3_secret_access_key],
@@ -82,9 +83,9 @@ module Match
82
83
  app_identifiers = params[:app_identifier].to_s.split(/\s*,\s*/).uniq
83
84
  end
84
85
 
85
- # sometimes we get an array with arrays, this is a bug. To unblock people using match, I suggest we flatten!
86
+ # sometimes we get an array with arrays, this is a bug. To unblock people using match, I suggest we flatten
86
87
  # then in the future address the root cause of https://github.com/fastlane/fastlane/issues/11324
87
- app_identifiers.flatten!
88
+ app_identifiers = app_identifiers.flatten
88
89
 
89
90
  # Verify the App ID (as we don't want 'match' to fail at a later point)
90
91
  if spaceship
@@ -419,7 +420,12 @@ module Match
419
420
 
420
421
  return false unless portal_profile
421
422
 
422
- profile_certs_count = portal_profile.fetch_all_certificates.count
423
+ # When a certificate expires (not revoked) provisioning profile stays valid.
424
+ # And if we regenerate certificate count will not differ:
425
+ # * For portal certificates, we filter out the expired one but includes a new certificate;
426
+ # * Profile still contains an expired certificate and is valid.
427
+ # Thus, we need to check the validity of profile certificates too.
428
+ profile_certs_count = portal_profile.fetch_all_certificates.select(&:valid?).count
423
429
 
424
430
  certificate_types =
425
431
  case platform