fastlane 2.238.0 → 2.241.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (192) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +57 -177
  3. data/bin/fastlane +4 -2
  4. data/credentials_manager/README.md +1 -1
  5. data/credentials_manager/lib/credentials_manager/account_manager.rb +6 -2
  6. data/deliver/lib/deliver/app_screenshot.rb +0 -4
  7. data/deliver/lib/deliver/commands_generator.rb +1 -1
  8. data/deliver/lib/deliver/detect_values.rb +3 -1
  9. data/deliver/lib/deliver/download_screenshots.rb +8 -1
  10. data/deliver/lib/deliver/html_generator.rb +1 -1
  11. data/deliver/lib/deliver/options.rb +8 -0
  12. data/deliver/lib/deliver/runner.rb +5 -4
  13. data/deliver/lib/deliver/sync_screenshots.rb +27 -28
  14. data/deliver/lib/deliver/upload_app_clip_default_experience_header_images.rb +3 -3
  15. data/deliver/lib/deliver/upload_metadata.rb +34 -16
  16. data/deliver/lib/deliver/upload_screenshots.rb +24 -18
  17. data/docs/README.md +25 -0
  18. data/fastlane/lib/assets/TeamTable.md.erb +28 -0
  19. data/fastlane/lib/fastlane/actions/appaloosa.rb +2 -1
  20. data/fastlane/lib/fastlane/actions/appium.rb +1 -1
  21. data/fastlane/lib/fastlane/actions/apteligent.rb +8 -1
  22. data/fastlane/lib/fastlane/actions/build_and_upload_to_appetize.rb +3 -1
  23. data/fastlane/lib/fastlane/actions/changelog_from_git_commits.rb +7 -2
  24. data/fastlane/lib/fastlane/actions/clean_build_artifacts.rb +3 -0
  25. data/fastlane/lib/fastlane/actions/danger.rb +5 -5
  26. data/fastlane/lib/fastlane/actions/docs/build_app.md +1 -2
  27. data/fastlane/lib/fastlane/actions/docs/create_app_online.md +1 -2
  28. data/fastlane/lib/fastlane/actions/docs/get_certificates.md +0 -2
  29. data/fastlane/lib/fastlane/actions/docs/get_push_certificate.md +7 -3
  30. data/fastlane/lib/fastlane/actions/docs/sync_code_signing.md +13 -3
  31. data/fastlane/lib/fastlane/actions/ensure_no_debug_code.rb +2 -2
  32. data/fastlane/lib/fastlane/actions/get_managed_play_store_publishing_rights.rb +1 -0
  33. data/fastlane/lib/fastlane/actions/github_api.rb +1 -2
  34. data/fastlane/lib/fastlane/actions/hg_commit_version_bump.rb +1 -1
  35. data/fastlane/lib/fastlane/actions/increment_build_number.rb +1 -1
  36. data/fastlane/lib/fastlane/actions/increment_version_number.rb +1 -1
  37. data/fastlane/lib/fastlane/actions/install_xcode_plugin.rb +16 -6
  38. data/fastlane/lib/fastlane/actions/lcov.rb +11 -2
  39. data/fastlane/lib/fastlane/actions/nexus_upload.rb +16 -4
  40. data/fastlane/lib/fastlane/actions/notification.rb +3 -2
  41. data/fastlane/lib/fastlane/actions/oclint.rb +8 -8
  42. data/fastlane/lib/fastlane/actions/push_to_git_remote.rb +9 -4
  43. data/fastlane/lib/fastlane/actions/register_device.rb +1 -1
  44. data/fastlane/lib/fastlane/actions/say.rb +2 -4
  45. data/fastlane/lib/fastlane/actions/set_pod_key.rb +3 -3
  46. data/fastlane/lib/fastlane/actions/sonar.rb +16 -16
  47. data/fastlane/lib/fastlane/actions/sourcedocs.rb +8 -8
  48. data/fastlane/lib/fastlane/actions/spaceship_logs.rb +4 -2
  49. data/fastlane/lib/fastlane/actions/splunkmint.rb +8 -1
  50. data/fastlane/lib/fastlane/actions/swiftlint.rb +6 -3
  51. data/fastlane/lib/fastlane/actions/update_project_provisioning.rb +4 -2
  52. data/fastlane/lib/fastlane/actions/upload_to_app_store.rb +5 -2
  53. data/fastlane/lib/fastlane/actions/upload_to_testflight.rb +5 -2
  54. data/fastlane/lib/fastlane/actions/verify_build.rb +1 -4
  55. data/fastlane/lib/fastlane/actions/verify_pod_keys.rb +3 -1
  56. data/fastlane/lib/fastlane/actions/xcode_server_get_assets.rb +20 -19
  57. data/fastlane/lib/fastlane/actions/xcodebuild.rb +5 -6
  58. data/fastlane/lib/fastlane/actions/zip.rb +2 -1
  59. data/fastlane/lib/fastlane/auto_complete.rb +1 -1
  60. data/fastlane/lib/fastlane/cli_tools_distributor.rb +14 -0
  61. data/fastlane/lib/fastlane/documentation/markdown_docs_generator.rb +23 -0
  62. data/fastlane/lib/fastlane/environment_printer.rb +12 -25
  63. data/fastlane/lib/fastlane/fast_file.rb +2 -1
  64. data/fastlane/lib/fastlane/fastlane_require.rb +5 -1
  65. data/fastlane/lib/fastlane/helper/git_helper.rb +4 -2
  66. data/fastlane/lib/fastlane/helper/sh_helper.rb +25 -7
  67. data/fastlane/lib/fastlane/new_action.rb +1 -1
  68. data/fastlane/lib/fastlane/plugins/plugin_fetcher.rb +1 -1
  69. data/fastlane/lib/fastlane/plugins/plugin_info_collector.rb +1 -1
  70. data/fastlane/lib/fastlane/plugins/plugin_manager.rb +36 -4
  71. data/fastlane/lib/fastlane/plugins/template/%gem_name%.gemspec.erb +1 -1
  72. data/fastlane/lib/fastlane/plugins/template/.github/workflows/test.yml +1 -1
  73. data/fastlane/lib/fastlane/plugins/template/.rubocop.yml +7 -7
  74. data/fastlane/lib/fastlane/swift_lane_manager.rb +22 -4
  75. data/fastlane/lib/fastlane/version.rb +3 -2
  76. data/fastlane/swift/Deliverfile.swift +1 -1
  77. data/fastlane/swift/DeliverfileProtocol.swift +8 -1
  78. data/fastlane/swift/Fastlane.swift +129 -11
  79. data/fastlane/swift/Gymfile.swift +1 -1
  80. data/fastlane/swift/GymfileProtocol.swift +8 -1
  81. data/fastlane/swift/MainProcess.swift +190 -20
  82. data/fastlane/swift/Matchfile.swift +1 -1
  83. data/fastlane/swift/MatchfileProtocol.swift +10 -3
  84. data/fastlane/swift/Precheckfile.swift +1 -1
  85. data/fastlane/swift/PrecheckfileProtocol.swift +1 -1
  86. data/fastlane/swift/Scanfile.swift +1 -1
  87. data/fastlane/swift/ScanfileProtocol.swift +15 -1
  88. data/fastlane/swift/Screengrabfile.swift +1 -1
  89. data/fastlane/swift/ScreengrabfileProtocol.swift +1 -1
  90. data/fastlane/swift/Snapshotfile.swift +1 -1
  91. data/fastlane/swift/SnapshotfileProtocol.swift +8 -1
  92. data/fastlane/swift/formatting/Rakefile +1 -0
  93. data/fastlane/swift/main.swift +4 -1
  94. data/fastlane_core/README.md +1 -1
  95. data/fastlane_core/lib/fastlane_core/analytics/analytics_event_builder.rb +1 -17
  96. data/fastlane_core/lib/fastlane_core/configuration/configuration.rb +23 -8
  97. data/fastlane_core/lib/fastlane_core/device_manager.rb +2 -2
  98. data/fastlane_core/lib/fastlane_core/fastlane_pty.rb +20 -7
  99. data/fastlane_core/lib/fastlane_core/helper.rb +34 -5
  100. data/fastlane_core/lib/fastlane_core/ipa_file_analyser.rb +1 -1
  101. data/fastlane_core/lib/fastlane_core/itunes_transporter.rb +16 -27
  102. data/fastlane_core/lib/fastlane_core/keychain_importer.rb +31 -28
  103. data/fastlane_core/lib/fastlane_core/languages.rb +0 -1
  104. data/fastlane_core/lib/fastlane_core/print_table.rb +5 -2
  105. data/fastlane_core/lib/fastlane_core/project.rb +19 -0
  106. data/fastlane_core/lib/fastlane_core/provisioning_profile.rb +10 -19
  107. data/fastlane_core/lib/fastlane_core/secrets.rb +77 -0
  108. data/fastlane_core/lib/fastlane_core/ui/fastlane_runner.rb +3 -3
  109. data/fastlane_core/lib/fastlane_core/ui/github_issue_inspector_reporter.rb +1 -1
  110. data/fastlane_core/lib/fastlane_core/ui/implementations/shell.rb +2 -1
  111. data/fastlane_core/lib/fastlane_core.rb +1 -0
  112. data/frameit/lib/frameit/device.rb +1 -1
  113. data/frameit/lib/frameit/frame_downloader.rb +2 -0
  114. data/frameit/lib/frameit/runner.rb +3 -2
  115. data/frameit/lib/frameit/screenshot.rb +0 -1
  116. data/gym/lib/gym/generators/build_command_generator.rb +4 -4
  117. data/gym/lib/gym/generators/package_command_generator_xcode7.rb +3 -3
  118. data/gym/lib/gym/options.rb +5 -0
  119. data/gym/lib/gym/runner.rb +1 -1
  120. data/internal/README.md +1 -1
  121. data/match/lib/match/encryption/openssl.rb +6 -2
  122. data/match/lib/match/generator.rb +1 -0
  123. data/match/lib/match/nuke.rb +2 -2
  124. data/match/lib/match/options.rb +13 -5
  125. data/match/lib/match/runner.rb +30 -3
  126. data/match/lib/match/storage/git_storage.rb +44 -11
  127. data/match/lib/match/storage/gitlab/secure_file.rb +2 -1
  128. data/match/lib/match/storage/google_cloud_storage.rb +6 -1
  129. data/match/lib/match/storage/interface.rb +8 -5
  130. data/pem/lib/pem/manager.rb +5 -1
  131. data/pem/lib/pem/module.rb +0 -4
  132. data/pem/lib/pem/options.rb +6 -0
  133. data/pilot/lib/pilot/build_manager.rb +32 -0
  134. data/pilot/lib/pilot/options.rb +8 -0
  135. data/precheck/lib/precheck/rule_processor.rb +1 -0
  136. data/produce/lib/produce/developer_center.rb +49 -2
  137. data/produce/lib/produce/itunes_connect.rb +1 -1
  138. data/produce/lib/produce/module.rb +21 -0
  139. data/produce/lib/produce/options.rb +17 -0
  140. data/produce/lib/produce/service.rb +3 -5
  141. data/produce/lib/produce.rb +0 -1
  142. data/scan/lib/scan/options.rb +12 -0
  143. data/scan/lib/scan/runner.rb +1 -1
  144. data/scan/lib/scan/test_command_generator.rb +12 -9
  145. data/scan/lib/scan/test_result_parser.rb +1 -0
  146. data/scan/lib/scan/xcpretty_reporter_options_generator.rb +2 -2
  147. data/screengrab/lib/screengrab/page.html.erb +12 -7
  148. data/screengrab/lib/screengrab/reports_generator.rb +1 -1
  149. data/sigh/lib/assets/resign.sh +38 -9
  150. data/sigh/lib/sigh/local_manage.rb +1 -1
  151. data/sigh/lib/sigh/options.rb +5 -0
  152. data/sigh/lib/sigh/resign.rb +3 -3
  153. data/sigh/lib/sigh/runner.rb +6 -1
  154. data/snapshot/lib/snapshot/options.rb +5 -0
  155. data/snapshot/lib/snapshot/page.html.erb +17 -12
  156. data/snapshot/lib/snapshot/reports_generator.rb +1 -1
  157. data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher_base.rb +1 -1
  158. data/snapshot/lib/snapshot.rb +0 -2
  159. data/spaceship/README.md +2 -3
  160. data/spaceship/lib/spaceship/base.rb +3 -1
  161. data/spaceship/lib/spaceship/client.rb +159 -19
  162. data/spaceship/lib/spaceship/connect_api/models/app_store_version.rb +16 -0
  163. data/spaceship/lib/spaceship/connect_api/models/bundle_id.rb +13 -2
  164. data/spaceship/lib/spaceship/connect_api/models/bundle_id_capability.rb +6 -0
  165. data/spaceship/lib/spaceship/connect_api/models/profile.rb +7 -5
  166. data/spaceship/lib/spaceship/connect_api/models/routing_app_coverage.rb +75 -0
  167. data/spaceship/lib/spaceship/connect_api/provisioning/provisioning.rb +25 -0
  168. data/spaceship/lib/spaceship/connect_api/token.rb +6 -1
  169. data/spaceship/lib/spaceship/connect_api/tunes/tunes.rb +45 -0
  170. data/spaceship/lib/spaceship/connect_api.rb +1 -0
  171. data/spaceship/lib/spaceship/du/upload_file.rb +4 -3
  172. data/spaceship/lib/spaceship/errors.rb +7 -1
  173. data/spaceship/lib/spaceship/globals.rb +2 -2
  174. data/spaceship/lib/spaceship/portal/merchant.rb +127 -2
  175. data/spaceship/lib/spaceship/portal/portal_client.rb +58 -0
  176. data/spaceship/lib/spaceship/portal/ui/select_team.rb +0 -2
  177. data/spaceship/lib/spaceship/portal/website_push.rb +8 -2
  178. data/spaceship/lib/spaceship/test_flight/client.rb +0 -22
  179. data/spaceship/lib/spaceship/test_flight.rb +0 -1
  180. data/spaceship/lib/spaceship/two_step_or_factor_client.rb +11 -0
  181. data/supply/lib/supply/client.rb +6 -0
  182. data/supply/lib/supply/options.rb +1 -0
  183. data/supply/lib/supply/reader.rb +15 -0
  184. data/supply/lib/supply.rb +0 -1
  185. data/trainer/lib/trainer/xcresult/helper.rb +27 -13
  186. metadata +80 -64
  187. data/produce/lib/produce/available_default_languages.rb +0 -62
  188. data/snapshot/lib/snapshot/screenshot_flatten.rb +0 -20
  189. data/snapshot/lib/snapshot/screenshot_rotate.rb +0 -36
  190. data/spaceship/lib/spaceship/test_flight/app_test_info.rb +0 -40
  191. data/supply/lib/supply/apk_listing.rb +0 -14
  192. /data/fastlane/lib/assets/{custom_action_template.rb → custom_action_template.rb.template} +0 -0
@@ -57,6 +57,21 @@ module FastlaneCore
57
57
  !self.bundler? && !self.contained_fastlane? && !self.homebrew? && !self.mac_app?
58
58
  end
59
59
 
60
+ # How this fastlane was installed, as reported to analytics and printed at startup
61
+ def self.install_method
62
+ if self.bundler?
63
+ 'bundler'
64
+ elsif self.contained_fastlane?
65
+ 'standalone'
66
+ elsif self.homebrew?
67
+ 'homebrew'
68
+ elsif self.mac_app?
69
+ 'mac_app'
70
+ else
71
+ 'gem'
72
+ end
73
+ end
74
+
60
75
  # environment
61
76
  #
62
77
 
@@ -332,18 +347,18 @@ module FastlaneCore
332
347
  # Zips directory
333
348
  def self.zip_directory(path, output_path, contents_only: false, overwrite: false, print: true)
334
349
  if overwrite
335
- overwrite_command = " && rm -f '#{output_path}'"
350
+ overwrite_command = " && rm -f #{output_path.shellescape}"
336
351
  else
337
352
  overwrite_command = ""
338
353
  end
339
354
 
340
355
  if contents_only
341
- command = "cd '#{path}'#{overwrite_command} && zip -r '#{output_path}' *"
356
+ command = "cd #{path.shellescape}#{overwrite_command} && zip -r #{output_path.shellescape} *"
342
357
  else
343
358
  containing_path = File.expand_path("..", path)
344
359
  contents_path = File.basename(path)
345
360
 
346
- command = "cd '#{containing_path}'#{overwrite_command} && zip -r '#{output_path}' '#{contents_path}'"
361
+ command = "cd #{containing_path.shellescape}#{overwrite_command} && zip -r #{output_path.shellescape} #{contents_path.shellescape}"
347
362
  end
348
363
 
349
364
  UI.command(command) unless print
@@ -381,6 +396,8 @@ module FastlaneCore
381
396
  # we set the default here, instead of at the parameters
382
397
  # as we don't want to `UI.message` a rocket that's just there for the loading indicator
383
398
  text ||= "🚀"
399
+ # A spinner left running by a show without a hide could never be stopped once replaced
400
+ @require_fastlane_spinner.stop if @require_fastlane_spinner && !@require_fastlane_spinner.done?
384
401
  @require_fastlane_spinner = TTY::Spinner.new("[:spinner] #{text} ", format: :dots)
385
402
  @require_fastlane_spinner.auto_spin
386
403
  else
@@ -388,12 +405,24 @@ module FastlaneCore
388
405
  end
389
406
  end
390
407
 
391
- def self.hide_loading_indicator
408
+ def self.hide_loading_indicator(success: true)
392
409
  if self.should_show_loading_indicator? && @require_fastlane_spinner
393
- @require_fastlane_spinner.success
410
+ success ? @require_fastlane_spinner.success : @require_fastlane_spinner.error
394
411
  end
395
412
  end
396
413
 
414
+ # Shows the loading indicator while the block runs, and hides it even when the block raises
415
+ def self.with_loading_indicator(text = nil)
416
+ failed = false
417
+ show_loading_indicator(text)
418
+ yield
419
+ rescue Exception # rubocop:disable Lint/RescueException
420
+ failed = true
421
+ raise
422
+ ensure
423
+ hide_loading_indicator(success: !failed)
424
+ end
425
+
397
426
  # files
398
427
  #
399
428
 
@@ -55,7 +55,7 @@ module FastlaneCore
55
55
  end
56
56
 
57
57
  def self.fetch_info_plist_with_rubyzip(path)
58
- Zip::File.open(path, "rb") do |zipfile|
58
+ Zip::File.open(path) do |zipfile|
59
59
  file = zipfile.glob('**/Payload/*.app/Info.plist').first
60
60
  return nil unless file
61
61
  zipfile.read(file)
@@ -9,14 +9,6 @@ require_relative 'helper'
9
9
  require_relative 'fastlane_pty'
10
10
 
11
11
  module FastlaneCore
12
- # The TransporterInputError occurs when you passed wrong inputs to the {Deliver::ItunesTransporter}
13
- class TransporterInputError < StandardError
14
- end
15
- # The TransporterTransferError occurs when some error happens
16
- # while uploading or downloading something from/to iTC
17
- class TransporterTransferError < StandardError
18
- end
19
-
20
12
  # Used internally
21
13
  class TransporterRequiresApplicationSpecificPasswordError < StandardError
22
14
  end
@@ -35,7 +27,7 @@ module FastlaneCore
35
27
 
36
28
  private_constant :ERROR_REGEX, :WARNING_REGEX, :OUTPUT_REGEX, :RETURN_VALUE_REGEX, :SKIP_ERRORS
37
29
 
38
- def build_download_command(username, password, apple_id, destination = "/tmp", provider_short_name = "", jwt = nil)
30
+ def build_download_command(username, password, apple_id, destination = Dir.tmpdir, provider_short_name = "", jwt = nil)
39
31
  not_implemented(__method__)
40
32
  end
41
33
 
@@ -43,11 +35,11 @@ module FastlaneCore
43
35
  not_implemented(__method__)
44
36
  end
45
37
 
46
- def build_upload_command(username, password, source = "/tmp", options = {})
38
+ def build_upload_command(username, password, source = Dir.tmpdir, options = {})
47
39
  not_implemented(__method__)
48
40
  end
49
41
 
50
- def build_verify_command(username, password, source = "/tmp", provider_short_name = "", **kwargs)
42
+ def build_verify_command(username, password, source = Dir.tmpdir, provider_short_name = "", **kwargs)
51
43
  not_implemented(__method__)
52
44
  end
53
45
 
@@ -291,6 +283,7 @@ module FastlaneCore
291
283
 
292
284
  @errors << "The call to the altool completed with a non-zero exit status: #{exit_status}. This indicates a failure." unless exit_status.zero?
293
285
  @errors << "-1 indicates altool exited abnormally; try retrying (see https://github.com/fastlane/fastlane/issues/21535)" if exit_status == -1
286
+ @errors.clear if @all_lines.any? { |line| line.include?("UPLOAD SUCCEEDED with no errors") }
294
287
 
295
288
  unless @errors.empty? || @all_lines.empty?
296
289
  @all_lines.each do |line|
@@ -319,7 +312,7 @@ module FastlaneCore
319
312
  end
320
313
  end
321
314
 
322
- def build_upload_command(username, password, source = "/tmp", options = {})
315
+ def build_upload_command(username, password, source = Dir.tmpdir, options = {})
323
316
  provider_short_name = options.fetch(:provider_short_name, "")
324
317
  provider_public_id = options.fetch(:provider_public_id, "")
325
318
  jwt = options[:jwt]
@@ -351,11 +344,11 @@ module FastlaneCore
351
344
  ].compact.join(' ')
352
345
  end
353
346
 
354
- def build_download_command(username, password, apple_id, destination = "/tmp", provider_short_name = "", jwt = nil)
347
+ def build_download_command(username, password, apple_id, destination = Dir.tmpdir, provider_short_name = "", jwt = nil)
355
348
  raise "This feature has not been implemented yet with altool for Xcode 14"
356
349
  end
357
350
 
358
- def build_verify_command(username, password, source = "/tmp", options = {})
351
+ def build_verify_command(username, password, source = Dir.tmpdir, options = {})
359
352
  provider_short_name = options.fetch(:provider_short_name, "")
360
353
  provider_public_id = options.fetch(:provider_public_id, "")
361
354
  api_key = options[:api_key]
@@ -442,7 +435,7 @@ module FastlaneCore
442
435
  end
443
436
  end
444
437
 
445
- def build_upload_command(username, password, source = "/tmp", options = {})
438
+ def build_upload_command(username, password, source = Dir.tmpdir, options = {})
446
439
  provider_short_name = options.fetch(:provider_short_name, "")
447
440
  jwt = options[:jwt]
448
441
  api_key = options[:api_key]
@@ -458,7 +451,7 @@ module FastlaneCore
458
451
  ].compact.join(' ')
459
452
  end
460
453
 
461
- def build_download_command(username, password, apple_id, destination = "/tmp", provider_short_name = "", jwt = nil)
454
+ def build_download_command(username, password, apple_id, destination = Dir.tmpdir, provider_short_name = "", jwt = nil)
462
455
  [
463
456
  '"' + Helper.transporter_path + '"',
464
457
  "-m lookupMetadata",
@@ -477,7 +470,7 @@ module FastlaneCore
477
470
  ].compact.join(' ')
478
471
  end
479
472
 
480
- def build_verify_command(username, password, source = "/tmp", options = {})
473
+ def build_verify_command(username, password, source = Dir.tmpdir, options = {})
481
474
  provider_short_name = options.fetch(:provider_short_name, "")
482
475
  jwt = options[:jwt]
483
476
  [
@@ -568,7 +561,7 @@ module FastlaneCore
568
561
  end
569
562
  end
570
563
 
571
- def build_upload_command(username, password, source = "/tmp", options = {})
564
+ def build_upload_command(username, password, source = Dir.tmpdir, options = {})
572
565
  provider_short_name = options.fetch(:provider_short_name, "")
573
566
  jwt = options[:jwt]
574
567
  api_key = options[:api_key]
@@ -607,7 +600,7 @@ module FastlaneCore
607
600
  end
608
601
  end
609
602
 
610
- def build_verify_command(username, password, source = "/tmp", options = {})
603
+ def build_verify_command(username, password, source = Dir.tmpdir, options = {})
611
604
  provider_short_name = options.fetch(:provider_short_name, "")
612
605
  jwt = options[:jwt]
613
606
  credential_params = build_credential_params(username, password, jwt, nil, is_default_itms_on_xcode_11?)
@@ -641,7 +634,7 @@ module FastlaneCore
641
634
  end
642
635
  end
643
636
 
644
- def build_download_command(username, password, apple_id, destination = "/tmp", provider_short_name = "", jwt = nil)
637
+ def build_download_command(username, password, apple_id, destination = Dir.tmpdir, provider_short_name = "", jwt = nil)
645
638
  credential_params = build_credential_params(username, password, jwt, nil, is_default_itms_on_xcode_11?)
646
639
  if is_default_itms_on_xcode_11?
647
640
  [
@@ -790,10 +783,10 @@ module FastlaneCore
790
783
  # @param app_id [Integer] The unique App ID
791
784
  # @param dir [String] the path in which the package file should be stored
792
785
  # @return (Bool) True if everything worked fine
793
- # @raise [Deliver::TransporterTransferError] when something went wrong
794
- # when transferring
795
786
  def download(app_id, dir = nil)
796
- dir ||= "/tmp"
787
+ # Dir.tmpdir, not a literal "/tmp": the transporter chdirs into this
788
+ # directory, and "/tmp" is not one on Windows. See fastlane#30184.
789
+ dir ||= Dir.tmpdir
797
790
 
798
791
  password_placeholder = @jwt.nil? ? 'YourPassword' : nil
799
792
  jwt_placeholder = @jwt.nil? ? nil : 'YourJWT'
@@ -829,8 +822,6 @@ module FastlaneCore
829
822
  # @param package_path [String] the path to the package file (used instead of app_id and dir)
830
823
  # @param asset_path [String] the path to the ipa/dmg/pkg file (used instead of package_path if running on macOS)
831
824
  # @return (Bool) True if everything worked fine
832
- # @raise [Deliver::TransporterTransferError] when something went wrong
833
- # when transferring
834
825
  def upload(app_id = nil, dir = nil, package_path: nil, asset_path: nil, platform: nil)
835
826
  raise "app_id and dir are required or package_path or asset_path is required" if (app_id.nil? || dir.nil?) && package_path.nil? && asset_path.nil?
836
827
 
@@ -898,8 +889,6 @@ module FastlaneCore
898
889
  # @param dir [String] the path in which the package file is located
899
890
  # @param package_path [String] the path to the package file (used instead of app_id and dir)
900
891
  # @return (Bool) True if everything worked fine
901
- # @raise [Deliver::TransporterTransferError] when something went wrong
902
- # when transferring
903
892
  def verify(app_id = nil, dir = nil, package_path: nil, asset_path: nil, platform: nil)
904
893
  raise "app_id and dir are required or package_path or asset_path is required" if (app_id.nil? || dir.nil?) && package_path.nil? && asset_path.nil?
905
894
 
@@ -54,37 +54,34 @@ module FastlaneCore
54
54
  command << " 1> /dev/null" # always disable stdout. This can be very verbose, and leak potentially sensitive info
55
55
 
56
56
  # Showing loading indicator as this can take some time if a lot of keys installed
57
- Helper.show_loading_indicator("Setting key partition list... (this can take a minute if there are a lot of keys installed)")
58
-
59
- # Strip keychain password from command output
60
- sensitive_command = command.gsub(password_part, " -k ********")
61
- UI.command(sensitive_command) if output
62
- Open3.popen3(command) do |stdin, stdout, stderr, thrd|
63
- unless thrd.value.success?
64
- err = stderr.read.to_s.strip
65
-
66
- # Inform user when no/wrong password was used as its needed to prevent UI permission popup from Xcode when signing
67
- if err.include?("SecKeychainItemSetAccessWithPassword")
68
- keychain_name = File.basename(keychain_path, ".*")
69
- Security::InternetPassword.delete(server: server_name(keychain_name))
70
-
71
- UI.important("")
72
- UI.important("Could not configure imported keychain item (certificate) to prevent UI permission popup when code signing\n" \
73
- "Check if you supplied the correct `keychain_password` for keychain: `#{keychain_path}`\n" \
74
- "#{err}")
75
- UI.important("")
76
- UI.important("Please look at the following docs to see how to set a keychain password:")
77
- UI.important(" - https://docs.fastlane.tools/actions/sync_code_signing")
78
- UI.important(" - https://docs.fastlane.tools/actions/get_certificates")
79
- else
80
- UI.error(err)
57
+ Helper.with_loading_indicator("Setting key partition list... (this can take a minute if there are a lot of keys installed)") do
58
+ # Strip keychain password from command output
59
+ sensitive_command = command.gsub(password_part, " -k ********")
60
+ UI.command(sensitive_command) if output
61
+ Open3.popen3(command) do |stdin, stdout, stderr, thrd|
62
+ unless thrd.value.success?
63
+ err = stderr.read.to_s.strip
64
+
65
+ # Inform user when no/wrong password was used as its needed to prevent UI permission popup from Xcode when signing
66
+ if err.include?("SecKeychainItemSetAccessWithPassword")
67
+ keychain_name = File.basename(keychain_path, ".*")
68
+ Security::InternetPassword.delete(server: server_name(keychain_name))
69
+
70
+ UI.important("")
71
+ UI.important("Could not configure imported keychain item (certificate) to prevent UI permission popup when code signing\n" \
72
+ "Check if you supplied the correct `keychain_password` for keychain: `#{keychain_path}`\n" \
73
+ "#{err}")
74
+ UI.important("")
75
+ UI.important("Please look at the following docs to see how to set a keychain password:")
76
+ UI.important(" - https://docs.fastlane.tools/actions/sync_code_signing")
77
+ UI.important(" - https://docs.fastlane.tools/actions/get_certificates")
78
+ else
79
+ UI.error(err)
80
+ end
81
81
  end
82
82
  end
83
83
  end
84
84
 
85
- # Hiding after Open3 finishes
86
- Helper.hide_loading_indicator
87
-
88
85
  end
89
86
  end
90
87
 
@@ -98,7 +95,13 @@ module FastlaneCore
98
95
  server = server_name(keychain_name)
99
96
 
100
97
  # Attempt to find password in keychain for keychain
101
- item = Security::InternetPassword.find(server: server)
98
+ begin
99
+ item = Security::InternetPassword.find(server: server)
100
+ rescue Security::Error => ex
101
+ UI.important("Could not read the keychain item #{server}: #{ex.message}")
102
+ item = nil
103
+ end
104
+
102
105
  if item
103
106
  keychain_password = item.password
104
107
  UI.important("Using keychain password from keychain item #{server} in #{keychain_path}")
@@ -8,7 +8,6 @@ module FastlaneCore
8
8
  # The new format used from September 2015 on
9
9
  # This was generated from `Spaceship::Tunes.client.available_languages.sort`
10
10
  # Updates should also be made to:
11
- # - produce/lib/produce/available_default_languages.rb
12
11
  # - spaceship/lib/assets/languageMapping.json
13
12
  # See pull request for example: https://github.com/fastlane/fastlane/pull/14110
14
13
  ALL_LANGUAGES = %w[ar-SA bn-BD ca cs da de-DE el en-AU en-CA en-GB en-US es-ES es-MX fi fr-CA fr-FR gu-IN he hi hr hu id it ja kn-IN ko ml-IN mr-IN ms nl-NL no or-IN pa-IN pl pt-BR pt-PT ro ru sk sl-SI sv ta-IN te-IN th tr uk ur-PK vi zh-Hans zh-Hant]
@@ -1,5 +1,6 @@
1
1
  require_relative 'configuration/configuration'
2
2
  require_relative 'helper'
3
+ require_relative 'secrets'
3
4
 
4
5
  module FastlaneCore
5
6
  class PrintTable
@@ -87,6 +88,8 @@ module FastlaneCore
87
88
  end
88
89
 
89
90
  def transform_output(rows, transform: :newline)
91
+ # Masked before wrapping, which would split a secret across lines
92
+ rows = rows.map { |row| row.map { |column| column.kind_of?(String) ? Secrets.mask(column) : column } }
90
93
  return rows unless should_transform?
91
94
 
92
95
  require 'fastlane_core/string_filters'
@@ -110,7 +113,7 @@ module FastlaneCore
110
113
  return return_array
111
114
  end
112
115
 
113
- def collect_rows(options: nil, hide_keys: [], mask_keys: [], prefix: '', mask: '********')
116
+ def collect_rows(options: nil, hide_keys: [], mask_keys: [], prefix: '', mask: nil)
114
117
  rows = []
115
118
 
116
119
  options.each do |key, value|
@@ -118,7 +121,7 @@ module FastlaneCore
118
121
  next if value.nil?
119
122
  next if value.to_s == ""
120
123
  next if hide_keys.include?(prefixed_key)
121
- value = mask if mask_keys.include?(prefixed_key)
124
+ value = mask || Secrets.label(key) if mask_keys.include?(prefixed_key)
122
125
 
123
126
  if value.respond_to?(:key)
124
127
  rows.concat(self.collect_rows(options: value, hide_keys: hide_keys, mask_keys: mask_keys, prefix: "#{prefix}#{key}.", mask: mask))
@@ -412,6 +412,16 @@ module FastlaneCore
412
412
  # @param [String] The key of which we want the value for (e.g. "PRODUCT_NAME")
413
413
  def build_settings(key: nil, optional: true)
414
414
  unless @build_settings
415
+ if (disallowed_by = xcodebuild_settings_lookup_disallowed_by)
416
+ message = "Could not read the '#{key}' build setting: fetching build settings by running" \
417
+ " `xcodebuild -showBuildSettings` is disallowed by #{disallowed_by}."
418
+ trigger = caller.find { |frame| !frame.start_with?(__FILE__) }
419
+ message += "\nThe build setting lookup was triggered by: #{trigger}" if trigger
420
+ message += "\nTo fix this, manually specify the option whose automatic detection required the '#{key}' build setting," \
421
+ " or disable #{disallowed_by} to allow fastlane to fetch it automatically."
422
+ UI.user_error!(message)
423
+ end
424
+
415
425
  if is_workspace
416
426
  if schemes.count == 0
417
427
  UI.user_error!("Could not find any schemes for Xcode workspace at path '#{self.path}'. Please make sure that the schemes you want to use are marked as `Shared` from Xcode.")
@@ -563,5 +573,14 @@ module FastlaneCore
563
573
  def automated_scheme_selection?
564
574
  FastlaneCore::Env.truthy?("AUTOMATED_SCHEME_SELECTION")
565
575
  end
576
+
577
+ # Returns a description of what disallowed fetching build settings via the
578
+ # (potentially slow on large projects) `xcodebuild -showBuildSettings` command,
579
+ # or nil if the lookup is allowed
580
+ def xcodebuild_settings_lookup_disallowed_by
581
+ return "the FASTLANE_DISALLOW_XCODEBUILD_SETTINGS_LOOKUP environment variable" if FastlaneCore::Env.truthy?("FASTLANE_DISALLOW_XCODEBUILD_SETTINGS_LOOKUP")
582
+ return "the `disallow_xcodebuild_settings_lookup` option" if options[:disallow_xcodebuild_settings_lookup]
583
+ nil
584
+ end
566
585
  end
567
586
  end
@@ -106,26 +106,17 @@ module FastlaneCore
106
106
 
107
107
  private
108
108
 
109
+ # keychain_path is ignored: unlike `security cms -D`, this imports no certificate into a keychain. See #30186.
109
110
  def decode(path, keychain_path = nil)
110
- require 'tmpdir'
111
- Dir.mktmpdir('fastlane') do |dir|
112
- err = "#{dir}/cms.err"
113
- # we want to prevent the error output to mix up with the standard output because of
114
- # /dev/null: https://github.com/fastlane/fastlane/issues/6387
115
- if Helper.mac?
116
- if keychain_path.nil?
117
- decoded = `security cms -D -i "#{path}" 2> #{err}`
118
- else
119
- decoded = `security cms -D -i "#{path}" -k "#{keychain_path.shellescape}" 2> #{err}`
120
- end
121
- else
122
- # `security` only works on Mac, fallback to `openssl`
123
- # via https://stackoverflow.com/a/14379814/252627
124
- decoded = `openssl smime -inform der -verify -noverify -in #{path.shellescape} 2> #{err}`
125
- end
126
- UI.error("Failure to decode #{path}. Exit: #{$?.exitstatus}: #{File.read(err)}") if $?.exitstatus != 0
127
- decoded
128
- end
111
+ require 'openssl'
112
+ profile = OpenSSL::PKCS7.new(File.binread(path))
113
+ # NOVERIFY skips the certificate chain, which `security cms -D` does not enforce either, but still checks the signature.
114
+ # A mismatch is decoded anyway, as `security cms -D` did: match/spec/fixtures/test.provisionprofile has one.
115
+ UI.important("The signature of #{path} does not match its content: it was changed after it was signed") unless profile.verify([], OpenSSL::X509::Store.new, nil, OpenSSL::PKCS7::NOVERIFY)
116
+ profile.data.to_s
117
+ rescue ArgumentError, OpenSSL::PKCS7::PKCS7Error, SystemCallError => e
118
+ UI.error("Failure to decode #{path}: #{e.message}")
119
+ ""
129
120
  end
130
121
  end
131
122
  end
@@ -0,0 +1,77 @@
1
+ require_relative 'core_ext/shellwords'
2
+ require_relative 'env'
3
+
4
+ module FastlaneCore
5
+ # Values hidden from everything fastlane prints. Only output is masked: commands still receive the real value.
6
+ # FASTLANE_DISABLE_SECRET_MASKING turns it off, for debugging.
7
+ module Secrets
8
+ MASK = '********'.freeze
9
+ # Shorter values would mask unrelated text.
10
+ MIN_LENGTH = 4
11
+
12
+ # Masks what is written to an IO, so `puts`, `print`, `abort` and Logger output are covered.
13
+ module OutputFilter
14
+ def write(*args)
15
+ super(*args.map { |arg| Secrets.mask(arg.to_s) })
16
+ end
17
+ end
18
+
19
+ class << self
20
+ # Registers a secret, or every String inside a Hash or Array, together with the escaped forms `sh` prints.
21
+ # A name, such as the option's key, replaces it with `<NAME>_REDACTED` rather than MASK.
22
+ def register(value, name: nil)
23
+ case value
24
+ when Hash then value.each_value { |v| register(v, name: name) }
25
+ when Array then value.each { |v| register(v, name: name) }
26
+ when String
27
+ return if value.length < MIN_LENGTH
28
+
29
+ replacement = name ? label(name) : MASK
30
+ [value, Shellwords.escape(value), value.shellescape].each do |form|
31
+ labels[form.b] = replacement if [nil, MASK].include?(labels[form.b])
32
+ end
33
+ @pattern = nil
34
+ install_output_filter unless disabled?
35
+ end
36
+ end
37
+
38
+ def mask(text)
39
+ return text if labels.empty? || !text.kind_of?(String) || disabled?
40
+
41
+ # One pass: a name put in place of a secret is not masked again by a shorter secret it contains
42
+ text.b.gsub(pattern) { |match| labels[match] }.force_encoding(text.encoding)
43
+ end
44
+
45
+ # What a secret registered under this name is replaced with, e.g. API_TOKEN_REDACTED
46
+ def label(name)
47
+ "#{name.to_s.upcase}_REDACTED"
48
+ end
49
+
50
+ def labels
51
+ @labels ||= {}
52
+ end
53
+
54
+ def clear
55
+ @labels = {}
56
+ @pattern = nil
57
+ end
58
+
59
+ def disabled?
60
+ FastlaneCore::Env.truthy?('FASTLANE_DISABLE_SECRET_MASKING')
61
+ end
62
+
63
+ private
64
+
65
+ # Longest first, so a secret wins over a shorter one it contains
66
+ def pattern
67
+ @pattern ||= Regexp.union(labels.keys.sort_by { |v| -v.length })
68
+ end
69
+
70
+ def install_output_filter
71
+ [$stdout, $stderr].each do |io|
72
+ io.singleton_class.prepend(OutputFilter) unless io.singleton_class.include?(OutputFilter)
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -265,11 +265,11 @@ module Commander
265
265
  ui.error("- If you use system Ruby:")
266
266
  ui.error(" - Run `brew update && brew install ruby`")
267
267
  ui.error("- If you use rbenv with ruby-build:")
268
- ui.error(" - Run `brew update && brew upgrade ruby-build && rbenv install 2.3.1`")
269
- ui.error(" - Run `rbenv global 2.3.1` to make it the new global default Ruby version")
268
+ ui.error(" - Run `brew update && brew upgrade ruby-build && rbenv install #{Fastlane::SUGGESTED_MINIMUM_RUBY}`")
269
+ ui.error(" - Run `rbenv global #{Fastlane::SUGGESTED_MINIMUM_RUBY}` to make it the new global default Ruby version")
270
270
  ui.error("- If you use rvm:")
271
271
  ui.error(" - First run `rvm osx-ssl-certs update all`")
272
- ui.error(" - Then run `rvm reinstall ruby-2.3.1 --with-openssl-dir=/usr/local`")
272
+ ui.error(" - Then run `rvm reinstall ruby-#{Fastlane::SUGGESTED_MINIMUM_RUBY}`")
273
273
  ui.error("")
274
274
  ui.error("If that doesn't fix your issue, please google for the following error message:")
275
275
  ui.error(" '#{e}'")
@@ -20,7 +20,7 @@ module Fastlane
20
20
  report.issues[0..(NUMBER_OF_ISSUES_INLINE - 1)].each { |issue| print_issue_full(issue) }
21
21
 
22
22
  if report.issues.count > NUMBER_OF_ISSUES_INLINE
23
- report.url.sub!('\'', '%27')
23
+ report.url.gsub!('\'', '%27')
24
24
  puts("and #{report.total_results - NUMBER_OF_ISSUES_INLINE} more at: #{report.url}")
25
25
  puts("")
26
26
  end
@@ -1,6 +1,7 @@
1
1
  require_relative '../../helper'
2
2
  require_relative '../../globals'
3
3
  require_relative '../../env'
4
+ require_relative '../../secrets'
4
5
 
5
6
  require_relative '../interface'
6
7
 
@@ -23,7 +24,7 @@ module FastlaneCore
23
24
  end
24
25
 
25
26
  @log.formatter = proc do |severity, datetime, progname, msg|
26
- "#{format_string(datetime, severity)}#{msg}\n"
27
+ "#{format_string(datetime, severity)}#{Secrets.mask(msg.to_s)}\n"
27
28
  end
28
29
 
29
30
  @log
@@ -2,6 +2,7 @@ require_relative 'fastlane_core/globals'
2
2
  # Ruby monkey-patches - should be before almost all else
3
3
  require_relative 'fastlane_core/core_ext/string'
4
4
  require_relative 'fastlane_core/core_ext/shellwords'
5
+ require_relative 'fastlane_core/secrets'
5
6
 
6
7
  require_relative 'fastlane_core/analytics/action_completion_context'
7
8
  require_relative 'fastlane_core/analytics/action_launch_context'
@@ -15,7 +15,7 @@ module Frameit
15
15
  attr_reader :priority_config_key
16
16
 
17
17
  def initialize(id, formatted_name, priority, resolutions, density_ppi, default_color, platform = Platform::IOS, deliver_screen_id = nil, priority_config_key = nil)
18
- Raise("Priority mustn't be higher than #{REQUIRED_PRIORITY}") if priority > REQUIRED_PRIORITY
18
+ raise "Priority mustn't be higher than #{REQUIRED_PRIORITY}" if priority > REQUIRED_PRIORITY
19
19
  @id = id
20
20
  @deliver_screen_id = deliver_screen_id
21
21
  @formatted_name = formatted_name
@@ -20,6 +20,8 @@ module Frameit
20
20
 
21
21
  files = JSON.parse(download_file("files.json"))
22
22
  files.each_with_index do |current, index|
23
+ # files.json is downloaded: only accept plain file names, so nothing is written outside templates_path
24
+ UI.user_error!("Unexpected frame file name '#{current}'") if current.include?("/") || current.include?("\\") || current.start_with?(".")
23
25
  content = download_file(current, txt: "#{index + 1} of #{files.count} files")
24
26
  File.binwrite(File.join(templates_path, current), content)
25
27
  end
@@ -38,8 +38,9 @@ module Frameit
38
38
  if editor.should_skip?
39
39
  UI.message("Skipping framing of screenshot #{screenshot.path}. No title provided in your Framefile.json or title.strings.")
40
40
  else
41
- Helper.show_loading_indicator("Framing screenshot '#{full_path}'")
42
- editor.frame!
41
+ Helper.with_loading_indicator("Framing screenshot '#{full_path}'") do
42
+ editor.frame!
43
+ end
43
44
  end
44
45
  rescue => ex
45
46
  UI.error(ex.to_s)
@@ -48,7 +48,6 @@ module Frameit
48
48
  # Device name for a given screen size. Used to use the correct template
49
49
  def device_name
50
50
  @device.formatted_name
51
- # rubocop:enable Require/MissingRequireStatement
52
51
  end
53
52
 
54
53
  def default_color
@@ -34,11 +34,11 @@ module Gym
34
34
 
35
35
  options = []
36
36
  options += project_path_array
37
- options << "-sdk '#{config[:sdk]}'" if config[:sdk]
38
- options << "-toolchain '#{config[:toolchain]}'" if config[:toolchain]
39
- options << "-destination '#{config[:destination]}'" if config[:destination]
37
+ options << "-sdk #{config[:sdk].shellescape}" if config[:sdk]
38
+ options << "-toolchain #{config[:toolchain].shellescape}" if config[:toolchain]
39
+ options << "-destination #{config[:destination].shellescape}" if config[:destination]
40
40
  options << "-archivePath #{archive_path.shellescape}" unless config[:skip_archive]
41
- options << "-resultBundlePath '#{result_bundle_path}'" if config[:result_bundle]
41
+ options << "-resultBundlePath #{result_bundle_path.shellescape}" if config[:result_bundle]
42
42
  options << "-showBuildTimingSummary" if config[:build_timing_summary]
43
43
  if config[:use_system_scm] && !options.include?("-scmProvider system")
44
44
  options << "-scmProvider system"
@@ -33,10 +33,10 @@ module Gym
33
33
  config = Gym.config
34
34
 
35
35
  options = []
36
- options << "-exportOptionsPlist '#{config_path}'"
36
+ options << "-exportOptionsPlist #{config_path.shellescape}"
37
37
  options << "-archivePath #{BuildCommandGenerator.archive_path.shellescape}"
38
- options << "-exportPath '#{temporary_output_path}'"
39
- options << "-toolchain '#{config[:toolchain]}'" if config[:toolchain]
38
+ options << "-exportPath #{temporary_output_path.shellescape}"
39
+ options << "-toolchain #{config[:toolchain].shellescape}" if config[:toolchain]
40
40
  options << config[:export_xcargs] if config[:export_xcargs]
41
41
  options << config[:xcargs] if config[:xcargs]
42
42