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.
- checksums.yaml +4 -4
- data/README.md +57 -177
- data/bin/fastlane +4 -2
- data/credentials_manager/README.md +1 -1
- data/credentials_manager/lib/credentials_manager/account_manager.rb +6 -2
- data/deliver/lib/deliver/app_screenshot.rb +0 -4
- data/deliver/lib/deliver/commands_generator.rb +1 -1
- data/deliver/lib/deliver/detect_values.rb +3 -1
- data/deliver/lib/deliver/download_screenshots.rb +8 -1
- data/deliver/lib/deliver/html_generator.rb +1 -1
- data/deliver/lib/deliver/options.rb +8 -0
- data/deliver/lib/deliver/runner.rb +5 -4
- data/deliver/lib/deliver/sync_screenshots.rb +27 -28
- data/deliver/lib/deliver/upload_app_clip_default_experience_header_images.rb +3 -3
- data/deliver/lib/deliver/upload_metadata.rb +34 -16
- data/deliver/lib/deliver/upload_screenshots.rb +24 -18
- data/docs/README.md +25 -0
- data/fastlane/lib/assets/TeamTable.md.erb +28 -0
- data/fastlane/lib/fastlane/actions/appaloosa.rb +2 -1
- data/fastlane/lib/fastlane/actions/appium.rb +1 -1
- data/fastlane/lib/fastlane/actions/apteligent.rb +8 -1
- data/fastlane/lib/fastlane/actions/build_and_upload_to_appetize.rb +3 -1
- data/fastlane/lib/fastlane/actions/changelog_from_git_commits.rb +7 -2
- data/fastlane/lib/fastlane/actions/clean_build_artifacts.rb +3 -0
- data/fastlane/lib/fastlane/actions/danger.rb +5 -5
- data/fastlane/lib/fastlane/actions/docs/build_app.md +1 -2
- data/fastlane/lib/fastlane/actions/docs/create_app_online.md +1 -2
- data/fastlane/lib/fastlane/actions/docs/get_certificates.md +0 -2
- data/fastlane/lib/fastlane/actions/docs/get_push_certificate.md +7 -3
- data/fastlane/lib/fastlane/actions/docs/sync_code_signing.md +13 -3
- data/fastlane/lib/fastlane/actions/ensure_no_debug_code.rb +2 -2
- data/fastlane/lib/fastlane/actions/get_managed_play_store_publishing_rights.rb +1 -0
- data/fastlane/lib/fastlane/actions/github_api.rb +1 -2
- data/fastlane/lib/fastlane/actions/hg_commit_version_bump.rb +1 -1
- data/fastlane/lib/fastlane/actions/increment_build_number.rb +1 -1
- data/fastlane/lib/fastlane/actions/increment_version_number.rb +1 -1
- data/fastlane/lib/fastlane/actions/install_xcode_plugin.rb +16 -6
- data/fastlane/lib/fastlane/actions/lcov.rb +11 -2
- data/fastlane/lib/fastlane/actions/nexus_upload.rb +16 -4
- data/fastlane/lib/fastlane/actions/notification.rb +3 -2
- data/fastlane/lib/fastlane/actions/oclint.rb +8 -8
- data/fastlane/lib/fastlane/actions/push_to_git_remote.rb +9 -4
- data/fastlane/lib/fastlane/actions/register_device.rb +1 -1
- data/fastlane/lib/fastlane/actions/say.rb +2 -4
- data/fastlane/lib/fastlane/actions/set_pod_key.rb +3 -3
- data/fastlane/lib/fastlane/actions/sonar.rb +16 -16
- data/fastlane/lib/fastlane/actions/sourcedocs.rb +8 -8
- data/fastlane/lib/fastlane/actions/spaceship_logs.rb +4 -2
- data/fastlane/lib/fastlane/actions/splunkmint.rb +8 -1
- data/fastlane/lib/fastlane/actions/swiftlint.rb +6 -3
- data/fastlane/lib/fastlane/actions/update_project_provisioning.rb +4 -2
- data/fastlane/lib/fastlane/actions/upload_to_app_store.rb +5 -2
- data/fastlane/lib/fastlane/actions/upload_to_testflight.rb +5 -2
- data/fastlane/lib/fastlane/actions/verify_build.rb +1 -4
- data/fastlane/lib/fastlane/actions/verify_pod_keys.rb +3 -1
- data/fastlane/lib/fastlane/actions/xcode_server_get_assets.rb +20 -19
- data/fastlane/lib/fastlane/actions/xcodebuild.rb +5 -6
- data/fastlane/lib/fastlane/actions/zip.rb +2 -1
- data/fastlane/lib/fastlane/auto_complete.rb +1 -1
- data/fastlane/lib/fastlane/cli_tools_distributor.rb +14 -0
- data/fastlane/lib/fastlane/documentation/markdown_docs_generator.rb +23 -0
- data/fastlane/lib/fastlane/environment_printer.rb +12 -25
- data/fastlane/lib/fastlane/fast_file.rb +2 -1
- data/fastlane/lib/fastlane/fastlane_require.rb +5 -1
- data/fastlane/lib/fastlane/helper/git_helper.rb +4 -2
- data/fastlane/lib/fastlane/helper/sh_helper.rb +25 -7
- data/fastlane/lib/fastlane/new_action.rb +1 -1
- data/fastlane/lib/fastlane/plugins/plugin_fetcher.rb +1 -1
- data/fastlane/lib/fastlane/plugins/plugin_info_collector.rb +1 -1
- data/fastlane/lib/fastlane/plugins/plugin_manager.rb +36 -4
- data/fastlane/lib/fastlane/plugins/template/%gem_name%.gemspec.erb +1 -1
- data/fastlane/lib/fastlane/plugins/template/.github/workflows/test.yml +1 -1
- data/fastlane/lib/fastlane/plugins/template/.rubocop.yml +7 -7
- data/fastlane/lib/fastlane/swift_lane_manager.rb +22 -4
- data/fastlane/lib/fastlane/version.rb +3 -2
- data/fastlane/swift/Deliverfile.swift +1 -1
- data/fastlane/swift/DeliverfileProtocol.swift +8 -1
- data/fastlane/swift/Fastlane.swift +129 -11
- data/fastlane/swift/Gymfile.swift +1 -1
- data/fastlane/swift/GymfileProtocol.swift +8 -1
- data/fastlane/swift/MainProcess.swift +190 -20
- data/fastlane/swift/Matchfile.swift +1 -1
- data/fastlane/swift/MatchfileProtocol.swift +10 -3
- data/fastlane/swift/Precheckfile.swift +1 -1
- data/fastlane/swift/PrecheckfileProtocol.swift +1 -1
- data/fastlane/swift/Scanfile.swift +1 -1
- data/fastlane/swift/ScanfileProtocol.swift +15 -1
- data/fastlane/swift/Screengrabfile.swift +1 -1
- data/fastlane/swift/ScreengrabfileProtocol.swift +1 -1
- data/fastlane/swift/Snapshotfile.swift +1 -1
- data/fastlane/swift/SnapshotfileProtocol.swift +8 -1
- data/fastlane/swift/formatting/Rakefile +1 -0
- data/fastlane/swift/main.swift +4 -1
- data/fastlane_core/README.md +1 -1
- data/fastlane_core/lib/fastlane_core/analytics/analytics_event_builder.rb +1 -17
- data/fastlane_core/lib/fastlane_core/configuration/configuration.rb +23 -8
- data/fastlane_core/lib/fastlane_core/device_manager.rb +2 -2
- data/fastlane_core/lib/fastlane_core/fastlane_pty.rb +20 -7
- data/fastlane_core/lib/fastlane_core/helper.rb +34 -5
- data/fastlane_core/lib/fastlane_core/ipa_file_analyser.rb +1 -1
- data/fastlane_core/lib/fastlane_core/itunes_transporter.rb +16 -27
- data/fastlane_core/lib/fastlane_core/keychain_importer.rb +31 -28
- data/fastlane_core/lib/fastlane_core/languages.rb +0 -1
- data/fastlane_core/lib/fastlane_core/print_table.rb +5 -2
- data/fastlane_core/lib/fastlane_core/project.rb +19 -0
- data/fastlane_core/lib/fastlane_core/provisioning_profile.rb +10 -19
- data/fastlane_core/lib/fastlane_core/secrets.rb +77 -0
- data/fastlane_core/lib/fastlane_core/ui/fastlane_runner.rb +3 -3
- data/fastlane_core/lib/fastlane_core/ui/github_issue_inspector_reporter.rb +1 -1
- data/fastlane_core/lib/fastlane_core/ui/implementations/shell.rb +2 -1
- data/fastlane_core/lib/fastlane_core.rb +1 -0
- data/frameit/lib/frameit/device.rb +1 -1
- data/frameit/lib/frameit/frame_downloader.rb +2 -0
- data/frameit/lib/frameit/runner.rb +3 -2
- data/frameit/lib/frameit/screenshot.rb +0 -1
- data/gym/lib/gym/generators/build_command_generator.rb +4 -4
- data/gym/lib/gym/generators/package_command_generator_xcode7.rb +3 -3
- data/gym/lib/gym/options.rb +5 -0
- data/gym/lib/gym/runner.rb +1 -1
- data/internal/README.md +1 -1
- data/match/lib/match/encryption/openssl.rb +6 -2
- data/match/lib/match/generator.rb +1 -0
- data/match/lib/match/nuke.rb +2 -2
- data/match/lib/match/options.rb +13 -5
- data/match/lib/match/runner.rb +30 -3
- data/match/lib/match/storage/git_storage.rb +44 -11
- data/match/lib/match/storage/gitlab/secure_file.rb +2 -1
- data/match/lib/match/storage/google_cloud_storage.rb +6 -1
- data/match/lib/match/storage/interface.rb +8 -5
- data/pem/lib/pem/manager.rb +5 -1
- data/pem/lib/pem/module.rb +0 -4
- data/pem/lib/pem/options.rb +6 -0
- data/pilot/lib/pilot/build_manager.rb +32 -0
- data/pilot/lib/pilot/options.rb +8 -0
- data/precheck/lib/precheck/rule_processor.rb +1 -0
- data/produce/lib/produce/developer_center.rb +49 -2
- data/produce/lib/produce/itunes_connect.rb +1 -1
- data/produce/lib/produce/module.rb +21 -0
- data/produce/lib/produce/options.rb +17 -0
- data/produce/lib/produce/service.rb +3 -5
- data/produce/lib/produce.rb +0 -1
- data/scan/lib/scan/options.rb +12 -0
- data/scan/lib/scan/runner.rb +1 -1
- data/scan/lib/scan/test_command_generator.rb +12 -9
- data/scan/lib/scan/test_result_parser.rb +1 -0
- data/scan/lib/scan/xcpretty_reporter_options_generator.rb +2 -2
- data/screengrab/lib/screengrab/page.html.erb +12 -7
- data/screengrab/lib/screengrab/reports_generator.rb +1 -1
- data/sigh/lib/assets/resign.sh +38 -9
- data/sigh/lib/sigh/local_manage.rb +1 -1
- data/sigh/lib/sigh/options.rb +5 -0
- data/sigh/lib/sigh/resign.rb +3 -3
- data/sigh/lib/sigh/runner.rb +6 -1
- data/snapshot/lib/snapshot/options.rb +5 -0
- data/snapshot/lib/snapshot/page.html.erb +17 -12
- data/snapshot/lib/snapshot/reports_generator.rb +1 -1
- data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher_base.rb +1 -1
- data/snapshot/lib/snapshot.rb +0 -2
- data/spaceship/README.md +2 -3
- data/spaceship/lib/spaceship/base.rb +3 -1
- data/spaceship/lib/spaceship/client.rb +159 -19
- data/spaceship/lib/spaceship/connect_api/models/app_store_version.rb +16 -0
- data/spaceship/lib/spaceship/connect_api/models/bundle_id.rb +13 -2
- data/spaceship/lib/spaceship/connect_api/models/bundle_id_capability.rb +6 -0
- data/spaceship/lib/spaceship/connect_api/models/profile.rb +7 -5
- data/spaceship/lib/spaceship/connect_api/models/routing_app_coverage.rb +75 -0
- data/spaceship/lib/spaceship/connect_api/provisioning/provisioning.rb +25 -0
- data/spaceship/lib/spaceship/connect_api/token.rb +6 -1
- data/spaceship/lib/spaceship/connect_api/tunes/tunes.rb +45 -0
- data/spaceship/lib/spaceship/connect_api.rb +1 -0
- data/spaceship/lib/spaceship/du/upload_file.rb +4 -3
- data/spaceship/lib/spaceship/errors.rb +7 -1
- data/spaceship/lib/spaceship/globals.rb +2 -2
- data/spaceship/lib/spaceship/portal/merchant.rb +127 -2
- data/spaceship/lib/spaceship/portal/portal_client.rb +58 -0
- data/spaceship/lib/spaceship/portal/ui/select_team.rb +0 -2
- data/spaceship/lib/spaceship/portal/website_push.rb +8 -2
- data/spaceship/lib/spaceship/test_flight/client.rb +0 -22
- data/spaceship/lib/spaceship/test_flight.rb +0 -1
- data/spaceship/lib/spaceship/two_step_or_factor_client.rb +11 -0
- data/supply/lib/supply/client.rb +6 -0
- data/supply/lib/supply/options.rb +1 -0
- data/supply/lib/supply/reader.rb +15 -0
- data/supply/lib/supply.rb +0 -1
- data/trainer/lib/trainer/xcresult/helper.rb +27 -13
- metadata +80 -64
- data/produce/lib/produce/available_default_languages.rb +0 -62
- data/snapshot/lib/snapshot/screenshot_flatten.rb +0 -20
- data/snapshot/lib/snapshot/screenshot_rotate.rb +0 -36
- data/spaceship/lib/spaceship/test_flight/app_test_info.rb +0 -40
- data/supply/lib/supply/apk_listing.rb +0 -14
- /data/fastlane/lib/assets/{custom_action_template.rb → custom_action_template.rb.template} +0 -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.
|
|
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
|
|
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
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
rubySocketCommand =
|
|
53
|
-
|
|
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
|
-
|
|
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 {
|
|
@@ -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.
|
|
423
|
+
// FastlaneRunnerAPIVersion [0.9.153]
|
|
@@ -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.
|
|
598
|
+
// FastlaneRunnerAPIVersion [0.9.164]
|
|
@@ -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.
|
|
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
|
data/fastlane/swift/main.swift
CHANGED
|
@@ -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.
|
|
50
|
+
// FastlaneRunnerAPIVersion [0.9.3]
|
data/fastlane_core/README.md
CHANGED
|
@@ -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
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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.
|
|
46
|
-
rescue
|
|
47
|
-
# The
|
|
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
|
|
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
|
-
#
|
|
57
|
-
status
|
|
58
|
-
raise FastlanePtyError.new(e, 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)
|