fastlane 2.149.1 → 2.150.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/deliver/lib/deliver.rb +0 -1
- data/deliver/lib/deliver/app_screenshot.rb +26 -25
- data/deliver/lib/deliver/options.rb +6 -11
- data/deliver/lib/deliver/runner.rb +7 -4
- data/deliver/lib/deliver/setup.rb +5 -30
- data/deliver/lib/deliver/submit_for_review.rb +124 -87
- data/deliver/lib/deliver/upload_metadata.rb +284 -143
- data/deliver/lib/deliver/upload_price_tier.rb +15 -8
- data/deliver/lib/deliver/upload_screenshots.rb +86 -37
- data/fastlane/lib/fastlane/actions/docs/capture_ios_screenshots.md +1 -1
- data/fastlane/lib/fastlane/actions/docs/upload_to_app_store.md.erb +3 -11
- data/fastlane/lib/fastlane/actions/docs/upload_to_play_store.md +3 -2
- data/fastlane/lib/fastlane/actions/download_dsyms.rb +7 -1
- data/fastlane/lib/fastlane/actions/google_play_track_release_names.rb +74 -0
- data/fastlane/lib/fastlane/actions/slack.rb +1 -1
- data/fastlane/lib/fastlane/actions/spm.rb +7 -0
- data/fastlane/lib/fastlane/actions/upload_symbols_to_crashlytics.rb +1 -32
- data/fastlane/lib/fastlane/lane.rb +3 -3
- data/fastlane/lib/fastlane/swift_fastlane_function.rb +8 -4
- data/fastlane/lib/fastlane/version.rb +1 -1
- data/fastlane/swift/ControlCommand.swift +1 -0
- data/fastlane/swift/Fastlane.swift +48 -12
- data/fastlane/swift/FastlaneSwiftRunner/FastlaneSwiftRunner.xcodeproj/xcshareddata/xcschemes/FastlaneRunner.xcscheme +3 -9
- data/fastlane/swift/LaneFileProtocol.swift +2 -5
- data/fastlane/swift/MatchfileProtocol.swift +1 -1
- data/fastlane/swift/RubyCommand.swift +29 -6
- data/fastlane/swift/RubyCommandable.swift +1 -0
- data/fastlane/swift/Runner.swift +85 -13
- data/fastlane/swift/ScanfileProtocol.swift +1 -1
- data/fastlane/swift/SnapshotfileProtocol.swift +3 -3
- data/fastlane/swift/SocketClient.swift +76 -45
- data/fastlane/swift/SocketClientDelegateProtocol.swift +1 -1
- data/fastlane/swift/SocketResponse.swift +1 -0
- data/fastlane_core/lib/fastlane_core/configuration/config_item.rb +1 -3
- data/fastlane_core/lib/fastlane_core/pkg_file_analyser.rb +7 -0
- data/frameit/lib/frameit/device_types.rb +100 -100
- data/produce/lib/produce/itunes_connect.rb +20 -20
- data/produce/lib/produce/options.rb +3 -3
- data/sigh/lib/assets/resign.sh +7 -7
- data/snapshot/lib/assets/SnapshotHelper.swift +5 -5
- data/snapshot/lib/assets/SnapshotHelperXcode8.swift +3 -3
- data/snapshot/lib/snapshot/options.rb +0 -1
- data/snapshot/lib/snapshot/reports_generator.rb +8 -1
- data/spaceship/lib/spaceship/.DS_Store +0 -0
- data/spaceship/lib/spaceship/connect_api.rb +21 -2
- data/spaceship/lib/spaceship/connect_api/client.rb +47 -11
- data/spaceship/lib/spaceship/connect_api/model.rb +1 -1
- data/spaceship/lib/spaceship/connect_api/models/age_rating_declaration.rb +109 -0
- data/spaceship/lib/spaceship/connect_api/models/app.rb +113 -3
- data/spaceship/lib/spaceship/connect_api/models/app_category.rb +94 -0
- data/spaceship/lib/spaceship/connect_api/models/app_info.rb +74 -0
- data/spaceship/lib/spaceship/connect_api/models/app_info_localization.rb +38 -0
- data/spaceship/lib/spaceship/connect_api/models/app_price.rb +22 -0
- data/spaceship/lib/spaceship/connect_api/models/app_price_tier.rb +12 -0
- data/spaceship/lib/spaceship/connect_api/models/app_review_attachment.rb +81 -0
- data/spaceship/lib/spaceship/connect_api/models/app_screenshot.rb +117 -0
- data/spaceship/lib/spaceship/connect_api/models/app_screenshot_set.rb +101 -0
- data/spaceship/lib/spaceship/connect_api/models/app_store_review_detail.rb +51 -0
- data/spaceship/lib/spaceship/connect_api/models/app_store_version.rb +182 -0
- data/spaceship/lib/spaceship/connect_api/models/app_store_version_localization.rb +70 -0
- data/spaceship/lib/spaceship/connect_api/models/app_store_version_phased_release.rb +36 -0
- data/spaceship/lib/spaceship/connect_api/models/app_store_version_submission.rb +26 -0
- data/spaceship/lib/spaceship/connect_api/models/build.rb +4 -0
- data/spaceship/lib/spaceship/connect_api/models/idfa_declaration.rb +40 -0
- data/spaceship/lib/spaceship/connect_api/models/reset_ratings_request.rb +26 -0
- data/spaceship/lib/spaceship/connect_api/testflight/testflight.rb +10 -3
- data/spaceship/lib/spaceship/connect_api/tunes/client.rb +33 -0
- data/spaceship/lib/spaceship/connect_api/tunes/tunes.rb +703 -0
- data/spaceship/lib/spaceship/spaceauth_runner.rb +2 -2
- data/supply/lib/supply/client.rb +19 -0
- data/supply/lib/supply/reader.rb +16 -0
- metadata +27 -24
- data/deliver/lib/deliver/upload_assets.rb +0 -27
- data/scan/lib/scan/.test_command_generator.rb.swp +0 -0
- data/snapshot/lib/snapshot/.test_command_generator_base.rb.swp +0 -0
@@ -49,6 +49,7 @@ struct ControlCommand: RubyCommandable {
|
|
49
49
|
}
|
50
50
|
|
51
51
|
let message: String?
|
52
|
+
let id: String = UUID().uuidString
|
52
53
|
let shutdownCommandType: ShutdownCommandType
|
53
54
|
var commandJson: String {
|
54
55
|
var jsonDictionary: [String: Any] = [ControlCommand.commandKey : self.shutdownCommandType.token]
|
@@ -1491,7 +1491,7 @@ func captureIosScreenshots(workspace: String? = nil,
|
|
1491
1491
|
appIdentifier: String? = nil,
|
1492
1492
|
addPhotos: [String]? = nil,
|
1493
1493
|
addVideos: [String]? = nil,
|
1494
|
-
htmlTemplate: String =
|
1494
|
+
htmlTemplate: String? = nil,
|
1495
1495
|
buildlogPath: String = "~/Library/Logs/snapshot",
|
1496
1496
|
clean: Bool = false,
|
1497
1497
|
testWithoutBuilding: Bool? = nil,
|
@@ -1625,7 +1625,7 @@ func captureScreenshots(workspace: String? = nil,
|
|
1625
1625
|
appIdentifier: String? = nil,
|
1626
1626
|
addPhotos: [String]? = nil,
|
1627
1627
|
addVideos: [String]? = nil,
|
1628
|
-
htmlTemplate: String =
|
1628
|
+
htmlTemplate: String? = nil,
|
1629
1629
|
buildlogPath: String = "~/Library/Logs/snapshot",
|
1630
1630
|
clean: Bool = false,
|
1631
1631
|
testWithoutBuilding: Bool? = nil,
|
@@ -2039,7 +2039,7 @@ func cocoapods(repoUpdate: Bool = false,
|
|
2039
2039
|
ansi: Bool = true,
|
2040
2040
|
useBundleExec: Bool = true,
|
2041
2041
|
podfile: String? = nil,
|
2042
|
-
errorCallback:
|
2042
|
+
errorCallback: ((String) -> Void)? = nil,
|
2043
2043
|
tryRepoUpdateOnError: Bool = false,
|
2044
2044
|
deployment: Bool = false,
|
2045
2045
|
clean: Bool = true,
|
@@ -2051,7 +2051,7 @@ func cocoapods(repoUpdate: Bool = false,
|
|
2051
2051
|
RubyCommand.Argument(name: "ansi", value: ansi),
|
2052
2052
|
RubyCommand.Argument(name: "use_bundle_exec", value: useBundleExec),
|
2053
2053
|
RubyCommand.Argument(name: "podfile", value: podfile),
|
2054
|
-
RubyCommand.Argument(name: "error_callback", value: errorCallback),
|
2054
|
+
RubyCommand.Argument(name: "error_callback", value: errorCallback, type: .stringClosure),
|
2055
2055
|
RubyCommand.Argument(name: "try_repo_update_on_error", value: tryRepoUpdateOnError),
|
2056
2056
|
RubyCommand.Argument(name: "deployment", value: deployment),
|
2057
2057
|
RubyCommand.Argument(name: "clean", value: clean),
|
@@ -3054,7 +3054,7 @@ func frameScreenshots(white: Bool? = nil,
|
|
3054
3054
|
useLegacyIphonexr: Bool = false,
|
3055
3055
|
useLegacyIphonexs: Bool = false,
|
3056
3056
|
useLegacyIphonexsmax: Bool = false,
|
3057
|
-
forceOrientationBlock: String? = nil,
|
3057
|
+
forceOrientationBlock: ((String) -> Void)? = nil,
|
3058
3058
|
debugMode: Bool = false,
|
3059
3059
|
resume: Bool = false,
|
3060
3060
|
usePlatform: String = "IOS",
|
@@ -3071,7 +3071,7 @@ func frameScreenshots(white: Bool? = nil,
|
|
3071
3071
|
RubyCommand.Argument(name: "use_legacy_iphonexr", value: useLegacyIphonexr),
|
3072
3072
|
RubyCommand.Argument(name: "use_legacy_iphonexs", value: useLegacyIphonexs),
|
3073
3073
|
RubyCommand.Argument(name: "use_legacy_iphonexsmax", value: useLegacyIphonexsmax),
|
3074
|
-
RubyCommand.Argument(name: "force_orientation_block", value: forceOrientationBlock),
|
3074
|
+
RubyCommand.Argument(name: "force_orientation_block", value: forceOrientationBlock, type: .stringClosure),
|
3075
3075
|
RubyCommand.Argument(name: "debug_mode", value: debugMode),
|
3076
3076
|
RubyCommand.Argument(name: "resume", value: resume),
|
3077
3077
|
RubyCommand.Argument(name: "use_platform", value: usePlatform),
|
@@ -3116,7 +3116,7 @@ func frameit(white: Bool? = nil,
|
|
3116
3116
|
useLegacyIphonexr: Bool = false,
|
3117
3117
|
useLegacyIphonexs: Bool = false,
|
3118
3118
|
useLegacyIphonexsmax: Bool = false,
|
3119
|
-
forceOrientationBlock: String? = nil,
|
3119
|
+
forceOrientationBlock: ((String) -> Void)? = nil,
|
3120
3120
|
debugMode: Bool = false,
|
3121
3121
|
resume: Bool = false,
|
3122
3122
|
usePlatform: String = "IOS",
|
@@ -3133,7 +3133,7 @@ func frameit(white: Bool? = nil,
|
|
3133
3133
|
RubyCommand.Argument(name: "use_legacy_iphonexr", value: useLegacyIphonexr),
|
3134
3134
|
RubyCommand.Argument(name: "use_legacy_iphonexs", value: useLegacyIphonexs),
|
3135
3135
|
RubyCommand.Argument(name: "use_legacy_iphonexsmax", value: useLegacyIphonexsmax),
|
3136
|
-
RubyCommand.Argument(name: "force_orientation_block", value: forceOrientationBlock),
|
3136
|
+
RubyCommand.Argument(name: "force_orientation_block", value: forceOrientationBlock, type: .stringClosure),
|
3137
3137
|
RubyCommand.Argument(name: "debug_mode", value: debugMode),
|
3138
3138
|
RubyCommand.Argument(name: "resume", value: resume),
|
3139
3139
|
RubyCommand.Argument(name: "use_platform", value: usePlatform),
|
@@ -3639,6 +3639,42 @@ func githubApi(serverUrl: String = "https://api.github.com",
|
|
3639
3639
|
_ = runner.executeCommand(command)
|
3640
3640
|
}
|
3641
3641
|
|
3642
|
+
/**
|
3643
|
+
Retrieves release names for a Google Play track
|
3644
|
+
|
3645
|
+
- parameters:
|
3646
|
+
- packageName: The package name of the application to use
|
3647
|
+
- track: The track of the application to use. The default available tracks are: production, beta, alpha, internal
|
3648
|
+
- key: **DEPRECATED!** Use `--json_key` instead - The p12 File used to authenticate with Google
|
3649
|
+
- issuer: **DEPRECATED!** Use `--json_key` instead - The issuer of the p12 file (email address of the service account)
|
3650
|
+
- jsonKey: The path to a file containing service account JSON, used to authenticate with Google
|
3651
|
+
- jsonKeyData: The raw service account JSON data used to authenticate with Google
|
3652
|
+
- rootUrl: Root URL for the Google Play API. The provided URL will be used for API calls in place of https://www.googleapis.com/
|
3653
|
+
- timeout: Timeout for read, open, and send (in seconds)
|
3654
|
+
|
3655
|
+
- returns: Array of strings representing the release names for the given Google Play track
|
3656
|
+
|
3657
|
+
More information: [https://docs.fastlane.tools/actions/supply/](https://docs.fastlane.tools/actions/supply/)
|
3658
|
+
*/
|
3659
|
+
func googlePlayTrackReleaseNames(packageName: String,
|
3660
|
+
track: String = "production",
|
3661
|
+
key: String? = nil,
|
3662
|
+
issuer: String? = nil,
|
3663
|
+
jsonKey: String? = nil,
|
3664
|
+
jsonKeyData: String? = nil,
|
3665
|
+
rootUrl: String? = nil,
|
3666
|
+
timeout: Int = 300) {
|
3667
|
+
let command = RubyCommand(commandID: "", methodName: "google_play_track_release_names", className: nil, args: [RubyCommand.Argument(name: "package_name", value: packageName),
|
3668
|
+
RubyCommand.Argument(name: "track", value: track),
|
3669
|
+
RubyCommand.Argument(name: "key", value: key),
|
3670
|
+
RubyCommand.Argument(name: "issuer", value: issuer),
|
3671
|
+
RubyCommand.Argument(name: "json_key", value: jsonKey),
|
3672
|
+
RubyCommand.Argument(name: "json_key_data", value: jsonKeyData),
|
3673
|
+
RubyCommand.Argument(name: "root_url", value: rootUrl),
|
3674
|
+
RubyCommand.Argument(name: "timeout", value: timeout)])
|
3675
|
+
_ = runner.executeCommand(command)
|
3676
|
+
}
|
3677
|
+
|
3642
3678
|
/**
|
3643
3679
|
Retrieves version codes for a Google Play track
|
3644
3680
|
|
@@ -6520,10 +6556,10 @@ func setupTravis(force: Bool = false) {
|
|
6520
6556
|
*/
|
6521
6557
|
@discardableResult func sh(command: String,
|
6522
6558
|
log: Bool = true,
|
6523
|
-
errorCallback:
|
6559
|
+
errorCallback: ((String) -> Void)? = nil) -> String {
|
6524
6560
|
let command = RubyCommand(commandID: "", methodName: "sh", className: nil, args: [RubyCommand.Argument(name: "command", value: command),
|
6525
6561
|
RubyCommand.Argument(name: "log", value: log),
|
6526
|
-
RubyCommand.Argument(name: "error_callback", value: errorCallback)])
|
6562
|
+
RubyCommand.Argument(name: "error_callback", value: errorCallback, type: .stringClosure)])
|
6527
6563
|
return runner.executeCommand(command)
|
6528
6564
|
}
|
6529
6565
|
|
@@ -6868,7 +6904,7 @@ func snapshot(workspace: Any? = snapshotfile.workspace,
|
|
6868
6904
|
appIdentifier: Any? = snapshotfile.appIdentifier,
|
6869
6905
|
addPhotos: [String]? = snapshotfile.addPhotos,
|
6870
6906
|
addVideos: [String]? = snapshotfile.addVideos,
|
6871
|
-
htmlTemplate: Any = snapshotfile.htmlTemplate,
|
6907
|
+
htmlTemplate: Any? = snapshotfile.htmlTemplate,
|
6872
6908
|
buildlogPath: Any = snapshotfile.buildlogPath,
|
6873
6909
|
clean: Bool = snapshotfile.clean,
|
6874
6910
|
testWithoutBuilding: Bool? = snapshotfile.testWithoutBuilding,
|
@@ -8924,4 +8960,4 @@ let snapshotfile: Snapshotfile = Snapshotfile()
|
|
8924
8960
|
|
8925
8961
|
// Please don't remove the lines below
|
8926
8962
|
// They are used to detect outdated files
|
8927
|
-
// FastlaneRunnerAPIVersion [0.9.
|
8963
|
+
// FastlaneRunnerAPIVersion [0.9.71]
|
@@ -26,10 +26,7 @@
|
|
26
26
|
buildConfiguration = "Debug"
|
27
27
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
28
28
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
29
|
-
language = ""
|
30
29
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
31
|
-
<Testables>
|
32
|
-
</Testables>
|
33
30
|
<MacroExpansion>
|
34
31
|
<BuildableReference
|
35
32
|
BuildableIdentifier = "primary"
|
@@ -39,14 +36,13 @@
|
|
39
36
|
ReferencedContainer = "container:FastlaneSwiftRunner.xcodeproj">
|
40
37
|
</BuildableReference>
|
41
38
|
</MacroExpansion>
|
42
|
-
<
|
43
|
-
</
|
39
|
+
<Testables>
|
40
|
+
</Testables>
|
44
41
|
</TestAction>
|
45
42
|
<LaunchAction
|
46
43
|
buildConfiguration = "Debug"
|
47
44
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
48
45
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
49
|
-
language = ""
|
50
46
|
launchStyle = "0"
|
51
47
|
useCustomWorkingDirectory = "NO"
|
52
48
|
ignoresPersistentStateOnLaunch = "NO"
|
@@ -65,7 +61,7 @@
|
|
65
61
|
</BuildableProductRunnable>
|
66
62
|
<CommandLineArguments>
|
67
63
|
<CommandLineArgument
|
68
|
-
argument = "lane
|
64
|
+
argument = "lane testLane"
|
69
65
|
isEnabled = "YES">
|
70
66
|
</CommandLineArgument>
|
71
67
|
<CommandLineArgument
|
@@ -73,8 +69,6 @@
|
|
73
69
|
isEnabled = "YES">
|
74
70
|
</CommandLineArgument>
|
75
71
|
</CommandLineArguments>
|
76
|
-
<AdditionalOptions>
|
77
|
-
</AdditionalOptions>
|
78
72
|
</LaunchAction>
|
79
73
|
<ProfileAction
|
80
74
|
buildConfiguration = "Release"
|
@@ -19,7 +19,6 @@ public protocol LaneFileProtocol: class {
|
|
19
19
|
static func runLane(named: String, parameters: [String : String]) -> Bool
|
20
20
|
|
21
21
|
func recordLaneDescriptions()
|
22
|
-
func beforeAll(currentLane: String, parameters: [String : String])
|
23
22
|
func beforeAll()
|
24
23
|
func afterAll(currentLane: String)
|
25
24
|
func onError(currentLane: String, errorInfo: String)
|
@@ -27,7 +26,6 @@ public protocol LaneFileProtocol: class {
|
|
27
26
|
|
28
27
|
public extension LaneFileProtocol {
|
29
28
|
var fastlaneVersion: String { return "" } // default "" because that means any is fine
|
30
|
-
func beforeAll(currentLane: String, parameters: [String : String]) { } // no op by default
|
31
29
|
func beforeAll() { } // no op by default
|
32
30
|
func afterAll(currentLane: String) { } // no op by default
|
33
31
|
func onError(currentLane: String, errorInfo: String) {} // no op by default
|
@@ -39,8 +37,7 @@ public class LaneFile: NSObject, LaneFileProtocol {
|
|
39
37
|
private(set) static var fastfileInstance: Fastfile?
|
40
38
|
|
41
39
|
// Called before any lane is executed.
|
42
|
-
private func setupAllTheThings(
|
43
|
-
LaneFile.fastfileInstance!.beforeAll(currentLane: lane, parameters: parameters)
|
40
|
+
private func setupAllTheThings() {
|
44
41
|
LaneFile.fastfileInstance!.beforeAll()
|
45
42
|
}
|
46
43
|
|
@@ -126,7 +123,7 @@ public class LaneFile: NSObject, LaneFileProtocol {
|
|
126
123
|
}
|
127
124
|
|
128
125
|
// call all methods that need to be called before we start calling lanes
|
129
|
-
fastfileInstance.setupAllTheThings(
|
126
|
+
fastfileInstance.setupAllTheThings()
|
130
127
|
|
131
128
|
// We need to catch all possible errors here and display a nice message
|
132
129
|
_ = fastfileInstance.perform(NSSelectorFromString(laneMethod), with: parameters)
|
@@ -82,27 +82,50 @@ struct RubyCommand: RubyCommandable {
|
|
82
82
|
let methodName: String
|
83
83
|
let className: String?
|
84
84
|
let args: [Argument]
|
85
|
+
let id: String = UUID().uuidString
|
86
|
+
|
87
|
+
var closure: ((String) -> Void)? {
|
88
|
+
let callbacks = self.args.filter { ($0.type != nil) && $0.type == .stringClosure }
|
89
|
+
guard let callback = callbacks.first else {
|
90
|
+
return nil
|
91
|
+
}
|
92
|
+
|
93
|
+
guard let callbackArgValue = callback.value else {
|
94
|
+
return nil
|
95
|
+
}
|
85
96
|
|
86
|
-
|
97
|
+
guard let callbackClosure = callbackArgValue as? ((String) -> Void) else {
|
98
|
+
return nil
|
99
|
+
}
|
100
|
+
return callbackClosure
|
101
|
+
}
|
102
|
+
|
103
|
+
|
104
|
+
func callbackClosure(_ callbackArg: String) -> ((String) -> Void)? {
|
87
105
|
// WARNING: This will perform the first callback it receives
|
88
106
|
let callbacks = self.args.filter { ($0.type != nil) && $0.type == .stringClosure }
|
89
107
|
guard let callback = callbacks.first else {
|
90
108
|
verbose(message: "received call to performCallback with \(callbackArg), but no callback available to perform")
|
91
|
-
return
|
109
|
+
return nil
|
92
110
|
}
|
93
111
|
|
94
112
|
guard let callbackArgValue = callback.value else {
|
95
113
|
verbose(message: "received call to performCallback with \(callbackArg), but callback is nil")
|
96
|
-
return
|
114
|
+
return nil
|
97
115
|
}
|
98
116
|
|
99
117
|
guard let callbackClosure = callbackArgValue as? ((String) -> Void) else {
|
100
118
|
verbose(message: "received call to performCallback with \(callbackArg), but callback type is unknown \(callbackArgValue.self)")
|
101
|
-
return
|
119
|
+
return nil
|
102
120
|
}
|
121
|
+
return callbackClosure
|
122
|
+
}
|
103
123
|
|
104
|
-
|
105
|
-
|
124
|
+
func performCallback(callbackArg: String, socket: SocketClient, completion: @escaping () -> Void) {
|
125
|
+
verbose(message: "Performing callback with: \(callbackArg)")
|
126
|
+
socket.leave()
|
127
|
+
self.callbackClosure(callbackArg)?(callbackArg)
|
128
|
+
completion()
|
106
129
|
}
|
107
130
|
|
108
131
|
var commandJson: String {
|
data/fastlane/swift/Runner.swift
CHANGED
@@ -33,28 +33,69 @@ class Runner {
|
|
33
33
|
fileprivate var returnValue: String? // lol, so safe
|
34
34
|
fileprivate var currentlyExecutingCommand: RubyCommandable? = nil
|
35
35
|
fileprivate var shouldLeaveDispatchGroupDuringDisconnect = false
|
36
|
+
fileprivate var executeNext: [String: Bool] = [:]
|
36
37
|
|
37
38
|
func executeCommand(_ command: RubyCommandable) -> String {
|
38
39
|
self.dispatchGroup.enter()
|
39
|
-
currentlyExecutingCommand = command
|
40
|
-
socketClient.send(rubyCommand: command)
|
40
|
+
self.currentlyExecutingCommand = command
|
41
|
+
self.socketClient.send(rubyCommand: command)
|
41
42
|
|
42
43
|
let secondsToWait = DispatchTimeInterval.seconds(SocketClient.defaultCommandTimeoutSeconds)
|
43
|
-
let
|
44
|
-
|
44
|
+
let timeoutResult = waitWithPolling(self.executeNext[command.id], toEventually: { $0 == true }, timeout: SocketClient.defaultCommandTimeoutSeconds)
|
45
|
+
executeNext.removeValue(forKey: command.id)
|
45
46
|
let failureMessage = "command didn't execute in: \(SocketClient.defaultCommandTimeoutSeconds) seconds"
|
46
|
-
let success = testDispatchTimeoutResult(timeoutResult, failureMessage: failureMessage, timeToWait: secondsToWait)
|
47
|
+
let success = self.testDispatchTimeoutResult(timeoutResult, failureMessage: failureMessage, timeToWait: secondsToWait)
|
47
48
|
guard success else {
|
48
49
|
log(message: "command timeout")
|
49
50
|
fatalError()
|
50
51
|
}
|
51
52
|
|
52
|
-
if let
|
53
|
-
return
|
53
|
+
if let _returnValue = self.returnValue {
|
54
|
+
return _returnValue
|
54
55
|
} else {
|
55
56
|
return ""
|
56
57
|
}
|
57
58
|
}
|
59
|
+
|
60
|
+
private func waitWithPolling<T>(_ expression: @autoclosure @escaping () throws -> T, toEventually predicate: @escaping (T) -> Bool, timeout: Int, pollingInterval: DispatchTimeInterval = .milliseconds(4)) -> DispatchTimeoutResult {
|
61
|
+
func memoizedClosure<T>(_ closure: @escaping () throws -> T) -> (Bool) throws -> T {
|
62
|
+
var cache: T?
|
63
|
+
return { withoutCaching in
|
64
|
+
if withoutCaching || cache == nil {
|
65
|
+
cache = try closure()
|
66
|
+
}
|
67
|
+
guard let cache = cache else {
|
68
|
+
preconditionFailure()
|
69
|
+
}
|
70
|
+
|
71
|
+
return cache
|
72
|
+
}
|
73
|
+
}
|
74
|
+
|
75
|
+
let runLoop = RunLoop.current
|
76
|
+
let timeoutDate = Date(timeInterval: TimeInterval(timeout), since: Date())
|
77
|
+
var fulfilled: Bool = false
|
78
|
+
let _expression = memoizedClosure(expression)
|
79
|
+
repeat {
|
80
|
+
do {
|
81
|
+
let exp = try _expression(true)
|
82
|
+
fulfilled = predicate(exp)
|
83
|
+
} catch {
|
84
|
+
fatalError("Error raised \(error.localizedDescription)")
|
85
|
+
}
|
86
|
+
if !fulfilled {
|
87
|
+
runLoop.run(until: Date(timeIntervalSinceNow: pollingInterval.timeInterval))
|
88
|
+
} else {
|
89
|
+
break
|
90
|
+
}
|
91
|
+
} while Date().compare(timeoutDate) == .orderedAscending
|
92
|
+
|
93
|
+
if fulfilled {
|
94
|
+
return .success
|
95
|
+
} else {
|
96
|
+
return .timedOut
|
97
|
+
}
|
98
|
+
}
|
58
99
|
}
|
59
100
|
|
60
101
|
// Handle threading stuff
|
@@ -110,25 +151,36 @@ extension Runner {
|
|
110
151
|
}
|
111
152
|
|
112
153
|
extension Runner : SocketClientDelegateProtocol {
|
113
|
-
func commandExecuted(serverResponse: SocketClientResponse) {
|
154
|
+
func commandExecuted(serverResponse: SocketClientResponse, completion: (SocketClient) -> Void) {
|
114
155
|
switch serverResponse {
|
115
156
|
case .success(let returnedObject, let closureArgumentValue):
|
116
157
|
verbose(message: "command executed")
|
117
158
|
self.returnValue = returnedObject
|
118
159
|
if let command = self.currentlyExecutingCommand as? RubyCommand {
|
119
|
-
if let closureArgumentValue = closureArgumentValue {
|
120
|
-
command.performCallback(callbackArg: closureArgumentValue)
|
160
|
+
if let closureArgumentValue = closureArgumentValue, !closureArgumentValue.isEmpty {
|
161
|
+
command.performCallback(callbackArg: closureArgumentValue, socket: socketClient) {
|
162
|
+
self.executeNext[command.id] = true
|
163
|
+
}
|
164
|
+
} else {
|
165
|
+
self.executeNext[command.id] = true
|
121
166
|
}
|
122
167
|
}
|
123
|
-
|
168
|
+
dispatchGroup.leave()
|
169
|
+
completion(socketClient)
|
124
170
|
case .clientInitiatedCancelAcknowledged:
|
125
171
|
verbose(message: "server acknowledged a cancel request")
|
126
172
|
self.dispatchGroup.leave()
|
127
|
-
|
173
|
+
if let command = self.currentlyExecutingCommand as? RubyCommand {
|
174
|
+
self.executeNext[command.id] = true
|
175
|
+
}
|
176
|
+
completion(socketClient)
|
128
177
|
case .alreadyClosedSockets, .connectionFailure, .malformedRequest, .malformedResponse, .serverError:
|
129
178
|
log(message: "error encountered while executing command:\n\(serverResponse)")
|
130
179
|
self.dispatchGroup.leave()
|
131
|
-
|
180
|
+
if let command = self.currentlyExecutingCommand as? RubyCommand {
|
181
|
+
self.executeNext[command.id] = true
|
182
|
+
}
|
183
|
+
completion(socketClient)
|
132
184
|
case .commandTimeout(let timeout):
|
133
185
|
log(message: "Runner timed out after \(timeout) second(s)")
|
134
186
|
}
|
@@ -144,6 +196,7 @@ extension Runner : SocketClientDelegateProtocol {
|
|
144
196
|
DispatchQueue.main.async {
|
145
197
|
self.thread?.cancel()
|
146
198
|
self.thread = nil
|
199
|
+
self.socketClient.closeSession()
|
147
200
|
self.socketClient = nil
|
148
201
|
verbose(message: "connection closed!")
|
149
202
|
if self.shouldLeaveDispatchGroupDuringDisconnect {
|
@@ -194,6 +247,25 @@ func verbose(message: String) {
|
|
194
247
|
logger.verbose(message: message)
|
195
248
|
}
|
196
249
|
|
250
|
+
private extension DispatchTimeInterval {
|
251
|
+
var timeInterval: TimeInterval {
|
252
|
+
var result: TimeInterval = 0
|
253
|
+
switch self {
|
254
|
+
case .seconds(let value):
|
255
|
+
result = TimeInterval(value)
|
256
|
+
case .milliseconds(let value):
|
257
|
+
result = TimeInterval(value)*0.001
|
258
|
+
case .microseconds(let value):
|
259
|
+
result = TimeInterval(value)*0.000001
|
260
|
+
case .nanoseconds(let value):
|
261
|
+
result = TimeInterval(value)*0.000000001
|
262
|
+
case .never:
|
263
|
+
fatalError()
|
264
|
+
}
|
265
|
+
return result
|
266
|
+
}
|
267
|
+
}
|
268
|
+
|
197
269
|
// Please don't remove the lines below
|
198
270
|
// They are used to detect outdated files
|
199
271
|
// FastlaneRunnerAPIVersion [0.9.2]
|