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
@@ -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.238.0
20
+ // Generated with fastlane 2.241.0
@@ -152,6 +152,9 @@ public protocol GymfileProtocol: AnyObject {
152
152
  /// Skips resolution of Swift Package Manager dependencies
153
153
  var skipPackageDependenciesResolution: Bool { get }
154
154
 
155
+ /// Raises an error instead of fetching build settings by running `xcodebuild -showBuildSettings`, which can take a long time on large projects. The error names the required build setting, so the corresponding option can be specified manually
156
+ var disallowXcodebuildSettingsLookup: Bool { get }
157
+
155
158
  /// Prevents packages from automatically being resolved to versions other than those recorded in the `Package.resolved` file. This translates in the option `-disableAutomaticPackageResolution` being passed to xcodebuild
156
159
  var disablePackageAutomaticUpdates: Bool { get }
157
160
 
@@ -369,6 +372,10 @@ public extension GymfileProtocol {
369
372
  return false
370
373
  }
371
374
 
375
+ var disallowXcodebuildSettingsLookup: Bool {
376
+ return false
377
+ }
378
+
372
379
  var disablePackageAutomaticUpdates: Bool {
373
380
  return false
374
381
  }
@@ -392,4 +399,4 @@ public extension GymfileProtocol {
392
399
 
393
400
  // Please don't remove the lines below
394
401
  // They are used to detect outdated files
395
- // FastlaneRunnerAPIVersion [0.9.155]
402
+ // FastlaneRunnerAPIVersion [0.9.159]
@@ -9,9 +9,6 @@
9
9
  //
10
10
 
11
11
  import Foundation
12
- #if canImport(SwiftShell)
13
- import SwiftShell
14
- #endif
15
12
 
16
13
  let argumentProcessor = ArgumentProcessor(args: CommandLine.arguments)
17
14
  let timeout = argumentProcessor.commandTimeout
@@ -20,9 +17,7 @@ class MainProcess {
20
17
  var doneRunningLane = false
21
18
  var thread: Thread!
22
19
  #if SWIFT_PACKAGE
23
- var lastPrintDate = Date.distantFuture
24
- var timeBetweenPrints = Int.min
25
- var rubySocketCommand: AsyncCommand!
20
+ var rubySocketCommand: Process!
26
21
  #endif
27
22
 
28
23
  @objc func connectToFastlaneAndRunLane(_ fastfile: LaneFile?) {
@@ -44,24 +39,199 @@ class MainProcess {
44
39
  #endif
45
40
  thread.name = "worker thread"
46
41
  #if SWIFT_PACKAGE
47
- let PATH = run("/bin/bash", "-c", "-l", "eval $(/usr/libexec/path_helper -s) ; echo $PATH").stdout
48
- main.env["PATH"] = PATH
49
- let path = main.run(bash: "which fastlane").stdout
50
- let pids = main.run("lsof", "-t", "-i", ":\(argumentProcessor.port)").stdout.split(separator: "\n")
51
- pids.forEach { main.run("kill", "-9", $0) }
52
- rubySocketCommand = main.runAsync(path, "socket_server", "-c", argumentProcessor.commandTimeout, "-p", argumentProcessor.port)
53
- lastPrintDate = Date()
54
- rubySocketCommand.stderror.onStringOutput { print($0) }
55
- rubySocketCommand.stdout.onStringOutput { stdout in
56
- print(stdout)
57
- self.timeBetweenPrints = Int(self.lastPrintDate.timeIntervalSinceNow)
58
- }
42
+ killExistingSocketServerProcesses(port: argumentProcessor.port)
43
+ abortIfPortIsInUse(argumentProcessor.port)
44
+
45
+ rubySocketCommand = Process()
46
+ rubySocketCommand.launchPath = "/usr/bin/env"
47
+ rubySocketCommand.arguments = fastlaneLaunchArguments() + ["socket_server", "-c", String(timeout), "-p", String(argumentProcessor.port)]
48
+ rubySocketCommand.launch()
59
49
 
60
- // swiftformat:disable:next redundantSelf
61
- _ = Runner.waitWithPolling(self.timeBetweenPrints, toEventually: { $0 > 5 }, timeout: 10)
50
+ waitUntilSocketServerIsListening(port: argumentProcessor.port, serverProcess: rubySocketCommand)
62
51
  thread.start()
63
52
  #endif
64
53
  }
54
+
55
+ #if SWIFT_PACKAGE
56
+ /// Resolves how to invoke fastlane, replacing the previous login-shell
57
+ /// `eval $(path_helper)` + `which fastlane` lookup that broke under
58
+ /// rbenv / bundler / system-ruby mixes (#29238). First match wins:
59
+ /// 1. FASTLANE_SPM_BIN environment variable (explicit override)
60
+ /// 2. bundler binstub bin/fastlane next to the Gemfile
61
+ /// 3. Gemfile (BUNDLE_GEMFILE, or found from the working directory up, as Bundler does) -> bundle exec fastlane
62
+ /// 4. fastlane on PATH
63
+ func fastlaneLaunchArguments() -> [String] {
64
+ if let bin = ProcessInfo.processInfo.environment["FASTLANE_SPM_BIN"],
65
+ !bin.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
66
+ {
67
+ // The shell splits the value, so quoted paths with spaces work; our arguments
68
+ // pass through "$@" untouched, and exec keeps the launched process ID.
69
+ return ["/bin/sh", "-c", "exec \(bin) \"$@\"", "sh"]
70
+ }
71
+ guard let bundleRoot = bundleRootDirectory() else {
72
+ return ["fastlane"]
73
+ }
74
+ let binstub = bundleRoot + "/bin/fastlane"
75
+ if FileManager.default.isExecutableFile(atPath: binstub) {
76
+ return [binstub]
77
+ }
78
+ return ["bundle", "exec", "fastlane"]
79
+ }
80
+
81
+ /// The directory of the Gemfile Bundler would use: BUNDLE_GEMFILE, else the
82
+ /// nearest Gemfile or gems.rb from the working directory up.
83
+ func bundleRootDirectory() -> String? {
84
+ let workingDirectory = FileManager.default.currentDirectoryPath
85
+ if let gemfile = ProcessInfo.processInfo.environment["BUNDLE_GEMFILE"], !gemfile.isEmpty {
86
+ let path = gemfile.hasPrefix("/") ? gemfile : workingDirectory + "/" + gemfile
87
+ return (path as NSString).deletingLastPathComponent
88
+ }
89
+ var directory = workingDirectory
90
+ while true {
91
+ for name in ["Gemfile", "gems.rb"] where FileManager.default.fileExists(atPath: directory + "/" + name) {
92
+ return directory
93
+ }
94
+ let parent = (directory as NSString).deletingLastPathComponent
95
+ if parent == directory || parent.isEmpty {
96
+ return nil
97
+ }
98
+ directory = parent
99
+ }
100
+ }
101
+
102
+ /// The ruby socket server performs a single `accept` (see
103
+ /// fastlane/server/socket_server.rb), so probing readiness with a TCP
104
+ /// connection would consume that accept and shut the server down.
105
+ /// Poll the LISTEN state read-only via lsof instead of the previous
106
+ /// "stdout quiet for 5 seconds" heuristic.
107
+ private func waitUntilSocketServerIsListening(port: UInt32, serverProcess: Process) {
108
+ let deadline = Date(timeIntervalSinceNow: 30)
109
+ while Date() < deadline {
110
+ if !serverProcess.isRunning {
111
+ log(message: "fastlane socket_server exited with status \(serverProcess.terminationStatus) before listening. Check that the resolved fastlane installation works (e.g. `bundle exec fastlane --version`).")
112
+ exit(1)
113
+ }
114
+ if isPortListening(port, by: serverProcess.processIdentifier) {
115
+ return
116
+ }
117
+ Thread.sleep(forTimeInterval: 0.2)
118
+ }
119
+ // Don't leak the socket server: it's still running (just not
120
+ // listening yet) on this timeout path, so terminate it before exit.
121
+ terminate(serverProcess: serverProcess)
122
+ log(message: "fastlane socket_server did not start listening on port \(port) within 30 seconds")
123
+ exit(1)
124
+ }
125
+
126
+ /// Terminate the socket server, escalating SIGTERM to SIGKILL if it
127
+ /// doesn't exit promptly, so the timeout path never leaves an orphan.
128
+ private func terminate(serverProcess: Process) {
129
+ serverProcess.terminate()
130
+ let killDeadline = Date(timeIntervalSinceNow: 2)
131
+ while serverProcess.isRunning, Date() < killDeadline {
132
+ Thread.sleep(forTimeInterval: 0.1)
133
+ }
134
+ if serverProcess.isRunning {
135
+ _ = outputOfProcess(arguments: ["/bin/kill", "-9", String(serverProcess.processIdentifier)])
136
+ serverProcess.waitUntilExit()
137
+ }
138
+ }
139
+
140
+ /// Clears a stale socket server left by a previously crashed run on this
141
+ /// port. Scoped to LISTENing ruby processes (`-sTCP:LISTEN -a -c ruby`)
142
+ /// so it never kills an unrelated service or a connected client that
143
+ /// happens to share the port.
144
+ private func killExistingSocketServerProcesses(port: UInt32) {
145
+ let pids = outputOfProcess(arguments: [lsofPath, "-t", "-nP", "-iTCP:\(port)", "-sTCP:LISTEN", "-a", "-c", "ruby"])
146
+ .split(separator: "\n")
147
+ pids.forEach { _ = outputOfProcess(arguments: ["/bin/kill", "-9", String($0)]) }
148
+ }
149
+
150
+ /// socket_server listens on whichever of 127.0.0.1 and ::1 is free, while the runner connects to `localhost`,
151
+ /// so a process holding the port on either address would receive the runner's commands.
152
+ private func abortIfPortIsInUse(_ port: UInt32) {
153
+ guard isAddressInUse(family: AF_INET, port: port) || isAddressInUse(family: AF_INET6, port: port) else {
154
+ return
155
+ }
156
+ // lsof only lists this user's processes unless run as root
157
+ let holders = outputOfProcess(arguments: [lsofPath, "-nP", "-iTCP:\(port)", "-sTCP:LISTEN"])
158
+ let holder = holders.isEmpty ? " by a process of another user" : ":\n\(holders)"
159
+ log(message: "Port \(port) is already in use on localhost\(holder)\nStop it, or choose another port for the runner with `swiftServerPort`.")
160
+ exit(1)
161
+ }
162
+
163
+ /// Binding fails with EADDRINUSE when another socket listens on that address and port, whoever owns it.
164
+ func isAddressInUse(family: Int32, port: UInt32) -> Bool {
165
+ let socketDescriptor = socket(family, SOCK_STREAM, 0)
166
+ guard socketDescriptor >= 0 else {
167
+ return false
168
+ }
169
+ defer { close(socketDescriptor) }
170
+ // Ignore connections left in TIME_WAIT by an earlier run, as the Ruby server does
171
+ var reuse: Int32 = 1
172
+ setsockopt(socketDescriptor, SOL_SOCKET, SO_REUSEADDR, &reuse, socklen_t(MemoryLayout<Int32>.size))
173
+
174
+ let result: Int32
175
+ if family == AF_INET {
176
+ var address = sockaddr_in()
177
+ address.sin_len = UInt8(MemoryLayout<sockaddr_in>.size)
178
+ address.sin_family = sa_family_t(AF_INET)
179
+ address.sin_port = in_port_t(UInt16(port).bigEndian)
180
+ address.sin_addr.s_addr = inet_addr("127.0.0.1")
181
+ result = withUnsafePointer(to: &address) {
182
+ $0.withMemoryRebound(to: sockaddr.self, capacity: 1) { bind(socketDescriptor, $0, socklen_t(MemoryLayout<sockaddr_in>.size)) }
183
+ }
184
+ } else {
185
+ var address = sockaddr_in6()
186
+ address.sin6_len = UInt8(MemoryLayout<sockaddr_in6>.size)
187
+ address.sin6_family = sa_family_t(AF_INET6)
188
+ address.sin6_port = in_port_t(UInt16(port).bigEndian)
189
+ address.sin6_addr = in6addr_loopback
190
+ result = withUnsafePointer(to: &address) {
191
+ $0.withMemoryRebound(to: sockaddr.self, capacity: 1) { bind(socketDescriptor, $0, socklen_t(MemoryLayout<sockaddr_in6>.size)) }
192
+ }
193
+ }
194
+ return result != 0 && errno == EADDRINUSE
195
+ }
196
+
197
+ /// Only the process we launched counts: another process listening on the port is not our server
198
+ private func isPortListening(_ port: UInt32, by processIdentifier: Int32) -> Bool {
199
+ let result = runProcess(arguments: [lsofPath, "-t", "-nP", "-iTCP:\(port)", "-sTCP:LISTEN"])
200
+ // `env` exits 127 when lsof can't be found. Without this guard the
201
+ // probe would silently return false on every poll, then kill the
202
+ // freshly launched server after the 30s timeout with a misleading
203
+ // "did not start listening" message. Fail fast with the real cause.
204
+ if result.status == 127 {
205
+ log(message: "Could not run lsof (\(lsofPath)) to check socket server readiness. lsof ships at /usr/sbin/lsof on macOS; ensure it is installed and reachable.")
206
+ exit(1)
207
+ }
208
+ return result.output.split(separator: "\n").contains { $0 == Substring(String(processIdentifier)) }
209
+ }
210
+
211
+ /// Prefer the absolute macOS path so port checks don't depend on PATH;
212
+ /// fall back to a PATH lookup if lsof lives somewhere non-standard.
213
+ private var lsofPath: String {
214
+ let standardPath = "/usr/sbin/lsof"
215
+ return FileManager.default.isExecutableFile(atPath: standardPath) ? standardPath : "lsof"
216
+ }
217
+
218
+ private func outputOfProcess(arguments: [String]) -> String {
219
+ return runProcess(arguments: arguments).output
220
+ }
221
+
222
+ private func runProcess(arguments: [String]) -> (output: String, status: Int32) {
223
+ let process = Process()
224
+ let pipe = Pipe()
225
+ process.launchPath = "/usr/bin/env"
226
+ process.arguments = arguments
227
+ process.standardOutput = pipe
228
+ process.standardError = FileHandle.nullDevice
229
+ process.launch()
230
+ process.waitUntilExit()
231
+ let data = pipe.fileHandleForReading.readDataToEndOfFile()
232
+ return (String(data: data, encoding: .utf8) ?? "", process.terminationStatus)
233
+ }
234
+ #endif
65
235
  }
66
236
 
67
237
  public class Main {
@@ -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.238.0
20
+ // Generated with fastlane 2.241.0
@@ -56,10 +56,10 @@ public protocol MatchfileProtocol: AnyObject {
56
56
  /// Clone just the branch specified, instead of the whole repo. This requires that the branch already exists. Otherwise the command will fail
57
57
  var cloneBranchDirectly: Bool { get }
58
58
 
59
- /// Use a basic authorization header to access the git repo (e.g.: access via HTTPS, GitHub Actions, etc), usually a string in Base64
59
+ /// 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
60
60
  var gitBasicAuthorization: String? { get }
61
61
 
62
- /// Use a bearer authorization header to access the git repo (e.g.: access to an Azure DevOps repository), usually a string in Base64
62
+ /// 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
63
63
  var gitBearerAuthorization: String? { get }
64
64
 
65
65
  /// Use a private key to access the git repo (e.g.: access to GitHub repository via Deploy keys), usually a id_rsa named file or the contents hereof
@@ -173,6 +173,9 @@ public protocol MatchfileProtocol: AnyObject {
173
173
  /// Force encryption to use legacy cbc algorithm for backwards compatibility with older match versions
174
174
  var forceLegacyEncryption: Bool { get }
175
175
 
176
+ /// Enable profile with 'Offline Support' (7 day validity). Requires Apple ID login, not supported with App Store Connect API key authentication
177
+ var offlineProfile: Bool { get }
178
+
176
179
  /// Print out extra information and all commands
177
180
  var verbose: Bool { get }
178
181
  }
@@ -406,6 +409,10 @@ public extension MatchfileProtocol {
406
409
  return false
407
410
  }
408
411
 
412
+ var offlineProfile: Bool {
413
+ return false
414
+ }
415
+
409
416
  var verbose: Bool {
410
417
  return false
411
418
  }
@@ -413,4 +420,4 @@ public extension MatchfileProtocol {
413
420
 
414
421
  // Please don't remove the lines below
415
422
  // They are used to detect outdated files
416
- // FastlaneRunnerAPIVersion [0.9.149]
423
+ // FastlaneRunnerAPIVersion [0.9.153]
@@ -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.238.0
20
+ // Generated with fastlane 2.241.0
@@ -84,4 +84,4 @@ public extension PrecheckfileProtocol {
84
84
 
85
85
  // Please don't remove the lines below
86
86
  // They are used to detect outdated files
87
- // FastlaneRunnerAPIVersion [0.9.148]
87
+ // FastlaneRunnerAPIVersion [0.9.152]
@@ -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.238.0
20
+ // Generated with fastlane 2.241.0
@@ -77,6 +77,9 @@ public protocol ScanfileProtocol: AnyObject {
77
77
  /// Should the thread sanitizer be turned on?
78
78
  var threadSanitizer: Bool? { get }
79
79
 
80
+ /// 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)
81
+ var collectTestDiagnostics: String? { get }
82
+
80
83
  /// Should the HTML report be opened when tests are completed?
81
84
  var openReport: Bool { get }
82
85
 
@@ -230,6 +233,9 @@ public protocol ScanfileProtocol: AnyObject {
230
233
  /// Skips resolution of Swift Package Manager dependencies
231
234
  var skipPackageDependenciesResolution: Bool { get }
232
235
 
236
+ /// Raises an error instead of fetching build settings by running `xcodebuild -showBuildSettings`, which can take a long time on large projects. The error names the required build setting, so the corresponding option can be specified manually
237
+ var disallowXcodebuildSettingsLookup: Bool { get }
238
+
233
239
  /// Prevents packages from automatically being resolved to versions other than those recorded in the `Package.resolved` file. This translates in the option `-disableAutomaticPackageResolution` being passed to xcodebuild
234
240
  var disablePackageAutomaticUpdates: Bool { get }
235
241
 
@@ -350,6 +356,10 @@ public extension ScanfileProtocol {
350
356
  return nil
351
357
  }
352
358
 
359
+ var collectTestDiagnostics: String? {
360
+ return nil
361
+ }
362
+
353
363
  var openReport: Bool {
354
364
  return false
355
365
  }
@@ -554,6 +564,10 @@ public extension ScanfileProtocol {
554
564
  return false
555
565
  }
556
566
 
567
+ var disallowXcodebuildSettingsLookup: Bool {
568
+ return false
569
+ }
570
+
557
571
  var disablePackageAutomaticUpdates: Bool {
558
572
  return false
559
573
  }
@@ -581,4 +595,4 @@ public extension ScanfileProtocol {
581
595
 
582
596
  // Please don't remove the lines below
583
597
  // They are used to detect outdated files
584
- // FastlaneRunnerAPIVersion [0.9.160]
598
+ // FastlaneRunnerAPIVersion [0.9.164]
@@ -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.238.0
20
+ // Generated with fastlane 2.241.0
@@ -161,4 +161,4 @@ public extension ScreengrabfileProtocol {
161
161
 
162
162
  // Please don't remove the lines below
163
163
  // They are used to detect outdated files
164
- // FastlaneRunnerAPIVersion [0.9.150]
164
+ // FastlaneRunnerAPIVersion [0.9.154]
@@ -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.238.0
20
+ // Generated with fastlane 2.241.0
@@ -125,6 +125,9 @@ public protocol SnapshotfileProtocol: AnyObject {
125
125
  /// Skips resolution of Swift Package Manager dependencies
126
126
  var skipPackageDependenciesResolution: Bool { get }
127
127
 
128
+ /// Raises an error instead of fetching build settings by running `xcodebuild -showBuildSettings`, which can take a long time on large projects. The error names the required build setting, so the corresponding option can be specified manually
129
+ var disallowXcodebuildSettingsLookup: Bool { get }
130
+
128
131
  /// Prevents packages from automatically being resolved to versions other than those recorded in the `Package.resolved` file. This translates in the option `-disableAutomaticPackageResolution` being passed to xcodebuild
129
132
  var disablePackageAutomaticUpdates: Bool { get }
130
133
 
@@ -327,6 +330,10 @@ public extension SnapshotfileProtocol {
327
330
  return false
328
331
  }
329
332
 
333
+ var disallowXcodebuildSettingsLookup: Bool {
334
+ return false
335
+ }
336
+
330
337
  var disablePackageAutomaticUpdates: Bool {
331
338
  return false
332
339
  }
@@ -378,4 +385,4 @@ public extension SnapshotfileProtocol {
378
385
 
379
386
  // Please don't remove the lines below
380
387
  // They are used to detect outdated files
381
- // FastlaneRunnerAPIVersion [0.9.144]
388
+ // FastlaneRunnerAPIVersion [0.9.148]
@@ -14,5 +14,6 @@ end
14
14
  task(:lint) do
15
15
  Dir.chdir('..') do
16
16
  sh("swiftformat . --config formatting/.swiftformat --verbose --selfrequired waitWithPolling --exclude Fastfile.swift --swiftversion 4.0")
17
+ sh("swiftformat ../spec/swift --config formatting/.swiftformat --verbose --swiftversion 4.0")
17
18
  end
18
19
  end
@@ -11,6 +11,9 @@
11
11
  import Foundation
12
12
 
13
13
  let argumentProcessor = ArgumentProcessor(args: CommandLine.arguments)
14
+ /// fastlane reads this from the built runner, to tell whether it is outdated. Increase it when the runner changes how it talks to fastlane.
15
+ let runnerProtocolVersion = "FastlaneRunnerProtocolVersion [1]"
16
+ verbose(message: runnerProtocolVersion)
14
17
  let timeout = argumentProcessor.commandTimeout
15
18
 
16
19
  class MainProcess {
@@ -44,4 +47,4 @@ while !process.doneRunningLane, RunLoop.current.run(mode: RunLoopMode.defaultRun
44
47
 
45
48
  // Please don't remove the lines below
46
49
  // They are used to detect outdated files
47
- // FastlaneRunnerAPIVersion [0.9.2]
50
+ // FastlaneRunnerAPIVersion [0.9.3]
@@ -72,7 +72,7 @@ UI.deprecated("The '--key' parameter is deprecated")
72
72
  ```
73
73
 
74
74
  # Code of Conduct
75
- 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).
75
+ 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).
76
76
 
77
77
  # License
78
78
  This project is licensed under the terms of the MIT license. See the LICENSE file.
@@ -21,7 +21,7 @@ module FastlaneCore
21
21
  params: {
22
22
  fastlane_client_language: @fastlane_client_language,
23
23
  fastlane_version: Fastlane::VERSION,
24
- install_method: install_method,
24
+ install_method: Helper.install_method,
25
25
  ruby_version: RUBY_VERSION,
26
26
  operating_system: Helper.operating_system,
27
27
  build_tool_version: @build_tool_version,
@@ -29,21 +29,5 @@ module FastlaneCore
29
29
  }.reject { |_, value| value.nil? }
30
30
  }
31
31
  end
32
-
33
- private
34
-
35
- def install_method
36
- if Helper.bundler?
37
- 'bundler'
38
- elsif Helper.contained_fastlane?
39
- 'standalone'
40
- elsif Helper.homebrew?
41
- 'homebrew'
42
- elsif Helper.mac_app?
43
- 'mac_app'
44
- else
45
- 'gem'
46
- end
47
- end
48
32
  end
49
33
  end
@@ -1,5 +1,6 @@
1
1
  require_relative '../helper'
2
2
  require_relative '../globals'
3
+ require_relative '../secrets'
3
4
  require_relative 'config_item'
4
5
  require_relative 'commander_generator'
5
6
  require_relative 'configuration_file'
@@ -53,16 +54,17 @@ module FastlaneCore
53
54
  # used for pushing and popping values to provide nesting configuration contexts
54
55
  @values_stack = []
55
56
 
56
- # if we are in captured output mode - keep a array of sensitive option values
57
- # those will be later - replaced by ####
58
- if FastlaneCore::Globals.capture_output?
59
- available_options.each do |element|
60
- next unless element.sensitive
61
- self.class.sensitive_strings << values[element.key]
62
- end
57
+ verify_input_types
58
+
59
+ @available_options.each do |element|
60
+ next unless element.sensitive
61
+
62
+ Secrets.register(@values[element.key], name: element.key)
63
+ # if we are in captured output mode - keep a array of sensitive option values
64
+ # those will be later - replaced by ####
65
+ self.class.sensitive_strings << @values[element.key] if FastlaneCore::Globals.capture_output?
63
66
  end
64
67
 
65
- verify_input_types
66
68
  verify_value_exists
67
69
  verify_no_duplicates
68
70
  verify_conflicts
@@ -229,6 +231,7 @@ module FastlaneCore
229
231
 
230
232
  value = option.auto_convert_value(value)
231
233
  value = nil if value.nil? && !option.string? # by default boolean flags are false
234
+ Secrets.register(value, name: option.key) if option.sensitive
232
235
  return value unless value.nil? && (!option.optional || force_ask) && ask
233
236
 
234
237
  # fallback to asking
@@ -267,6 +270,18 @@ module FastlaneCore
267
270
  end
268
271
  # rubocop:enable Metrics/PerceivedComplexity
269
272
 
273
+ # Returns true if the value for a certain key comes from one of the sources `fetch` checks
274
+ # before falling back to the default value: passed in, an environment variable or the config file
275
+ def specified?(key)
276
+ UI.crash!("Key '#{key}' must be a symbol. Example :#{key}") unless key.kind_of?(Symbol)
277
+
278
+ option = verify_options_key!(key)
279
+
280
+ !@values[key].nil? ||
281
+ !option.fetch_env_value.nil? ||
282
+ self.config_file_options.key?(key)
283
+ end
284
+
270
285
  # Overwrites or sets a new value for a given key
271
286
  # @param key [Symbol] Must be a symbol
272
287
  def set(key, value)
@@ -243,7 +243,7 @@ module FastlaneCore
243
243
  plist_buddy_cmd = "-c \"Add :KeyboardContinuousPathEnabled bool false\""
244
244
  plist_path = File.expand_path("~/Library/Developer/CoreSimulator/Devices/#{self.udid}/data/Library/Preferences/com.apple.keyboard.ContinuousPath.plist")
245
245
 
246
- Helper.backticks("#{plist_buddy} #{plist_buddy_cmd} #{plist_path} >/dev/null 2>&1")
246
+ Helper.backticks("#{plist_buddy} #{plist_buddy_cmd} #{plist_path.shellescape} >/dev/null 2>&1")
247
247
  end
248
248
  end
249
249
  end
@@ -300,7 +300,7 @@ module FastlaneCore
300
300
 
301
301
  UI.verbose("Launching #{simulator_path} for device: #{device.name} (#{device.udid})")
302
302
 
303
- Helper.backticks("open -a #{simulator_path} --args -CurrentDeviceUDID #{device.udid}", print: FastlaneCore::Globals.verbose?)
303
+ Helper.backticks("open -a #{simulator_path.shellescape} --args -CurrentDeviceUDID #{device.udid}", print: FastlaneCore::Globals.verbose?)
304
304
  end
305
305
 
306
306
  def copy_logs(device, log_identity, logs_destination_dir, log_collection_start_time)
@@ -30,6 +30,11 @@ module FastlaneCore
30
30
  require 'pty'
31
31
  # this forces the PTY flush - fixes #21792
32
32
  command = ENV['FASTLANE_EXEC_FLUSH_PTY_WORKAROUND'] ? "#{original_command};" : original_command
33
+ # The status is produced in the ensure below and read after the block. It
34
+ # travels in a local rather than in $?, which is a thread global: anything
35
+ # that runs a subprocess in between overwrites it, and nothing writes it at
36
+ # all when the wait does not happen. See fastlane#30188.
37
+ status = nil
33
38
  PTY.spawn(command) do |command_stdout, command_stdin, pid|
34
39
  begin
35
40
  yield(command_stdout, command_stdin, pid)
@@ -42,20 +47,28 @@ module FastlaneCore
42
47
  command_stdin.close
43
48
  command_stdout.close
44
49
  begin
45
- Process.wait(pid)
46
- rescue Errno::ECHILD, PTY::ChildExited
47
- # The process might have exited.
50
+ _pid, status = Process.wait2(pid)
51
+ rescue PTY::ChildExited => e
52
+ # The pty saw the child go before we asked for it. The exception
53
+ # carries the status we were about to wait for.
54
+ status = e.status
55
+ rescue Errno::ECHILD
56
+ # Something else reaped it, so there is nothing left to ask for. $?
57
+ # may still hold it, and may just as easily hold someone else's.
48
58
  end
49
59
  end
50
60
  end
51
- status = self.process_status
61
+ status ||= self.process_status
62
+ # Better a plain error than a NoMethodError raised from inside the handler
63
+ # that exists to report the failure, which is what nil used to produce.
64
+ raise StandardError, "Could not determine the exit status of the command" if status.nil?
52
65
  raise StandardError, "Process crashed" if status.signaled?
53
66
  status.exitstatus
54
67
  rescue StandardError => e
55
68
  # Wrapping any error in FastlanePtyError to allow callers to see and use
56
- # $?.exitstatus that would usually get returned
57
- status = self.process_status
58
- raise FastlanePtyError.new(e, status.exitstatus || e.exit_status, status)
69
+ # the exit status that would usually get returned
70
+ status ||= self.process_status
71
+ raise FastlanePtyError.new(e, status&.exitstatus || e.exit_status, status)
59
72
  end
60
73
 
61
74
  def self.spawn_with_popen(command, &block)