fastlane 2.240.1 → 2.241.1

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 (157) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +51 -171
  3. data/bin/fastlane +4 -2
  4. data/credentials_manager/README.md +1 -1
  5. data/deliver/lib/deliver/app_screenshot.rb +8 -4
  6. data/deliver/lib/deliver/commands_generator.rb +1 -1
  7. data/deliver/lib/deliver/download_screenshots.rb +8 -1
  8. data/deliver/lib/deliver/sync_screenshots.rb +27 -28
  9. data/deliver/lib/deliver/upload_app_clip_default_experience_header_images.rb +3 -3
  10. data/deliver/lib/deliver/upload_metadata.rb +12 -16
  11. data/deliver/lib/deliver/upload_screenshots.rb +12 -14
  12. data/docs/README.md +25 -0
  13. data/fastlane/lib/assets/TeamTable.md.erb +28 -0
  14. data/fastlane/lib/fastlane/actions/appaloosa.rb +2 -1
  15. data/fastlane/lib/fastlane/actions/appium.rb +1 -1
  16. data/fastlane/lib/fastlane/actions/apteligent.rb +8 -1
  17. data/fastlane/lib/fastlane/actions/build_and_upload_to_appetize.rb +1 -1
  18. data/fastlane/lib/fastlane/actions/clean_build_artifacts.rb +3 -0
  19. data/fastlane/lib/fastlane/actions/danger.rb +5 -5
  20. data/fastlane/lib/fastlane/actions/docs/build_app.md +1 -2
  21. data/fastlane/lib/fastlane/actions/docs/create_app_online.md +1 -2
  22. data/fastlane/lib/fastlane/actions/docs/get_certificates.md +0 -2
  23. data/fastlane/lib/fastlane/actions/docs/get_push_certificate.md +1 -3
  24. data/fastlane/lib/fastlane/actions/docs/sync_code_signing.md +13 -3
  25. data/fastlane/lib/fastlane/actions/ensure_no_debug_code.rb +2 -2
  26. data/fastlane/lib/fastlane/actions/get_managed_play_store_publishing_rights.rb +1 -0
  27. data/fastlane/lib/fastlane/actions/github_api.rb +1 -2
  28. data/fastlane/lib/fastlane/actions/hg_commit_version_bump.rb +1 -1
  29. data/fastlane/lib/fastlane/actions/increment_build_number.rb +1 -1
  30. data/fastlane/lib/fastlane/actions/increment_version_number.rb +1 -1
  31. data/fastlane/lib/fastlane/actions/install_xcode_plugin.rb +16 -6
  32. data/fastlane/lib/fastlane/actions/lcov.rb +9 -2
  33. data/fastlane/lib/fastlane/actions/nexus_upload.rb +16 -4
  34. data/fastlane/lib/fastlane/actions/notification.rb +3 -2
  35. data/fastlane/lib/fastlane/actions/oclint.rb +8 -8
  36. data/fastlane/lib/fastlane/actions/push_to_git_remote.rb +9 -4
  37. data/fastlane/lib/fastlane/actions/register_device.rb +1 -1
  38. data/fastlane/lib/fastlane/actions/say.rb +2 -4
  39. data/fastlane/lib/fastlane/actions/set_pod_key.rb +3 -3
  40. data/fastlane/lib/fastlane/actions/sonar.rb +16 -16
  41. data/fastlane/lib/fastlane/actions/sourcedocs.rb +8 -8
  42. data/fastlane/lib/fastlane/actions/splunkmint.rb +8 -1
  43. data/fastlane/lib/fastlane/actions/update_project_provisioning.rb +1 -1
  44. data/fastlane/lib/fastlane/actions/upload_to_app_store.rb +5 -2
  45. data/fastlane/lib/fastlane/actions/upload_to_testflight.rb +5 -2
  46. data/fastlane/lib/fastlane/actions/verify_build.rb +1 -4
  47. data/fastlane/lib/fastlane/actions/verify_pod_keys.rb +3 -1
  48. data/fastlane/lib/fastlane/actions/xcode_server_get_assets.rb +20 -19
  49. data/fastlane/lib/fastlane/actions/xcodebuild.rb +5 -6
  50. data/fastlane/lib/fastlane/actions/zip.rb +2 -1
  51. data/fastlane/lib/fastlane/auto_complete.rb +1 -1
  52. data/fastlane/lib/fastlane/cli_tools_distributor.rb +14 -0
  53. data/fastlane/lib/fastlane/documentation/markdown_docs_generator.rb +23 -0
  54. data/fastlane/lib/fastlane/environment_printer.rb +12 -25
  55. data/fastlane/lib/fastlane/fast_file.rb +2 -1
  56. data/fastlane/lib/fastlane/fastlane_require.rb +5 -1
  57. data/fastlane/lib/fastlane/helper/sh_helper.rb +16 -6
  58. data/fastlane/lib/fastlane/new_action.rb +1 -1
  59. data/fastlane/lib/fastlane/plugins/plugin_fetcher.rb +1 -1
  60. data/fastlane/lib/fastlane/plugins/plugin_info_collector.rb +1 -1
  61. data/fastlane/lib/fastlane/plugins/plugin_manager.rb +36 -4
  62. data/fastlane/lib/fastlane/plugins/template/%gem_name%.gemspec.erb +1 -1
  63. data/fastlane/lib/fastlane/plugins/template/.github/workflows/test.yml +1 -1
  64. data/fastlane/lib/fastlane/plugins/template/.rubocop.yml +3 -7
  65. data/fastlane/lib/fastlane/swift_lane_manager.rb +22 -4
  66. data/fastlane/lib/fastlane/version.rb +3 -2
  67. data/fastlane/swift/Deliverfile.swift +1 -1
  68. data/fastlane/swift/DeliverfileProtocol.swift +1 -1
  69. data/fastlane/swift/Fastlane.swift +39 -9
  70. data/fastlane/swift/Gymfile.swift +1 -1
  71. data/fastlane/swift/GymfileProtocol.swift +1 -1
  72. data/fastlane/swift/MainProcess.swift +190 -20
  73. data/fastlane/swift/Matchfile.swift +1 -1
  74. data/fastlane/swift/MatchfileProtocol.swift +10 -3
  75. data/fastlane/swift/Precheckfile.swift +1 -1
  76. data/fastlane/swift/PrecheckfileProtocol.swift +1 -1
  77. data/fastlane/swift/Scanfile.swift +1 -1
  78. data/fastlane/swift/ScanfileProtocol.swift +8 -1
  79. data/fastlane/swift/Screengrabfile.swift +1 -1
  80. data/fastlane/swift/ScreengrabfileProtocol.swift +1 -1
  81. data/fastlane/swift/Snapshotfile.swift +1 -1
  82. data/fastlane/swift/SnapshotfileProtocol.swift +1 -1
  83. data/fastlane/swift/formatting/Rakefile +1 -0
  84. data/fastlane/swift/main.swift +4 -1
  85. data/fastlane_core/README.md +1 -1
  86. data/fastlane_core/lib/fastlane_core/analytics/analytics_event_builder.rb +1 -17
  87. data/fastlane_core/lib/fastlane_core/configuration/configuration.rb +11 -8
  88. data/fastlane_core/lib/fastlane_core/device_manager.rb +2 -2
  89. data/fastlane_core/lib/fastlane_core/helper.rb +34 -5
  90. data/fastlane_core/lib/fastlane_core/itunes_transporter.rb +0 -14
  91. data/fastlane_core/lib/fastlane_core/keychain_importer.rb +24 -27
  92. data/fastlane_core/lib/fastlane_core/languages.rb +0 -1
  93. data/fastlane_core/lib/fastlane_core/print_table.rb +5 -2
  94. data/fastlane_core/lib/fastlane_core/provisioning_profile.rb +10 -19
  95. data/fastlane_core/lib/fastlane_core/secrets.rb +77 -0
  96. data/fastlane_core/lib/fastlane_core/ui/fastlane_runner.rb +3 -3
  97. data/fastlane_core/lib/fastlane_core/ui/github_issue_inspector_reporter.rb +1 -1
  98. data/fastlane_core/lib/fastlane_core/ui/implementations/shell.rb +2 -1
  99. data/fastlane_core/lib/fastlane_core.rb +1 -0
  100. data/frameit/lib/frameit/device.rb +1 -1
  101. data/frameit/lib/frameit/frame_downloader.rb +2 -0
  102. data/frameit/lib/frameit/runner.rb +3 -2
  103. data/frameit/lib/frameit/screenshot.rb +0 -1
  104. data/gym/lib/gym/generators/build_command_generator.rb +4 -4
  105. data/gym/lib/gym/generators/package_command_generator_xcode7.rb +3 -3
  106. data/gym/lib/gym/runner.rb +1 -1
  107. data/internal/README.md +1 -1
  108. data/match/lib/match/generator.rb +1 -0
  109. data/match/lib/match/options.rb +13 -5
  110. data/match/lib/match/storage/git_storage.rb +43 -7
  111. data/match/lib/match/storage/gitlab/secure_file.rb +2 -1
  112. data/pem/lib/pem/module.rb +0 -4
  113. data/precheck/lib/precheck/rule_processor.rb +1 -0
  114. data/produce/lib/produce/itunes_connect.rb +1 -1
  115. data/produce/lib/produce/service.rb +0 -1
  116. data/produce/lib/produce.rb +0 -1
  117. data/scan/lib/scan/options.rb +7 -0
  118. data/scan/lib/scan/runner.rb +1 -1
  119. data/scan/lib/scan/test_command_generator.rb +12 -9
  120. data/scan/lib/scan/test_result_parser.rb +1 -0
  121. data/scan/lib/scan/xcpretty_reporter_options_generator.rb +2 -2
  122. data/screengrab/lib/screengrab/page.html.erb +12 -7
  123. data/screengrab/lib/screengrab/reports_generator.rb +1 -1
  124. data/sigh/lib/assets/resign.sh +17 -0
  125. data/sigh/lib/sigh/local_manage.rb +1 -1
  126. data/sigh/lib/sigh/options.rb +5 -0
  127. data/sigh/lib/sigh/resign.rb +3 -3
  128. data/sigh/lib/sigh/runner.rb +6 -1
  129. data/snapshot/lib/snapshot/page.html.erb +17 -12
  130. data/snapshot/lib/snapshot/reports_generator.rb +3 -1
  131. data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher_base.rb +1 -1
  132. data/snapshot/lib/snapshot.rb +0 -2
  133. data/spaceship/README.md +2 -3
  134. data/spaceship/lib/spaceship/base.rb +3 -1
  135. data/spaceship/lib/spaceship/client.rb +65 -47
  136. data/spaceship/lib/spaceship/connect_api/models/app_screenshot_set.rb +2 -0
  137. data/spaceship/lib/spaceship/connect_api/models/profile.rb +7 -5
  138. data/spaceship/lib/spaceship/connect_api/provisioning/provisioning.rb +9 -0
  139. data/spaceship/lib/spaceship/du/upload_file.rb +1 -1
  140. data/spaceship/lib/spaceship/errors.rb +7 -1
  141. data/spaceship/lib/spaceship/globals.rb +2 -2
  142. data/spaceship/lib/spaceship/portal/merchant.rb +127 -2
  143. data/spaceship/lib/spaceship/portal/portal_client.rb +58 -0
  144. data/spaceship/lib/spaceship/portal/ui/select_team.rb +0 -2
  145. data/spaceship/lib/spaceship/portal/website_push.rb +8 -2
  146. data/spaceship/lib/spaceship/test_flight/client.rb +0 -22
  147. data/spaceship/lib/spaceship/test_flight.rb +0 -1
  148. data/spaceship/lib/spaceship/two_step_or_factor_client.rb +11 -0
  149. data/supply/lib/supply/options.rb +1 -0
  150. data/supply/lib/supply.rb +0 -1
  151. metadata +55 -37
  152. data/produce/lib/produce/available_default_languages.rb +0 -62
  153. data/snapshot/lib/snapshot/screenshot_flatten.rb +0 -20
  154. data/snapshot/lib/snapshot/screenshot_rotate.rb +0 -36
  155. data/spaceship/lib/spaceship/test_flight/app_test_info.rb +0 -40
  156. data/supply/lib/supply/apk_listing.rb +0 -14
  157. /data/fastlane/lib/assets/{custom_action_template.rb → custom_action_template.rb.template} +0 -0
@@ -160,14 +160,14 @@ module Match
160
160
  FastlaneCore::ConfigItem.new(key: :git_basic_authorization,
161
161
  env_name: "MATCH_GIT_BASIC_AUTHORIZATION",
162
162
  sensitive: true,
163
- description: "Use a basic authorization header to access the git repo (e.g.: access via HTTPS, GitHub Actions, etc), usually a string in Base64",
163
+ description: "Use a basic authorization header to access the git repo (e.g.: access via HTTPS, GitHub Actions, etc), usually a string in Base64. Needs git 2.31 or later",
164
164
  conflicting_options: [:git_bearer_authorization, :git_private_key],
165
165
  optional: true,
166
166
  default_value: nil),
167
167
  FastlaneCore::ConfigItem.new(key: :git_bearer_authorization,
168
168
  env_name: "MATCH_GIT_BEARER_AUTHORIZATION",
169
169
  sensitive: true,
170
- description: "Use a bearer authorization header to access the git repo (e.g.: access to an Azure DevOps repository), usually a string in Base64",
170
+ description: "Use a bearer authorization header to access the git repo (e.g.: access to an Azure DevOps repository), usually a string in Base64. Needs git 2.31 or later",
171
171
  conflicting_options: [:git_basic_authorization, :git_private_key],
172
172
  optional: true,
173
173
  default_value: nil),
@@ -209,7 +209,8 @@ module Match
209
209
  FastlaneCore::ConfigItem.new(key: :s3_access_key,
210
210
  env_name: "MATCH_S3_ACCESS_KEY",
211
211
  description: "S3 access key",
212
- optional: true),
212
+ optional: true,
213
+ sensitive: true),
213
214
  FastlaneCore::ConfigItem.new(key: :s3_secret_access_key,
214
215
  env_name: "MATCH_S3_SECRET_ACCESS_KEY",
215
216
  description: "S3 secret access key",
@@ -247,11 +248,13 @@ module Match
247
248
  FastlaneCore::ConfigItem.new(key: :job_token,
248
249
  env_name: "CI_JOB_TOKEN",
249
250
  description: "GitLab CI_JOB_TOKEN",
250
- optional: true),
251
+ optional: true,
252
+ sensitive: true),
251
253
  FastlaneCore::ConfigItem.new(key: :private_token,
252
254
  env_name: "PRIVATE_TOKEN",
253
255
  description: "GitLab Access Token",
254
- optional: true),
256
+ optional: true,
257
+ sensitive: true),
255
258
 
256
259
  # Keychain
257
260
  FastlaneCore::ConfigItem.new(key: :keychain_name,
@@ -374,6 +377,11 @@ module Match
374
377
  description: "Force encryption to use legacy cbc algorithm for backwards compatibility with older match versions",
375
378
  type: Boolean,
376
379
  default_value: false),
380
+ FastlaneCore::ConfigItem.new(key: :offline_profile,
381
+ env_name: "MATCH_OFFLINE_PROFILE",
382
+ description: "Enable profile with 'Offline Support' (7 day validity). Requires Apple ID login, not supported with App Store Connect API key authentication",
383
+ type: Boolean,
384
+ default_value: false),
377
385
 
378
386
  # other
379
387
  FastlaneCore::ConfigItem.new(key: :verbose,
@@ -1,4 +1,5 @@
1
1
  require 'fastlane_core/command_executor'
2
+ require 'open3'
2
3
 
3
4
  require_relative '../module'
4
5
  require_relative './interface'
@@ -7,6 +8,9 @@ module Match
7
8
  module Storage
8
9
  # Store the code signing identities in a git repo
9
10
  class GitStorage < Interface
11
+ DEFAULT_BRANCH = "main"
12
+ PRIVATE_KEY_ENV = "MATCH_SSH_ADD_PRIVATE_KEY"
13
+
10
14
  # User provided values
11
15
  attr_accessor :git_url
12
16
  attr_accessor :shallow_clone
@@ -85,11 +89,6 @@ module Match
85
89
  self.working_directory = Dir.mktmpdir
86
90
 
87
91
  command = "git clone #{self.git_url.shellescape} #{self.working_directory.shellescape}"
88
- # HTTP headers are supposed to be case-insensitive but
89
- # Bitbucket requires `Authorization: Basic` and `Authorization Bearer` to work
90
- # https://github.com/fastlane/fastlane/pull/15928
91
- command << " -c http.extraheader='Authorization: Basic #{self.git_basic_authorization}'" unless self.git_basic_authorization.nil?
92
- command << " -c http.extraheader='Authorization: Bearer #{self.git_bearer_authorization}'" unless self.git_bearer_authorization.nil?
93
92
 
94
93
  if self.shallow_clone
95
94
  command << " --depth 1"
@@ -165,8 +164,10 @@ module Match
165
164
  def generate_matchfile_content
166
165
  UI.important("Please create a new, private git repository to store the certificates and profiles there")
167
166
  url = UI.input("URL of the Git Repo: ")
167
+ branch = UI.input("Branch of the Git Repo (leave blank to use '#{DEFAULT_BRANCH}'): ").to_s.strip
168
+ branch = DEFAULT_BRANCH if branch.empty?
168
169
 
169
- return "git_url(\"#{url}\")"
170
+ return "git_url(\"#{url}\")\ngit_branch(\"#{branch}\")"
170
171
  end
171
172
 
172
173
  def list_files(file_name: "", file_ext: "")
@@ -178,7 +179,8 @@ module Match
178
179
  ssh_add = File.expand_path(self.git_private_key).shellescape.to_s
179
180
  else
180
181
  UI.message("Private key file does not exist, will continue by using it as a raw key.")
181
- ssh_add = "- <<< \"#{self.git_private_key}\""
182
+ # From the environment (git_env_values), so the key is not on bash's command line
183
+ ssh_add = "- <<< \"$#{PRIVATE_KEY_ENV}\""
182
184
  end
183
185
  return "ssh-agent bash -c 'ssh-add #{ssh_add}; #{command}'"
184
186
  end
@@ -264,9 +266,43 @@ module Match
264
266
  def git_env_values
265
267
  env_values = { 'GIT_TERMINAL_PROMPT' => '0' }
266
268
  env_values['GIT_SSH_COMMAND'] = non_interactive_git_ssh_command
269
+ env_values[PRIVATE_KEY_ENV] = self.git_private_key unless self.git_private_key.nil?
270
+ env_values.merge(authorization_env_values)
271
+ end
272
+
273
+ # Through git's environment (git 2.31+), so the header is neither on the command line nor stored in .git/config
274
+ def authorization_env_values
275
+ headers = []
276
+ # HTTP headers are supposed to be case-insensitive but
277
+ # Bitbucket requires `Authorization: Basic` and `Authorization Bearer` to work
278
+ # https://github.com/fastlane/fastlane/pull/15928
279
+ headers << "Authorization: Basic #{self.git_basic_authorization}" unless self.git_basic_authorization.nil?
280
+ headers << "Authorization: Bearer #{self.git_bearer_authorization}" unless self.git_bearer_authorization.nil?
281
+ return {} if headers.empty?
282
+
283
+ version = git_version
284
+ UI.user_error!("git_basic_authorization and git_bearer_authorization need git 2.31 or later, found git #{version}") if version && Gem::Version.new(version) < Gem::Version.new('2.31')
285
+
286
+ # Keep pairs the user already passes this way
287
+ first = ENV['GIT_CONFIG_COUNT'].to_i
288
+ env_values = { 'GIT_CONFIG_COUNT' => (first + headers.count).to_s }
289
+ headers.each_with_index do |header, i|
290
+ env_values["GIT_CONFIG_KEY_#{first + i}"] = 'http.extraheader'
291
+ env_values["GIT_CONFIG_VALUE_#{first + i}"] = header
292
+ end
267
293
  env_values
268
294
  end
269
295
 
296
+ # nil when git cannot be run: cloning reports that
297
+ def git_version
298
+ @git_version ||= begin
299
+ output, status = Open3.capture2('git', '--version')
300
+ output[/\d+\.\d+(\.\d+)?/] if status.success?
301
+ rescue Errno::ENOENT
302
+ nil
303
+ end
304
+ end
305
+
270
306
  def non_interactive_git_ssh_command
271
307
  ssh_command = ENV['GIT_SSH_COMMAND']
272
308
 
@@ -1,4 +1,5 @@
1
1
  require 'open-uri'
2
+ require 'ostruct'
2
3
 
3
4
  require_relative '../../module'
4
5
 
@@ -39,7 +40,7 @@ module Match
39
40
 
40
41
  create_subfolders(working_directory)
41
42
  File.open(destination_file, "wb") do |saved_file|
42
- URI.open(url, "rb", { @client.authentication_key => @client.authentication_value }) do |data|
43
+ url.open("rb", { @client.authentication_key => @client.authentication_value }) do |data|
43
44
  saved_file.write(data.read)
44
45
  end
45
46
 
@@ -6,10 +6,6 @@ module PEM
6
6
  attr_accessor :config
7
7
  end
8
8
 
9
- tmp_dir = Dir.tmpdir
10
- TMP_FOLDER = "#{tmp_dir}/fastlane/PEM/"
11
- FileUtils.mkdir_p(TMP_FOLDER)
12
-
13
9
  ENV['FASTLANE_TEAM_ID'] ||= ENV["PEM_TEAM_ID"]
14
10
  ENV['DELIVER_USER'] ||= ENV["PEM_USERNAME"]
15
11
 
@@ -1,3 +1,4 @@
1
+ require 'ostruct'
1
2
  require 'spaceship/tunes/language_item'
2
3
  require 'spaceship/tunes/iap_list'
3
4
  require 'fastlane/markdown_table_formatter'
@@ -38,7 +38,7 @@ module Produce
38
38
  end
39
39
 
40
40
  # Produce.config[:itc_users]
41
- application = Spaceship::ConnectAPI::App.create(
41
+ Spaceship::ConnectAPI::App.create(
42
42
  name: Produce.config[:app_name],
43
43
  version_string: Produce.config[:app_version] || "1.0",
44
44
  sku: Produce.config[:sku].to_s,
@@ -88,7 +88,6 @@ module Produce
88
88
  end
89
89
 
90
90
  # rubocop:disable Metrics/PerceivedComplexity
91
- # rubocop:disable Require/MissingRequireStatement
92
91
  def update(on, options)
93
92
  updated = valid_services_for(options).count
94
93
 
@@ -2,5 +2,4 @@ require_relative 'produce/manager'
2
2
  require_relative 'produce/options'
3
3
  require_relative 'produce/developer_center'
4
4
  require_relative 'produce/itunes_connect'
5
- require_relative 'produce/available_default_languages'
6
5
  require_relative 'produce/module'
@@ -207,6 +207,13 @@ module Scan
207
207
  conflict_block: proc do |value|
208
208
  UI.user_error!("You can't use 'thread_sanitizer' and 'address_sanitizer' options in one run")
209
209
  end),
210
+ FastlaneCore::ConfigItem.new(key: :collect_test_diagnostics,
211
+ env_name: "SCAN_COLLECT_TEST_DIAGNOSTICS",
212
+ description: "Whether verbose and long-running diagnostics (like sysdiagnoses or log archives) are collected when testing. Valid values are: on-failure or never. If not specified, the value in the test plan is used. Equivalent to -collect-test-diagnostics (Xcode 14 and up)",
213
+ optional: true,
214
+ verify_block: proc do |value|
215
+ UI.user_error!("Invalid collect_test_diagnostics #{value}") unless ['on-failure', 'never'].include?(value)
216
+ end),
210
217
 
211
218
  # output
212
219
  FastlaneCore::ConfigItem.new(key: :open_report,
@@ -327,7 +327,7 @@ module Scan
327
327
 
328
328
  def open_report
329
329
  if !Helper.ci? && Scan.cache[:open_html_report_path]
330
- `open --hide '#{Scan.cache[:open_html_report_path]}'`
330
+ system("open", "--hide", Scan.cache[:open_html_report_path])
331
331
  end
332
332
  end
333
333
 
@@ -44,9 +44,9 @@ module Scan
44
44
 
45
45
  options = []
46
46
  options += project_path_array unless config[:xctestrun]
47
- options << "-sdk '#{config[:sdk]}'" if config[:sdk]
47
+ options << "-sdk #{config[:sdk].shellescape}" if config[:sdk]
48
48
  options << destination if destination # generated in `detect_values`
49
- options << "-toolchain '#{config[:toolchain]}'" if config[:toolchain]
49
+ options << "-toolchain #{config[:toolchain].to_s.shellescape}" if config[:toolchain]
50
50
  if config[:derived_data_path] && !options.include?("-derivedDataPath #{config[:derived_data_path].shellescape}")
51
51
  options << "-derivedDataPath #{config[:derived_data_path].shellescape}"
52
52
  end
@@ -68,6 +68,9 @@ module Scan
68
68
  options << "-enableCodeCoverage #{config[:code_coverage] ? 'YES' : 'NO'}" unless config[:code_coverage].nil?
69
69
  options << "-enableAddressSanitizer #{config[:address_sanitizer] ? 'YES' : 'NO'}" unless config[:address_sanitizer].nil?
70
70
  options << "-enableThreadSanitizer #{config[:thread_sanitizer] ? 'YES' : 'NO'}" unless config[:thread_sanitizer].nil?
71
+ if config[:collect_test_diagnostics] && FastlaneCore::Helper.xcode_at_least?(14)
72
+ options << "-collect-test-diagnostics #{config[:collect_test_diagnostics]}"
73
+ end
71
74
  if FastlaneCore::Helper.xcode_at_least?(11)
72
75
  if config[:cloned_source_packages_path] && !options.include?("-clonedSourcePackagesDirPath #{config[:cloned_source_packages_path].shellescape}")
73
76
  options << "-clonedSourcePackagesDirPath #{config[:cloned_source_packages_path].shellescape}"
@@ -77,14 +80,14 @@ module Scan
77
80
  options << "-packageCachePath #{config[:package_cache_path].shellescape}"
78
81
  end
79
82
 
80
- options << "-testPlan '#{config[:testplan]}'" if config[:testplan]
83
+ options << "-testPlan #{config[:testplan].shellescape}" if config[:testplan]
81
84
 
82
85
  # detect_values will ensure that these values are present as Arrays if
83
86
  # they are present at all
84
- options += config[:only_test_configurations].map { |name| "-only-test-configuration '#{name}'" } if config[:only_test_configurations]
85
- options += config[:skip_test_configurations].map { |name| "-skip-test-configuration '#{name}'" } if config[:skip_test_configurations]
87
+ options += config[:only_test_configurations].map { |name| "-only-test-configuration #{name.shellescape}" } if config[:only_test_configurations]
88
+ options += config[:skip_test_configurations].map { |name| "-skip-test-configuration #{name.shellescape}" } if config[:skip_test_configurations]
86
89
  end
87
- options << "-xctestrun '#{config[:xctestrun]}'" if config[:xctestrun]
90
+ options << "-xctestrun #{config[:xctestrun].shellescape}" if config[:xctestrun]
88
91
  options << config[:xcargs] if config[:xcargs]
89
92
 
90
93
  # Number of retries does not equal xcodebuild's -test-iterations number
@@ -127,7 +130,7 @@ module Scan
127
130
  end
128
131
 
129
132
  def pipe
130
- pipe = ["| tee '#{xcodebuild_log_path}'"]
133
+ pipe = ["| tee #{xcodebuild_log_path.shellescape}"]
131
134
 
132
135
  # disable_xcpretty is now deprecated and directs to use output_style of raw
133
136
  if Scan.config[:disable_xcpretty] || Scan.config[:output_style] == 'raw'
@@ -182,7 +185,7 @@ module Scan
182
185
  formatter = []
183
186
  if (custom_formatter = Scan.config[:xcpretty_formatter] || Scan.config[:formatter])
184
187
  if custom_formatter.end_with?(".rb")
185
- formatter << "-f '#{custom_formatter}'"
188
+ formatter << "-f #{custom_formatter.shellescape}"
186
189
  else
187
190
  formatter << "-f `#{custom_formatter}`"
188
191
  end
@@ -234,7 +237,7 @@ module Scan
234
237
  # Generate destination parameters
235
238
  def destination
236
239
  unless Scan.cache[:destination]
237
- Scan.cache[:destination] = [*Scan.config[:destination]].map { |dst| "-destination '#{dst}'" }.join(' ')
240
+ Scan.cache[:destination] = [*Scan.config[:destination]].map { |dst| "-destination #{dst.shellescape}" }.join(' ')
238
241
  end
239
242
  Scan.cache[:destination]
240
243
  end
@@ -3,6 +3,7 @@ require_relative 'module'
3
3
  module Scan
4
4
  class TestResultParser
5
5
  def parse_result(output)
6
+ UI.deprecated("Scan::TestResultParser is deprecated and will be removed in a future version of fastlane; scan no longer uses it. Read the test counts from the result bundle with Trainer::TestParser, or from the <testsuites> attributes of the JUnit report.")
6
7
  unless output
7
8
  return {
8
9
  tests: 0,
@@ -49,7 +49,7 @@ module Scan
49
49
  type = raw_type.strip
50
50
  output_path = File.join(File.expand_path(@output_directory), determine_output_file_name(type))
51
51
  reporter << "--report #{type}"
52
- reporter << "--output '#{output_path}'"
52
+ reporter << "--output #{output_path.shellescape}"
53
53
 
54
54
  if type == "html" && @open_report
55
55
  Scan.cache[:open_html_report_path] = output_path
@@ -62,7 +62,7 @@ module Scan
62
62
  @temp_junit_report = Tempfile.new("junit_report")
63
63
  Scan.cache[:temp_junit_report] = @temp_junit_report.path
64
64
  reporter << "--report junit"
65
- reporter << "--output '#{Scan.cache[:temp_junit_report]}'"
65
+ reporter << "--output #{Scan.cache[:temp_junit_report].shellescape}"
66
66
  return reporter
67
67
  end
68
68
 
@@ -65,18 +65,18 @@
65
65
  </style>
66
66
  </head>
67
67
  <body><% image_counter = 0 %><% @data.each do |language, content| %>
68
- <h1 id="<%= language %>" class="language"><%= language %></h1>
68
+ <h1 id="<%= ERB::Util.h(language) %>" class="language"><%= ERB::Util.h(language) %></h1>
69
69
  <hr>
70
70
  <table><% content.each do |device_name, screens| %>
71
71
  <tr>
72
72
  <th colspan="<%= screens.count %>">
73
- <a id="<%= language %>-<%= device_name %>" class="deviceName" href="#<%= language %>-<%= device_name %>"><%= device_name %></a>
73
+ <a id="<%= ERB::Util.h(language) %>-<%= ERB::Util.h(device_name) %>" class="deviceName" href="#<%= ERB::Util.h(language) %>-<%= ERB::Util.h(device_name) %>"><%= ERB::Util.h(device_name) %></a>
74
74
  </th>
75
75
  </tr>
76
76
  <tr><% screens.each do |screen_path| %><% next if screen_path.include?"_framed.png" %>
77
77
  <td><% image_counter += 1 %>
78
- <a href="<%= screen_path %>" target="_blank" class="screenshotLink">
79
- <img class="screenshot" src="<%= screen_path %>" style="width: 100%;" alt="<%= language %> <%= device_name %>" data-counter="<%= image_counter %>">
78
+ <a href="<%= ERB::Util.h(screen_path) %>" target="_blank" class="screenshotLink">
79
+ <img class="screenshot" src="<%= ERB::Util.h(screen_path) %>" style="width: 100%;" alt="<%= ERB::Util.h(language) %> <%= ERB::Util.h(device_name) %>" data-counter="<%= image_counter %>">
80
80
  </a>
81
81
  </td><% end %>
82
82
  </tr><% end %>
@@ -128,9 +128,14 @@
128
128
  imageDisplay.alt = img.alt;
129
129
  imageDisplay.dataset.counter = img.dataset.counter;
130
130
 
131
- imageInfo.innerHTML = '<h3>'+img.alt+'</h3>';
132
- imageInfo.innerHTML += decodeURI(img.src.split("/").pop());
133
- imageInfo.innerHTML += '<br />'+tmpImg.height+'&times;'+tmpImg.width+'px';
131
+ // textContent, not innerHTML: file names must not be interpreted as HTML
132
+ var imageTitle = document.createElement('h3');
133
+ imageTitle.textContent = img.alt;
134
+ imageInfo.textContent = '';
135
+ imageInfo.appendChild(imageTitle);
136
+ imageInfo.appendChild(document.createTextNode(decodeURI(img.src.split("/").pop())));
137
+ imageInfo.appendChild(document.createElement('br'));
138
+ imageInfo.appendChild(document.createTextNode(tmpImg.height+'\u00d7'+tmpImg.width+'px'));
134
139
 
135
140
  overlay.style.display = "block";
136
141
  });
@@ -30,7 +30,7 @@ module Screengrab
30
30
 
31
31
  export_path = File.expand_path(export_path)
32
32
  UI.success("Successfully created HTML file with an overview of all the screenshots: '#{export_path}'")
33
- system("open '#{export_path}'") unless Screengrab.config[:skip_open_summary]
33
+ system("open", export_path) unless Screengrab.config[:skip_open_summary]
34
34
  end
35
35
  end
36
36
  end
@@ -321,6 +321,23 @@ else
321
321
  error "Error: Only can resign .app files and .ipa files."
322
322
  fi
323
323
 
324
+ # Stop if a symbolic link resolves outside the temporary directory: later steps write through such links.
325
+ # Resolved with the cd -P and pwd -P builtins, as realpath and readlink -f are missing on older macOS.
326
+ TEMP_DIR_PHYSICAL="$(cd -P "$TEMP_DIR" && pwd -P)"
327
+ checkStatus
328
+ while IFS= read -d '' -r link; do
329
+ target="$(readlink "$link")"
330
+ [[ "$target" == /* ]] || target="$(dirname "$link")/$target"
331
+ if [ -d "$target" ]; then
332
+ resolved="$(cd -P "$target" 2>/dev/null && pwd -P)"
333
+ else
334
+ resolved="$(cd -P "$(dirname "$target")" 2>/dev/null && pwd -P)/$(basename "$target")"
335
+ fi
336
+ if [[ "$resolved" != "$TEMP_DIR_PHYSICAL" && "$resolved" != "$TEMP_DIR_PHYSICAL"/* ]]; then
337
+ error "Error: '${link#"$TEMP_DIR"/}' is a symbolic link to '$(readlink "$link")', outside of '$ORIGINAL_FILE'. Remove it before resigning."
338
+ fi
339
+ done < <(find "$TEMP_DIR" -type l -print0)
340
+
324
341
  # check the keychain
325
342
  if [ "${KEYCHAIN}" != "" ]; then
326
343
  security list-keychains -s "$KEYCHAIN"
@@ -134,7 +134,7 @@ module Sigh
134
134
 
135
135
  profiles = []
136
136
  profile_paths.each do |profile_path|
137
- profile = Plist.parse_xml(`security cms -D -i '#{profile_path}' 2> /dev/null`) # /dev/null: https://github.com/fastlane/fastlane/issues/6387
137
+ profile = FastlaneCore::ProvisioningProfile.parse(profile_path)
138
138
  profile['Path'] = profile_path
139
139
  profiles << profile
140
140
  end
@@ -63,6 +63,11 @@ module Sigh
63
63
  code_gen_sensitive: true,
64
64
  default_value: CredentialsManager::AppfileConfig.try_fetch_value(:app_identifier),
65
65
  default_value_dynamic: true),
66
+ FastlaneCore::ConfigItem.new(key: :offline_profile,
67
+ env_name: "SIGH_OFFLINE_PROFILE",
68
+ description: "Enable profile with 'Offline Support' (7 day validity). Requires Apple ID login, not supported with App Store Connect API key authentication",
69
+ is_string: false,
70
+ default_value: false),
66
71
 
67
72
  # App Store Connect API
68
73
  FastlaneCore::ConfigItem.new(key: :api_key_path,
@@ -45,10 +45,10 @@ module Sigh
45
45
  entitlements = "-e #{entitlements.shellescape}" if entitlements
46
46
 
47
47
  provisioning_options = create_provisioning_options(provisioning_profiles)
48
- version = "-n #{version}" if version
48
+ version = "-n #{version.shellescape}" if version
49
49
  display_name = "-d #{display_name.shellescape}" if display_name
50
- short_version = "--short-version #{short_version}" if short_version
51
- bundle_version = "--bundle-version #{bundle_version}" if bundle_version
50
+ short_version = "--short-version #{short_version.shellescape}" if short_version
51
+ bundle_version = "--bundle-version #{bundle_version.shellescape}" if bundle_version
52
52
  verbose = "-v" if FastlaneCore::Globals.verbose?
53
53
  bundle_id = "-b '#{new_bundle_id}'" if new_bundle_id
54
54
  use_app_entitlements_flag = "--use-app-entitlements" if use_app_entitlements
@@ -34,6 +34,10 @@ module Sigh
34
34
  UI.message("Successfully logged in")
35
35
  end
36
36
 
37
+ if Sigh.config[:offline_profile] && !Spaceship::ConnectAPI.token.nil?
38
+ UI.user_error!("The 'offline_profile' option requires logging in with an Apple ID. Apple's App Store Connect API (API key authentication) does not support the 'Offline Support' profile setting")
39
+ end
40
+
37
41
  profiles = [] if Sigh.config[:skip_fetch_profiles]
38
42
  profiles ||= fetch_profiles # download the profile if it's there
39
43
 
@@ -185,7 +189,8 @@ module Sigh
185
189
  profile_type: profile_type,
186
190
  bundle_id_id: bundle_id.id,
187
191
  certificate_ids: certificates_to_use.map(&:id),
188
- device_ids: devices_to_use.map(&:id)
192
+ device_ids: devices_to_use.map(&:id),
193
+ is_offline_profile: Sigh.config[:offline_profile]
189
194
  )
190
195
 
191
196
  profile
@@ -96,38 +96,38 @@
96
96
  <button class="tabLink" onclick="openTab(event, 'byScreen')">By Screen</button>
97
97
  </div>
98
98
  <div id="byLanguage" class="tabContent"><h1 class="tabTitle">By Language:</h1><% image_counter = 0 %><% @data_by_language.each do |language, content| %>
99
- <h2 id="<%= language %>"><%= language %></h2>
99
+ <h2 id="<%= ERB::Util.h(language) %>"><%= ERB::Util.h(language) %></h2>
100
100
  <hr>
101
101
  <table><% content.each do |device_name, screens| %>
102
102
  <tr>
103
103
  <th colspan="<%= screens.count %>">
104
- <a id="<%= language %>-<%= device_name %>" class="deviceName" href="#<%= language %>-<%= device_name %>"><%= device_name %></a>
104
+ <a id="<%= ERB::Util.h(language) %>-<%= ERB::Util.h(device_name) %>" class="deviceName" href="#<%= ERB::Util.h(language) %>-<%= ERB::Util.h(device_name) %>"><%= ERB::Util.h(device_name) %></a>
105
105
  </th>
106
106
  </tr>
107
107
  <tr><% screens.each do |screen_path| %><% next if screen_path.include?"_framed.png" %>
108
108
  <td><% image_counter += 1 %>
109
- <a href="<%= screen_path %>" target="_blank" class="screenshotLink">
110
- <img class="screenshot" src="<%= screen_path %>" style="width: 100%;" alt="<%= language %> <%= device_name %>" data-tab="1" data-counter="<%= image_counter %>">
109
+ <a href="<%= ERB::Util.h(screen_path) %>" target="_blank" class="screenshotLink">
110
+ <img class="screenshot" src="<%= ERB::Util.h(screen_path) %>" style="width: 100%;" alt="<%= ERB::Util.h(language) %> <%= ERB::Util.h(device_name) %>" data-tab="1" data-counter="<%= image_counter %>">
111
111
  </a>
112
112
  </td><% end %>
113
113
  </tr><% end %>
114
114
  </table><% end %>
115
115
  </div>
116
116
  <div id="byScreen" class="tabContent"><h1 class="tabTitle">By Screen:</h1><% image_counter = 0 %><% @data_by_screen.each do |screen, content| %>
117
- <h2 id="<%= screen %>" class="screen"><%= screen %></h2>
117
+ <h2 id="<%= ERB::Util.h(screen) %>" class="screen"><%= ERB::Util.h(screen) %></h2>
118
118
  <hr>
119
119
  <table><% content.each do |device_name, screens| %>
120
120
  <tr>
121
121
  <th colspan="<%= screens.count %>">
122
- <a id="<%= screen %>-<%= device_name %>" class="deviceName" href="#<%= screen %>-<%= device_name %>"><%= device_name %></a>
122
+ <a id="<%= ERB::Util.h(screen) %>-<%= ERB::Util.h(device_name) %>" class="deviceName" href="#<%= ERB::Util.h(screen) %>-<%= ERB::Util.h(device_name) %>"><%= ERB::Util.h(device_name) %></a>
123
123
  </th>
124
124
  </tr>
125
125
  <tr><% screens.each do |language, screen_path| %><% next if screen_path.include?"_framed.png" %>
126
126
  <td><% image_counter += 1 %>
127
- <a href="<%= screen_path %>" target="_blank" class="screenshotLink">
128
- <img class="screenshot" src="<%= screen_path %>" style="width: 100%;" alt="<%= language %> <%= device_name %>" data-tab="2" data-counter="<%= image_counter %>">
127
+ <a href="<%= ERB::Util.h(screen_path) %>" target="_blank" class="screenshotLink">
128
+ <img class="screenshot" src="<%= ERB::Util.h(screen_path) %>" style="width: 100%;" alt="<%= ERB::Util.h(language) %> <%= ERB::Util.h(device_name) %>" data-tab="2" data-counter="<%= image_counter %>">
129
129
  </a>
130
- <div class="caption"><%= language %></div>
130
+ <div class="caption"><%= ERB::Util.h(language) %></div>
131
131
  </td><% end %>
132
132
  </tr><% end %>
133
133
  </table><% end %>
@@ -222,9 +222,14 @@
222
222
  imageDisplay.alt = img.alt;
223
223
  imageDisplay.dataset.counter = img.dataset.counter;
224
224
 
225
- imageInfo.innerHTML = '<h3>'+img.alt+'</h3>';
226
- imageInfo.innerHTML += decodeURI(img.src.split("/").pop());
227
- imageInfo.innerHTML += '<br />'+tmpImg.height+'&times;'+tmpImg.width+'px';
225
+ // textContent, not innerHTML: file names must not be interpreted as HTML
226
+ var imageTitle = document.createElement('h3');
227
+ imageTitle.textContent = img.alt;
228
+ imageInfo.textContent = '';
229
+ imageInfo.appendChild(imageTitle);
230
+ imageInfo.appendChild(document.createTextNode(decodeURI(img.src.split("/").pop())));
231
+ imageInfo.appendChild(document.createElement('br'));
232
+ imageInfo.appendChild(document.createTextNode(tmpImg.height+'\u00d7'+tmpImg.width+'px'));
228
233
 
229
234
  overlay.style.display = "block";
230
235
  });
@@ -51,7 +51,7 @@ module Snapshot
51
51
 
52
52
  export_path = File.expand_path(export_path)
53
53
  UI.success("Successfully created HTML file with an overview of all the screenshots: '#{export_path}'")
54
- system("open '#{export_path}'") unless Snapshot.config[:skip_open_summary]
54
+ system("open", export_path) unless Snapshot.config[:skip_open_summary]
55
55
  end
56
56
 
57
57
  def xcode_8_and_below_device_name_mappings
@@ -84,6 +84,8 @@ module Snapshot
84
84
  {
85
85
  # snapshot in Xcode 9 saves screenshots with the SIMULATOR_DEVICE_NAME
86
86
  # which includes spaces
87
+ 'iPhone 18 Pro Max' => "iPhone 18 Pro Max",
88
+ 'iPhone 18 Pro' => "iPhone 18 Pro",
87
89
  'iPhone 17 Pro Max' => "iPhone 17 Pro Max",
88
90
  'iPhone 17 Pro' => "iPhone 17 Pro",
89
91
  'iPhone 17' => "iPhone 17",
@@ -82,7 +82,7 @@ module Snapshot
82
82
  unless launcher_config.headless
83
83
  simulator_path = File.join(Helper.xcode_path, 'Applications', 'Simulator.app')
84
84
  device_udid = TestCommandGenerator.device_udid(device_types.first)
85
- command = "open -a #{simulator_path} -g"
85
+ command = "open -a #{simulator_path.shellescape} -g"
86
86
  command += " --args -CurrentDeviceUDID #{device_udid}" if device_udid
87
87
  Helper.backticks(command, print: FastlaneCore::Globals.verbose?)
88
88
  end
@@ -1,8 +1,6 @@
1
1
  require_relative 'snapshot/runner'
2
2
  require_relative 'snapshot/reports_generator'
3
3
  require_relative 'snapshot/detect_values'
4
- require_relative 'snapshot/screenshot_flatten'
5
- require_relative 'snapshot/screenshot_rotate'
6
4
  require_relative 'snapshot/dependency_checker'
7
5
  require_relative 'snapshot/latest_os_version'
8
6
  require_relative 'snapshot/test_command_generator'
data/spaceship/README.md CHANGED
@@ -27,8 +27,7 @@ Get in contact with the creators on Twitter: [@FastlaneTools](https://twitter.co
27
27
  <a href="#whats-spaceship">Why?</a> &bull;
28
28
  <a href="#usage">Usage</a> &bull;
29
29
  <a href="#installation">Installation</a> &bull;
30
- <a href="#technical-details">Technical Details</a> &bull;
31
- <a href="#need-help">Need help?</a>
30
+ <a href="#technical-details">Technical Details</a>
32
31
  </p>
33
32
 
34
33
  -------
@@ -165,7 +164,7 @@ _spaceship_ does a lot of magic to get everything working so neatly:
165
164
  - **Multiple Spaceship**: You can launch multiple _spaceships_ with different Apple accounts to do things like syncing the registered devices.
166
165
 
167
166
  # Code of Conduct
168
- Help us keep _fastlane_ open and inclusive. Please read and follow our [Code of Conduct](https://github.com/fastlane/fastlane/blob/master/CODE_OF_CONDUCT.md).
167
+ Help us keep _fastlane_ open and inclusive. Please read and follow our [Code of Conduct](https://github.com/fastlane/fastlane/blob/master/docs/CODE_OF_CONDUCT.md).
169
168
 
170
169
  # License
171
170
  This project is licensed under the terms of the MIT license. See the LICENSE file.
@@ -224,7 +224,9 @@ module Spaceship
224
224
  # The initialize method accepts a parsed response from Apple and sets all
225
225
  # attributes that are defined by `attr_mapping`
226
226
  #
227
- # Do not override `initialize` in your own models.
227
+ # Do not override `initialize` in your own models, use `setup` instead. An
228
+ # override that has to take a value Apple's response does not carry must call
229
+ # `super`, or `attr_mapping`, `raw_data`, `client` and `setup` are all skipped.
228
230
  def initialize(attrs = {}, existing_client = nil)
229
231
  attrs.each do |key, val|
230
232
  self.send("#{key}=", val) if respond_to?("#{key}=")