fastlane 2.73.0 → 2.74.0.beta.20180106010004
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/deliver/lib/assets/summary.html.erb +2 -1
- data/fastlane/lib/fastlane.rb +0 -2
- data/fastlane/lib/fastlane/commands_generator.rb +5 -2
- data/fastlane/lib/fastlane/lane_manager.rb +0 -45
- data/fastlane/lib/fastlane/lane_manager_base.rb +4 -4
- data/fastlane/lib/fastlane/runner.rb +4 -0
- data/fastlane/lib/fastlane/server/{command.rb → action_command.rb} +16 -25
- data/fastlane/lib/fastlane/server/action_command_return.rb +14 -0
- data/fastlane/lib/fastlane/server/command_executor.rb +0 -2
- data/fastlane/lib/fastlane/server/command_parser.rb +20 -0
- data/fastlane/lib/fastlane/server/control_command.rb +23 -0
- data/fastlane/lib/fastlane/server/json_return_value_processor.rb +71 -0
- data/fastlane/lib/fastlane/server/socket_server.rb +111 -112
- data/fastlane/lib/fastlane/server/socket_server_action_command_executor.rb +4 -3
- data/fastlane/lib/fastlane/swift_lane_manager.rb +17 -6
- data/fastlane/lib/fastlane/version.rb +1 -1
- data/fastlane/swift/ControlCommand.swift +71 -0
- data/fastlane/swift/FastlaneSwiftRunner/FastlaneSwiftRunner.xcodeproj/project.pbxproj +8 -0
- data/fastlane/swift/LaneFileProtocol.swift +55 -27
- data/fastlane/swift/RubyCommand.swift +3 -6
- data/fastlane/swift/RubyCommandable.swift +38 -0
- data/fastlane/swift/Runner.swift +6 -3
- data/fastlane/swift/SocketClient.swift +43 -27
- data/fastlane/swift/SocketResponse.swift +7 -2
- data/fastlane/swift/main.swift +5 -3
- metadata +24 -24
- data/fastlane/lib/.DS_Store +0 -0
- data/fastlane/lib/assets/.DS_Store +0 -0
- data/fastlane/lib/fastlane/.DS_Store +0 -0
- data/fastlane/lib/fastlane/actions/.DS_Store +0 -0
- data/fastlane/lib/fastlane/actions/docs/.DS_Store +0 -0
- data/fastlane/lib/fastlane/setup/.DS_Store +0 -0
@@ -1,4 +1,5 @@
|
|
1
|
-
require 'fastlane/server/
|
1
|
+
require 'fastlane/server/action_command_return.rb'
|
2
|
+
require 'fastlane/server/command_parser.rb'
|
2
3
|
require 'fastlane/server/command_executor.rb'
|
3
4
|
|
4
5
|
module Fastlane
|
@@ -44,7 +45,7 @@ module Fastlane
|
|
44
45
|
parameter_map: parameter_map
|
45
46
|
)
|
46
47
|
|
47
|
-
command_return =
|
48
|
+
command_return = ActionCommandReturn.new(
|
48
49
|
return_value: action_return,
|
49
50
|
return_value_type: action_class_ref.return_type,
|
50
51
|
closure_argument_value: closure_argument_value
|
@@ -88,7 +89,7 @@ module Fastlane
|
|
88
89
|
action_return = Fastlane::FastFile.sh(command_param, log: log_param, error_callback: error_callback)
|
89
90
|
end
|
90
91
|
|
91
|
-
command_return =
|
92
|
+
command_return = ActionCommandReturn.new(
|
92
93
|
return_value: action_return,
|
93
94
|
return_value_type: action_return_type,
|
94
95
|
closure_argument_value: closure_argument_value
|
@@ -26,23 +26,34 @@ module Fastlane
|
|
26
26
|
socket_thread = self.start_socket_thread
|
27
27
|
sleep(0.250) while socket_thread[:ready].nil?
|
28
28
|
# wait on socket_thread to be in ready state, then start the runner thread
|
29
|
-
|
29
|
+
self.cruise_swift_lane_in_thread(lane, parameters)
|
30
30
|
|
31
|
-
runner_thread.join
|
32
31
|
socket_thread.join
|
33
32
|
rescue Exception => ex # rubocop:disable Lint/RescueException
|
33
|
+
e = ex
|
34
|
+
end
|
35
|
+
# If we have a thread exception, drop that in the exception
|
36
|
+
# won't ever have a situation where e is non-nil, and socket_thread[:exception] is also non-nil
|
37
|
+
e ||= socket_thread[:exception]
|
38
|
+
|
39
|
+
unless e.nil?
|
40
|
+
print_lane_context
|
41
|
+
|
34
42
|
# We also catch Exception, since the implemented action might send a SystemExit signal
|
35
43
|
# (or similar). We still want to catch that, since we want properly finish running fastlane
|
36
44
|
# Tested with `xcake`, which throws a `Xcake::Informative` object
|
45
|
+
UI.error e.to_s if e.kind_of?(StandardError) # we don't want to print things like 'system exit'
|
46
|
+
end
|
37
47
|
|
38
|
-
|
39
|
-
|
40
|
-
|
48
|
+
skip_message = false
|
49
|
+
exit_reason = socket_thread[:exit_reason]
|
50
|
+
if exit_reason == :cancelled && e.nil?
|
51
|
+
skip_message = true
|
41
52
|
end
|
42
53
|
|
43
54
|
duration = ((Time.now - started) / 60.0).round
|
44
55
|
|
45
|
-
finish_fastlane(nil, duration, e)
|
56
|
+
finish_fastlane(nil, duration, e, skip_message: skip_message)
|
46
57
|
end
|
47
58
|
|
48
59
|
def self.display_lanes
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Fastlane
|
2
|
-
VERSION = '2.
|
2
|
+
VERSION = '2.74.0.beta.20180106010004'.freeze
|
3
3
|
DESCRIPTION = "The easiest way to automate beta deployments and releases for your iOS and Android apps".freeze
|
4
4
|
MINIMUM_XCODE_RELEASE = "7.0".freeze
|
5
5
|
RUBOCOP_REQUIREMENT = '0.49.1'.freeze
|
@@ -0,0 +1,71 @@
|
|
1
|
+
//
|
2
|
+
// ClientShutdownCommand.swift
|
3
|
+
// FastlaneRunner
|
4
|
+
//
|
5
|
+
// Created by Joshua Liebowitz on 1/3/18.
|
6
|
+
// Copyright © 2018 Joshua Liebowitz. All rights reserved.
|
7
|
+
//
|
8
|
+
|
9
|
+
import Foundation
|
10
|
+
|
11
|
+
struct ControlCommand: RubyCommandable {
|
12
|
+
static let commandKey = "command"
|
13
|
+
var type: CommandType { return .control }
|
14
|
+
|
15
|
+
enum ShutdownCommandType {
|
16
|
+
static let userMessageKey: String = "userMessage"
|
17
|
+
|
18
|
+
enum CancelReason {
|
19
|
+
static let reasonKey: String = "reason"
|
20
|
+
case clientError
|
21
|
+
case serverError
|
22
|
+
|
23
|
+
var reasonText: String {
|
24
|
+
switch self {
|
25
|
+
case .clientError:
|
26
|
+
return "clientError"
|
27
|
+
case .serverError:
|
28
|
+
return "serverError"
|
29
|
+
}
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
case done
|
34
|
+
case cancel(cancelReason: CancelReason)
|
35
|
+
|
36
|
+
var token: String {
|
37
|
+
switch self {
|
38
|
+
case .done:
|
39
|
+
return "done"
|
40
|
+
case .cancel:
|
41
|
+
return "cancelFastlaneRun"
|
42
|
+
}
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
let message: String?
|
47
|
+
let shutdownCommandType: ShutdownCommandType
|
48
|
+
var commandJson: String {
|
49
|
+
var jsonDictionary: [String: Any] = [ControlCommand.commandKey : self.shutdownCommandType.token]
|
50
|
+
|
51
|
+
if let message = message {
|
52
|
+
jsonDictionary[ShutdownCommandType.userMessageKey] = message
|
53
|
+
}
|
54
|
+
if case .cancel(let reason) = shutdownCommandType {
|
55
|
+
jsonDictionary[ShutdownCommandType.CancelReason.reasonKey] = reason.reasonText
|
56
|
+
}
|
57
|
+
|
58
|
+
let jsonData = try! JSONSerialization.data(withJSONObject: jsonDictionary, options: [])
|
59
|
+
let jsonString = String(data: jsonData, encoding: .utf8)!
|
60
|
+
return jsonString
|
61
|
+
}
|
62
|
+
|
63
|
+
init(commandType: ShutdownCommandType, message: String? = nil) {
|
64
|
+
self.shutdownCommandType = commandType
|
65
|
+
self.message = message
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
// Please don't remove the lines below
|
70
|
+
// They are used to detect outdated files
|
71
|
+
// FastlaneRunnerAPIVersion [0.9.2]
|
@@ -32,7 +32,9 @@
|
|
32
32
|
D55B28C91F6C588300DC42C5 /* Snapshotfile.swift in Sources */ = {isa = PBXBuildFile; fileRef = D55B28C21F6C588300DC42C5 /* Snapshotfile.swift */; };
|
33
33
|
D5A7C48F1F7C4DAF00A91DE6 /* Appfile.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A7C48D1F7C4DAF00A91DE6 /* Appfile.swift */; };
|
34
34
|
D5A7C4901F7C4DAF00A91DE6 /* Fastfile.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A7C48E1F7C4DAF00A91DE6 /* Fastfile.swift */; };
|
35
|
+
D5B8A5B31FFDC49E00536B24 /* ControlCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5B8A5B21FFDC49D00536B24 /* ControlCommand.swift */; };
|
35
36
|
D5BAFD121F7DAAFC0030B324 /* ArgumentProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5BAFD111F7DAAFC0030B324 /* ArgumentProcessor.swift */; };
|
37
|
+
D5D1DE991FFEE8EA00502A00 /* RubyCommandable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5D1DE981FFEE8E900502A00 /* RubyCommandable.swift */; };
|
36
38
|
/* End PBXBuildFile section */
|
37
39
|
|
38
40
|
/* Begin PBXFileReference section */
|
@@ -62,7 +64,9 @@
|
|
62
64
|
D55B28C21F6C588300DC42C5 /* Snapshotfile.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Snapshotfile.swift; path = ../Snapshotfile.swift; sourceTree = "<group>"; };
|
63
65
|
D5A7C48D1F7C4DAF00A91DE6 /* Appfile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Appfile.swift; path = ../Appfile.swift; sourceTree = "<group>"; };
|
64
66
|
D5A7C48E1F7C4DAF00A91DE6 /* Fastfile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Fastfile.swift; path = ../Fastfile.swift; sourceTree = "<group>"; };
|
67
|
+
D5B8A5B21FFDC49D00536B24 /* ControlCommand.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ControlCommand.swift; path = ../ControlCommand.swift; sourceTree = "<group>"; };
|
65
68
|
D5BAFD111F7DAAFC0030B324 /* ArgumentProcessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ArgumentProcessor.swift; path = ../ArgumentProcessor.swift; sourceTree = "<group>"; };
|
69
|
+
D5D1DE981FFEE8E900502A00 /* RubyCommandable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RubyCommandable.swift; path = ../RubyCommandable.swift; sourceTree = "<group>"; };
|
66
70
|
/* End PBXFileReference section */
|
67
71
|
|
68
72
|
/* Begin PBXFrameworksBuildPhase section */
|
@@ -107,7 +111,9 @@
|
|
107
111
|
B3BA65B11F5A325E00B34850 /* Networking */ = {
|
108
112
|
isa = PBXGroup;
|
109
113
|
children = (
|
114
|
+
D5B8A5B21FFDC49D00536B24 /* ControlCommand.swift */,
|
110
115
|
B3BA65A01F5A269100B34850 /* RubyCommand.swift */,
|
116
|
+
D5D1DE981FFEE8E900502A00 /* RubyCommandable.swift */,
|
111
117
|
B3BA65A11F5A269100B34850 /* Runner.swift */,
|
112
118
|
B3BA65A21F5A269100B34850 /* SocketClient.swift */,
|
113
119
|
B3BA65A31F5A269100B34850 /* SocketClientDelegateProtocol.swift */,
|
@@ -225,6 +231,7 @@
|
|
225
231
|
buildActionMask = 2147483647;
|
226
232
|
files = (
|
227
233
|
B3BA65A91F5A269100B34850 /* RubyCommand.swift in Sources */,
|
234
|
+
D5D1DE991FFEE8EA00502A00 /* RubyCommandable.swift in Sources */,
|
228
235
|
D55B28C41F6C588300DC42C5 /* Gymfile.swift in Sources */,
|
229
236
|
B302067D1F5E3E9000DE6EBD /* MatchfileProtocol.swift in Sources */,
|
230
237
|
B3BA65AC1F5A269100B34850 /* SocketClientDelegateProtocol.swift in Sources */,
|
@@ -243,6 +250,7 @@
|
|
243
250
|
B30206811F5E3E9000DE6EBD /* DeliverfileProtocol.swift in Sources */,
|
244
251
|
B3BA65AA1F5A269100B34850 /* Runner.swift in Sources */,
|
245
252
|
B3BA65AF1F5A2D5C00B34850 /* RunnerArgument.swift in Sources */,
|
253
|
+
D5B8A5B31FFDC49E00536B24 /* ControlCommand.swift in Sources */,
|
246
254
|
B302067E1F5E3E9000DE6EBD /* PrecheckfileProtocol.swift in Sources */,
|
247
255
|
B3BA65AD1F5A269100B34850 /* SocketResponse.swift in Sources */,
|
248
256
|
B3BA65A81F5A269100B34850 /* main.swift in Sources */,
|
@@ -10,8 +10,8 @@ import Foundation
|
|
10
10
|
|
11
11
|
public protocol LaneFileProtocol: class {
|
12
12
|
var fastlaneVersion: String { get }
|
13
|
-
static func runLane(named: String, parameters: [String : String])
|
14
|
-
|
13
|
+
static func runLane(named: String, parameters: [String : String]) -> Bool
|
14
|
+
|
15
15
|
func recordLaneDescriptions()
|
16
16
|
func beforeAll()
|
17
17
|
func afterAll(currentLane: String)
|
@@ -29,38 +29,54 @@ public extension LaneFileProtocol {
|
|
29
29
|
@objcMembers
|
30
30
|
public class LaneFile: NSObject, LaneFileProtocol {
|
31
31
|
private(set) static var fastfileInstance: Fastfile?
|
32
|
-
|
32
|
+
|
33
33
|
// Called before any lane is executed.
|
34
34
|
private func setupAllTheThings() {
|
35
|
-
// Step 1, add lange descriptions
|
36
|
-
(self as! Fastfile).recordLaneDescriptions()
|
37
|
-
|
38
|
-
// Step 2, run beforeAll() function
|
39
35
|
LaneFile.fastfileInstance!.beforeAll()
|
40
36
|
}
|
41
|
-
|
42
|
-
|
43
|
-
|
37
|
+
|
38
|
+
private static func trimLaneFromName(laneName: String) -> String {
|
39
|
+
return String(laneName.prefix(laneName.count - 4))
|
40
|
+
}
|
41
|
+
|
42
|
+
private static func trimLaneWithOptionsFromName(laneName: String) -> String {
|
43
|
+
return String(laneName.prefix(laneName.count - 12))
|
44
|
+
}
|
45
|
+
|
46
|
+
private static var laneFunctionNames: [String] {
|
47
|
+
var lanes: [String] = []
|
44
48
|
var methodCount: UInt32 = 0
|
45
49
|
let methodList = class_copyMethodList(self, &methodCount)
|
46
50
|
for i in 0..<Int(methodCount) {
|
47
51
|
let selName = sel_getName(method_getName(methodList![i]))
|
48
52
|
let name = String(cString: selName)
|
53
|
+
let lowercasedName = name.lowercased()
|
54
|
+
if lowercasedName.hasSuffix("lane") || lowercasedName.hasSuffix("lanewithoptions:") {
|
55
|
+
lanes.append(name)
|
56
|
+
}
|
57
|
+
}
|
58
|
+
return lanes
|
59
|
+
}
|
60
|
+
|
61
|
+
public static var lanes: [String : String] {
|
62
|
+
var laneToMethodName: [String : String] = [:]
|
63
|
+
self.laneFunctionNames.forEach { name in
|
49
64
|
let lowercasedName = name.lowercased()
|
50
65
|
if lowercasedName.hasSuffix("lane") {
|
51
66
|
laneToMethodName[lowercasedName] = name
|
52
|
-
let lowercasedNameNoLane =
|
67
|
+
let lowercasedNameNoLane = trimLaneFromName(laneName: lowercasedName)
|
53
68
|
laneToMethodName[lowercasedNameNoLane] = name
|
54
69
|
} else if lowercasedName.hasSuffix("lanewithoptions:") {
|
55
|
-
let lowercasedNameNoOptions =
|
70
|
+
let lowercasedNameNoOptions = trimLaneWithOptionsFromName(laneName: lowercasedName)
|
56
71
|
laneToMethodName[lowercasedNameNoOptions] = name
|
57
|
-
let lowercasedNameNoLane =
|
72
|
+
let lowercasedNameNoLane = trimLaneFromName(laneName: lowercasedNameNoOptions)
|
58
73
|
laneToMethodName[lowercasedNameNoLane] = name
|
59
74
|
}
|
60
75
|
}
|
76
|
+
|
61
77
|
return laneToMethodName
|
62
78
|
}
|
63
|
-
|
79
|
+
|
64
80
|
public static func loadFastfile() {
|
65
81
|
if self.fastfileInstance == nil {
|
66
82
|
let fastfileType: AnyObject.Type = NSClassFromString(self.className())!
|
@@ -69,38 +85,50 @@ public class LaneFile: NSObject, LaneFileProtocol {
|
|
69
85
|
self.fastfileInstance = currentFastfileInstance
|
70
86
|
}
|
71
87
|
}
|
72
|
-
|
73
|
-
public static func runLane(named: String, parameters: [String : String]) {
|
88
|
+
|
89
|
+
public static func runLane(named: String, parameters: [String : String]) -> Bool {
|
74
90
|
log(message: "Running lane: \(named)")
|
75
91
|
self.loadFastfile()
|
76
|
-
|
92
|
+
|
77
93
|
guard let fastfileInstance: Fastfile = self.fastfileInstance else {
|
78
94
|
let message = "Unable to instantiate class named: \(self.className())"
|
79
95
|
log(message: message)
|
80
96
|
fatalError(message)
|
81
97
|
}
|
82
|
-
|
83
|
-
// call all methods that need to be called before we start calling lanes
|
84
|
-
fastfileInstance.setupAllTheThings()
|
85
|
-
|
98
|
+
|
86
99
|
let currentLanes = self.lanes
|
87
100
|
let lowerCasedLaneRequested = named.lowercased()
|
88
|
-
|
101
|
+
|
89
102
|
guard let laneMethod = currentLanes[lowerCasedLaneRequested] else {
|
90
|
-
let
|
103
|
+
let laneNames = self.laneFunctionNames.map { laneFuctionName in
|
104
|
+
if laneFuctionName.hasSuffix("lanewithoptions:") {
|
105
|
+
return trimLaneWithOptionsFromName(laneName: laneFuctionName)
|
106
|
+
} else {
|
107
|
+
return trimLaneFromName(laneName: laneFuctionName)
|
108
|
+
}
|
109
|
+
}.joined(separator: ", ")
|
110
|
+
|
111
|
+
let message = "[!] Could not find lane '\(named)'. Available lanes: \(laneNames)"
|
91
112
|
log(message: message)
|
92
|
-
|
113
|
+
|
114
|
+
let shutdownCommand = ControlCommand(commandType: .cancel(cancelReason: .clientError), message: message)
|
115
|
+
_ = runner.executeCommand(shutdownCommand)
|
116
|
+
return false
|
93
117
|
}
|
94
|
-
|
118
|
+
|
119
|
+
// call all methods that need to be called before we start calling lanes
|
120
|
+
fastfileInstance.setupAllTheThings()
|
121
|
+
|
95
122
|
// We need to catch all possible errors here and display a nice message
|
96
123
|
_ = fastfileInstance.perform(NSSelectorFromString(laneMethod), with: parameters)
|
97
|
-
|
124
|
+
|
98
125
|
// only call on success
|
99
126
|
fastfileInstance.afterAll(currentLane: named)
|
100
127
|
log(message: "Done running lane: \(named) 🚀")
|
128
|
+
return true
|
101
129
|
}
|
102
130
|
}
|
103
131
|
|
104
132
|
// Please don't remove the lines below
|
105
133
|
// They are used to detect outdated files
|
106
|
-
// FastlaneRunnerAPIVersion [0.9.
|
134
|
+
// FastlaneRunnerAPIVersion [0.9.2]
|
@@ -8,11 +8,9 @@
|
|
8
8
|
|
9
9
|
import Foundation
|
10
10
|
|
11
|
-
protocol RubyCommandable {
|
12
|
-
var json: String { get }
|
13
|
-
}
|
14
|
-
|
15
11
|
struct RubyCommand: RubyCommandable {
|
12
|
+
var type: CommandType { return .action }
|
13
|
+
|
16
14
|
struct Argument {
|
17
15
|
enum ArgType {
|
18
16
|
case stringClosure
|
@@ -41,7 +39,6 @@ struct RubyCommand: RubyCommandable {
|
|
41
39
|
|
42
40
|
var json: String {
|
43
41
|
get {
|
44
|
-
|
45
42
|
if let someValue = value {
|
46
43
|
let typeJson: String
|
47
44
|
if let type = type {
|
@@ -102,7 +99,7 @@ struct RubyCommand: RubyCommandable {
|
|
102
99
|
callbackClosure(callbackArg)
|
103
100
|
}
|
104
101
|
|
105
|
-
var
|
102
|
+
var commandJson: String {
|
106
103
|
let argsArrayJson = self.args
|
107
104
|
.map { $0.json }
|
108
105
|
.filter { $0 != "" }
|
@@ -0,0 +1,38 @@
|
|
1
|
+
//
|
2
|
+
// RubyCommandable.swift
|
3
|
+
// FastlaneRunner
|
4
|
+
//
|
5
|
+
// Created by Joshua Liebowitz on 1/4/18.
|
6
|
+
// Copyright © 2018 Joshua Liebowitz. All rights reserved.
|
7
|
+
//
|
8
|
+
|
9
|
+
import Foundation
|
10
|
+
|
11
|
+
enum CommandType {
|
12
|
+
case action
|
13
|
+
case control
|
14
|
+
|
15
|
+
var token: String {
|
16
|
+
switch self {
|
17
|
+
case .action:
|
18
|
+
return "action"
|
19
|
+
case .control:
|
20
|
+
return "control"
|
21
|
+
}
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
25
|
+
protocol RubyCommandable {
|
26
|
+
var type: CommandType { get }
|
27
|
+
var commandJson: String { get }
|
28
|
+
}
|
29
|
+
|
30
|
+
extension RubyCommandable {
|
31
|
+
var json: String {
|
32
|
+
return "{\"commandType\" : \"\(self.type.token)\", \"command\" : \(self.commandJson)}"
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
// Please don't remove the lines below
|
37
|
+
// They are used to detect outdated files
|
38
|
+
// FastlaneRunnerAPIVersion [0.9.2]
|
data/fastlane/swift/Runner.swift
CHANGED
@@ -27,7 +27,7 @@ class Runner {
|
|
27
27
|
fileprivate var returnValue: String? // lol, so safe
|
28
28
|
fileprivate var currentlyExecutingCommand: RubyCommandable? = nil
|
29
29
|
fileprivate var shouldLeaveDispatchGroupDuringDisconnect = false
|
30
|
-
|
30
|
+
|
31
31
|
func executeCommand(_ command: RubyCommandable) -> String {
|
32
32
|
self.dispatchGroup.enter()
|
33
33
|
currentlyExecutingCommand = command
|
@@ -115,7 +115,10 @@ extension Runner : SocketClientDelegateProtocol {
|
|
115
115
|
}
|
116
116
|
}
|
117
117
|
self.dispatchGroup.leave()
|
118
|
-
|
118
|
+
case .clientInitiatedCancelAcknowledged:
|
119
|
+
verbose(message: "server acknowledged a cancel request")
|
120
|
+
self.dispatchGroup.leave()
|
121
|
+
|
119
122
|
case .alreadyClosedSockets, .connectionFailure, .malformedRequest, .malformedResponse, .serverError:
|
120
123
|
log(message: "error encountered while executing command:\n\(serverResponse)")
|
121
124
|
self.dispatchGroup.leave()
|
@@ -187,4 +190,4 @@ func verbose(message: String) {
|
|
187
190
|
|
188
191
|
// Please don't remove the lines below
|
189
192
|
// They are used to detect outdated files
|
190
|
-
// FastlaneRunnerAPIVersion [0.9.
|
193
|
+
// FastlaneRunnerAPIVersion [0.9.2]
|
@@ -13,6 +13,7 @@ public enum SocketClientResponse: Error {
|
|
13
13
|
case malformedRequest
|
14
14
|
case malformedResponse
|
15
15
|
case serverError
|
16
|
+
case clientInitiatedCancelAcknowledged
|
16
17
|
case commandTimeout(seconds: Int)
|
17
18
|
case connectionFailure
|
18
19
|
case success(returnedObject: String?, closureArgumentValue: String?)
|
@@ -27,7 +28,8 @@ class SocketClient: NSObject {
|
|
27
28
|
|
28
29
|
static let connectTimeoutSeconds = 2
|
29
30
|
static let defaultCommandTimeoutSeconds = 3_600 // Hopefully 1 hr is enough ¯\_(ツ)_/¯
|
30
|
-
static let doneToken = "done"
|
31
|
+
static let doneToken = "done" // TODO: remove these
|
32
|
+
static let cancelToken = "cancelFastlaneRun"
|
31
33
|
|
32
34
|
fileprivate var inputStream: InputStream!
|
33
35
|
fileprivate var outputStream: OutputStream!
|
@@ -106,7 +108,7 @@ class SocketClient: NSObject {
|
|
106
108
|
}
|
107
109
|
|
108
110
|
public func sendComplete() {
|
109
|
-
sendAbort
|
111
|
+
closeSession(sendAbort: true)
|
110
112
|
}
|
111
113
|
|
112
114
|
private func testDispatchTimeoutResult(_ timeoutResult: DispatchTimeoutResult, failureMessage: String, timeToWait: DispatchTimeInterval) -> Bool {
|
@@ -130,42 +132,50 @@ class SocketClient: NSObject {
|
|
130
132
|
private func stopOutputSession() {
|
131
133
|
outputStream.close()
|
132
134
|
}
|
133
|
-
|
134
|
-
private func
|
135
|
-
guard !self.cleaningUpAfterDone else {
|
136
|
-
// This will happen after we abort if there are commands waiting to be executed
|
137
|
-
// Need to check state of SocketClient in command runner to make sure we can accept `send`
|
138
|
-
socketDelegate?.commandExecuted(serverResponse: .alreadyClosedSockets)
|
139
|
-
return
|
140
|
-
}
|
141
|
-
|
142
|
-
if string == SocketClient.doneToken {
|
143
|
-
self.cleaningUpAfterDone = true
|
144
|
-
}
|
145
|
-
|
146
|
-
self.dispatchGroup.enter()
|
135
|
+
|
136
|
+
private func sendThroughQueue(string: String) {
|
147
137
|
streamQueue.async {
|
148
138
|
let data = string.data(using: .utf8)!
|
149
139
|
_ = data.withUnsafeBytes { self.outputStream.write($0, maxLength: data.count) }
|
150
140
|
}
|
141
|
+
}
|
151
142
|
|
152
|
-
|
143
|
+
private func privateSend(string: String) {
|
144
|
+
self.dispatchGroup.enter()
|
145
|
+
sendThroughQueue(string: string)
|
153
146
|
|
147
|
+
let timeoutSeconds = self.cleaningUpAfterDone ? 1 : self.commandTimeoutSeconds
|
154
148
|
let timeToWait = DispatchTimeInterval.seconds(timeoutSeconds)
|
155
149
|
let commandTimeout = DispatchTime.now() + timeToWait
|
156
150
|
let timeoutResult = self.dispatchGroup.wait(timeout: commandTimeout)
|
157
151
|
|
158
152
|
_ = testDispatchTimeoutResult(timeoutResult, failureMessage: "Ruby process didn't return after: \(SocketClient.connectTimeoutSeconds) seconds", timeToWait: timeToWait)
|
159
153
|
}
|
160
|
-
|
161
|
-
func
|
154
|
+
|
155
|
+
private func send(string: String) {
|
156
|
+
guard !self.cleaningUpAfterDone else {
|
157
|
+
// This will happen after we abort if there are commands waiting to be executed
|
158
|
+
// Need to check state of SocketClient in command runner to make sure we can accept `send`
|
159
|
+
socketDelegate?.commandExecuted(serverResponse: .alreadyClosedSockets)
|
160
|
+
return
|
161
|
+
}
|
162
|
+
|
163
|
+
if string == SocketClient.doneToken {
|
164
|
+
self.cleaningUpAfterDone = true
|
165
|
+
}
|
166
|
+
|
167
|
+
privateSend(string: string)
|
168
|
+
}
|
169
|
+
|
170
|
+
func closeSession(sendAbort: Bool = true) {
|
162
171
|
self.socketStatus = .closed
|
163
|
-
|
172
|
+
|
164
173
|
stopInputSession()
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
174
|
+
|
175
|
+
if sendAbort {
|
176
|
+
send(rubyCommand: ControlCommand(commandType: .done))
|
177
|
+
}
|
178
|
+
|
169
179
|
stopOutputSession()
|
170
180
|
self.socketDelegate?.connectionsClosed()
|
171
181
|
}
|
@@ -188,7 +198,7 @@ extension SocketClient: StreamDelegate {
|
|
188
198
|
|
189
199
|
case Stream.Event.errorOccurred:
|
190
200
|
verbose(message: "input stream error occurred")
|
191
|
-
sendAbort
|
201
|
+
closeSession(sendAbort: true)
|
192
202
|
|
193
203
|
case Stream.Event.hasBytesAvailable:
|
194
204
|
read()
|
@@ -246,7 +256,8 @@ extension SocketClient: StreamDelegate {
|
|
246
256
|
|
247
257
|
func handleFailure(message: [String]) {
|
248
258
|
log(message: "Encountered a problem: \(message.joined(separator:"\n"))")
|
249
|
-
|
259
|
+
let shutdownCommand = ControlCommand(commandType: .cancel(cancelReason: .serverError))
|
260
|
+
self.send(rubyCommand: shutdownCommand)
|
250
261
|
}
|
251
262
|
|
252
263
|
func processResponse(string: String) {
|
@@ -261,6 +272,10 @@ extension SocketClient: StreamDelegate {
|
|
261
272
|
let socketResponse = SocketResponse(payload: responseString)
|
262
273
|
verbose(message: "response is: \(responseString)")
|
263
274
|
switch socketResponse.responseType {
|
275
|
+
case .clientInitiatedCancel:
|
276
|
+
self.socketDelegate?.commandExecuted(serverResponse: .clientInitiatedCancelAcknowledged)
|
277
|
+
self.closeSession(sendAbort: false)
|
278
|
+
|
264
279
|
case .failure(let failureInformation):
|
265
280
|
self.socketDelegate?.commandExecuted(serverResponse: .serverError)
|
266
281
|
self.handleFailure(message: failureInformation)
|
@@ -274,10 +289,11 @@ extension SocketClient: StreamDelegate {
|
|
274
289
|
// cool, ready for next command
|
275
290
|
break
|
276
291
|
}
|
292
|
+
|
277
293
|
self.dispatchGroup.leave() // should now pull the next piece of work
|
278
294
|
}
|
279
295
|
}
|
280
296
|
|
281
297
|
// Please don't remove the lines below
|
282
298
|
// They are used to detect outdated files
|
283
|
-
// FastlaneRunnerAPIVersion [0.9.
|
299
|
+
// FastlaneRunnerAPIVersion [0.9.2]
|