diff --git a/Sources/ProjectDescription/Project.swift b/Sources/ProjectDescription/Project.swift index 6921d9f47b4..73177b7d4ec 100644 --- a/Sources/ProjectDescription/Project.swift +++ b/Sources/ProjectDescription/Project.swift @@ -6,22 +6,26 @@ public class Project: Codable { public let name: String public let up: [Up] public let targets: [Target] + public let schemes: [Scheme] public let settings: Settings? public enum CodingKeys: String, CodingKey { case name case up case targets + case schemes case settings } public init(name: String, up: [Up] = [], settings: Settings? = nil, - targets: [Target] = []) { + targets: [Target] = [], + schemes: [Scheme] = []) { self.name = name self.up = up self.targets = targets + self.schemes = schemes self.settings = settings dumpIfNeeded(self) } diff --git a/Sources/ProjectDescription/Scheme.swift b/Sources/ProjectDescription/Scheme.swift index 81d005d9290..75fc3db7d0b 100644 --- a/Sources/ProjectDescription/Scheme.swift +++ b/Sources/ProjectDescription/Scheme.swift @@ -8,6 +8,7 @@ public class Scheme: Codable { public let buildAction: BuildAction? public let testAction: TestAction? public let runAction: RunAction? + public let archiveAction: ArchiveAction? public enum CodingKeys: String, CodingKey { case name @@ -15,18 +16,42 @@ public class Scheme: Codable { case buildAction = "build_action" case testAction = "test_action" case runAction = "run_action" + case archiveAction = "archive_action" } public init(name: String, shared: Bool = true, buildAction: BuildAction? = nil, testAction: TestAction? = nil, - runAction: RunAction? = nil) { + runAction: RunAction? = nil, + archiveAction: ArchiveAction? = nil) { self.name = name self.shared = shared self.buildAction = buildAction self.testAction = testAction self.runAction = runAction + self.archiveAction = archiveAction + } +} + +// MARK: - SchemeAction + +public class SchemeAction: Codable { + + public let title: String + public let scriptText: String + public let target: String? + + public enum CodingKeys: String, CodingKey { + case title + case scriptText + case target + } + + public init(title: String = "Run Script", scriptText: String, target: String? = nil) { + self.title = title + self.scriptText = scriptText + self.target = target } } @@ -51,14 +76,23 @@ public class Arguments: Codable { // MARK: - BuildAction public class BuildAction: Codable { + public let targets: [String] + public let preActions: [SchemeAction] + public let postActions: [SchemeAction] public enum CodingKeys: String, CodingKey { case targets + case preActions = "pre_actions" + case postActions = "post_actions" } - public init(targets: [String]) { + public init(targets: [String], + preActions: [SchemeAction] = [], + postActions: [SchemeAction] = []) { self.targets = targets + self.preActions = preActions + self.postActions = postActions } } @@ -66,6 +100,9 @@ public class BuildAction: Codable { public class TestAction: Codable { public let targets: [String] + public let preActions: [SchemeAction] + public let postActions: [SchemeAction] + public let arguments: Arguments? public let config: BuildConfiguration public let coverage: Bool @@ -75,16 +112,22 @@ public class TestAction: Codable { case arguments case config case coverage + case preActions = "pre_actions" + case postActions = "post_actions" } public init(targets: [String], arguments: Arguments? = nil, config: BuildConfiguration = .debug, + preActions: [SchemeAction] = [], + postActions: [SchemeAction] = [], coverage: Bool = false) { self.targets = targets self.arguments = arguments self.config = config self.coverage = coverage + self.preActions = preActions + self.postActions = postActions } } @@ -109,3 +152,26 @@ public class RunAction: Codable { self.arguments = arguments } } + +// MARK: - ArchiveAction + +public class ArchiveAction: Codable { + + public let config: BuildConfiguration + public let preActions: [SchemeAction] + public let postActions: [SchemeAction] + + public enum CodingKeys: String, CodingKey { + case config + case preActions = "pre_actions" + case postActions = "post_actions" + } + + public init(config: BuildConfiguration = .release, + preActions: [SchemeAction] = [], + postActions: [SchemeAction] = []) { + self.config = config + self.preActions = preActions + self.postActions = postActions + } +} diff --git a/Sources/TuistKit/Generator/ProjectGenerator.swift b/Sources/TuistKit/Generator/ProjectGenerator.swift index aa09bb62653..463b8967c7e 100644 --- a/Sources/TuistKit/Generator/ProjectGenerator.swift +++ b/Sources/TuistKit/Generator/ProjectGenerator.swift @@ -146,7 +146,7 @@ final class ProjectGenerator: ProjectGenerating { /// Schemes let generatedProject = GeneratedProject(path: xcodeprojPath, targets: nativeTargets) - try schemesGenerator.generateTargetSchemes(project: project, + try schemesGenerator.generateSchemes(project: project, generatedProject: generatedProject) return generatedProject diff --git a/Sources/TuistKit/Generator/SchemesGenerator.swift b/Sources/TuistKit/Generator/SchemesGenerator.swift index 90929f0378f..3c0eefd4dc5 100644 --- a/Sources/TuistKit/Generator/SchemesGenerator.swift +++ b/Sources/TuistKit/Generator/SchemesGenerator.swift @@ -11,8 +11,8 @@ protocol SchemesGenerating { /// - project: Project manifest. /// - generatedProject: Generated Xcode project. /// - Throws: A FatalError if the generation of the schemes fails. - func generateTargetSchemes(project: Project, - generatedProject: GeneratedProject) throws + func generateSchemes(project: Project, + generatedProject: GeneratedProject) throws } final class SchemesGenerator: SchemesGenerating { @@ -26,117 +26,186 @@ final class SchemesGenerator: SchemesGenerating { self.fileHandler = fileHandler } + /// Generates the schemes for the project manifest. + /// + /// - Parameters: + /// - project: Project manifest. + /// - generatedProject: Generated Xcode project. + /// - Throws: A FatalError if the generation of the schemes fails. + func generateSchemes(project: Project, generatedProject: GeneratedProject) throws { + + if project.schemes.isEmpty { + /// Generate scheme for every targets in Project + try generateTargetSchemes(project: project, generatedProject: generatedProject) + } else { + /// Generate scheme from manifest + try project.schemes.forEach { scheme in + try generateScheme(scheme: scheme, project: project, generatedProject: generatedProject) + } + } + } + /// Generates the schemes for the project targets. /// /// - Parameters: /// - project: Project manifest. /// - generatedProject: Generated Xcode project. /// - Throws: A FatalError if the generation of the schemes fails. - func generateTargetSchemes(project: Project, - generatedProject: GeneratedProject) throws { + + func generateTargetSchemes(project: Project, generatedProject: GeneratedProject) throws { try project.targets.forEach { target in - let pbxTarget = generatedProject.targets[target.name]! - try generateTargetScheme(target: target, - pbxTarget: pbxTarget, - projectPath: generatedProject.path) + let scheme = Scheme(name: target.name, + shared: true, + buildAction: BuildAction(targets: [target.name]), + testAction: TestAction(targets: [target.name]), + runAction: RunAction(config: .debug, executable: target.name)) + + try generateScheme(scheme: scheme, + project: project, + generatedProject: generatedProject) } } - - /// Generates the scheme for a given target. + /// Generates the scheme. /// /// - Parameters: - /// - target: Target manifest. - /// - pbxTarget: Xcode native target. - /// - projectPath: Path to the Xcode project (folder with extension .xcodeproj) + /// - scheme: Scheme manifest. + /// - project: Project manifest. + /// - generatedProject: Generated Xcode project. /// - Throws: An error if the generation fails. - func generateTargetScheme(target: Target, - pbxTarget: PBXNativeTarget, - projectPath: AbsolutePath) throws { - let schemesDirectory = try createSchemesDirectory(projectPath: projectPath) - let schemePath = schemesDirectory.appending(component: "\(target.name).xcscheme") + func generateScheme(scheme: Scheme, + project: Project, + generatedProject: GeneratedProject) throws { + let schemesDirectory = try createSchemesDirectory(projectPath: generatedProject.path) + let schemePath = schemesDirectory.appending(component: "\(scheme.name).xcscheme") - let scheme = XCScheme(name: target.name, + let generatedBuildAction = buildAction(scheme: scheme, project: project, generatedProject: generatedProject) + let generatedTestAction = testAction(scheme: scheme, project: project, generatedProject: generatedProject) + let generatedLaunchAction = launchAction(scheme: scheme, project: project, generatedProject: generatedProject) + let generatedProfileAction = profileAction(scheme: scheme, project: project, generatedProject: generatedProject) + let generatedArchiveAction = archiveAction(scheme: scheme, project: project, generatedProject: generatedProject) + + let scheme = XCScheme(name: scheme.name, lastUpgradeVersion: "1010", - version: "1.3", - buildAction: buildAction(target: target, - pbxTarget: pbxTarget, - projectPath: projectPath), - testAction: testAction(target: target, - pbxTarget: pbxTarget, - projectPath: projectPath), - launchAction: launchAction(target: target, - pbxTarget: pbxTarget, - projectPath: projectPath), - profileAction: profileAction(target: target, - pbxTarget: pbxTarget, - projectPath: projectPath), + version: "1.7", + buildAction: generatedBuildAction, + testAction: generatedTestAction, + launchAction: generatedLaunchAction, + profileAction: generatedProfileAction, analyzeAction: analyzeAction(), - archiveAction: archiveAction()) + archiveAction: generatedArchiveAction) try scheme.write(path: schemePath.path, override: true) } - /// Generates the scheme test action for a given target. + /// Generates the scheme test action. /// /// - Parameters: - /// - target: Target manifest. - /// - pbxTarget: Xcode native target. - /// - projectPath: Path to the Xcode project. + /// - scheme: Scheme manifest. + /// - project: Project manifest. + /// - generatedProject: Generated Xcode project. /// - Returns: Scheme test action. - func testAction(target: Target, - pbxTarget: PBXNativeTarget, - projectPath: AbsolutePath) -> XCScheme.TestAction? { + func testAction(scheme: Scheme, + project: Project, + generatedProject: GeneratedProject) -> XCScheme.TestAction? { + var testables: [XCScheme.TestableReference] = [] - if target.product.testsBundle { - let reference = buildableReference(target: target, - pbxTarget: pbxTarget, - projectPath: projectPath) - let testable = XCScheme.TestableReference(skipped: false, - buildableReference: reference) + var preActions: [XCScheme.ExecutionAction] = [] + var postActions: [XCScheme.ExecutionAction] = [] + + scheme.testAction?.targets.forEach { name in + guard let target = project.targets.first(where: { $0.name == name }), target.product.testsBundle else { return } + guard let pbxTarget = generatedProject.targets[name] else { return } + + let reference = self.buildableReference(target: target, + pbxTarget: pbxTarget, + projectPath: generatedProject.path) + + let testable = XCScheme.TestableReference(skipped: false, buildableReference: reference) testables.append(testable) } + + scheme.buildAction.flatMap { buildAction in + preActions = schemeActions(actions: buildAction.preActions, + project: project, + generatedProject: generatedProject) + + postActions = schemeActions(actions: buildAction.postActions, + project: project, + generatedProject: generatedProject) + } + return XCScheme.TestAction(buildConfiguration: "Debug", macroExpansion: nil, - testables: testables) + testables: testables, + preActions: preActions, + postActions: postActions) } - - /// Generates the scheme build action for a given target. + + /// Generates the scheme build action. /// /// - Parameters: - /// - target: Target manifest. - /// - pbxTarget: Xcode native target. - /// - projectPath: Path to the Xcode project. + /// - scheme: Scheme manifest. + /// - project: Project manifest. + /// - generatedProject: Generated Xcode project. /// - Returns: Scheme build action. - func buildAction(target: Target, - pbxTarget: PBXNativeTarget, - projectPath: AbsolutePath) -> XCScheme.BuildAction? { + func buildAction(scheme: Scheme, + project: Project, + generatedProject: GeneratedProject) -> XCScheme.BuildAction? { + let buildFor: [XCScheme.BuildAction.Entry.BuildFor] = [ .analyzing, .archiving, .profiling, .running, .testing ] - let buildableReference = self.buildableReference(target: target, - pbxTarget: pbxTarget, - projectPath: projectPath) var entries: [XCScheme.BuildAction.Entry] = [] - entries.append(XCScheme.BuildAction.Entry(buildableReference: buildableReference, buildFor: buildFor)) + var preActions: [XCScheme.ExecutionAction] = [] + var postActions: [XCScheme.ExecutionAction] = [] + + scheme.buildAction?.targets.forEach { name in + debugPrint(name) + guard let target = project.targets.first(where: { $0.name == name }) else { return } + debugPrint(target) + guard let pbxTarget = generatedProject.targets[name] else { return } + debugPrint(pbxTarget) + let buildableReference = self.buildableReference(target: target, + pbxTarget: pbxTarget, + projectPath: generatedProject.path) + + entries.append(XCScheme.BuildAction.Entry(buildableReference: buildableReference, buildFor: buildFor)) + } + + scheme.buildAction.flatMap { buildAction in + preActions = schemeActions(actions: buildAction.preActions, + project: project, + generatedProject: generatedProject) + + postActions = schemeActions(actions: buildAction.postActions, + project: project, + generatedProject: generatedProject) + } return XCScheme.BuildAction(buildActionEntries: entries, - parallelizeBuild: true, - buildImplicitDependencies: true) + preActions: preActions, + postActions: postActions, + parallelizeBuild: true, buildImplicitDependencies: true) } - - /// Generates the scheme launch action for a given target. + + /// Generates the scheme launch action. /// /// - Parameters: - /// - target: Target manifest. - /// - pbxTarget: Xcode native target. - /// - projectPath: Path to the Xcode project. + /// - scheme: Scheme manifest. + /// - project: Project manifest. + /// - generatedProject: Generated Xcode project. /// - Returns: Scheme launch action. - func launchAction(target: Target, - pbxTarget: PBXNativeTarget, - projectPath: AbsolutePath) -> XCScheme.LaunchAction? { + func launchAction(scheme: Scheme, + project: Project, + generatedProject: GeneratedProject) -> XCScheme.LaunchAction? { var buildableProductRunnable: XCScheme.BuildableProductRunnable? var macroExpansion: XCScheme.BuildableReference? - let buildableReference = self.buildableReference(target: target, pbxTarget: pbxTarget, projectPath: projectPath) + + guard let executable = scheme.runAction?.executable else { return nil } + guard let target = project.targets.first(where: { $0.name == executable }) else { return nil } + guard let pbxTarget = generatedProject.targets[executable] else { return nil } + + let buildableReference = self.buildableReference(target: target, pbxTarget: pbxTarget, projectPath: project.path) if target.product.runnable { buildableProductRunnable = XCScheme.BuildableProductRunnable(buildableReference: buildableReference, runnableDebuggingMode: "0") } else { @@ -145,25 +214,31 @@ final class SchemesGenerator: SchemesGenerating { let environmentVariables: [XCScheme.EnvironmentVariable] = target.environment.map({ variable, value in XCScheme.EnvironmentVariable(variable: variable, value: value, enabled: true) }) + return XCScheme.LaunchAction(buildableProductRunnable: buildableProductRunnable, buildConfiguration: "Debug", macroExpansion: macroExpansion, environmentVariables: environmentVariables) } - /// Generates the scheme profile action for a given target. + /// Generates the scheme profile action. /// /// - Parameters: - /// - target: Target manifest. - /// - pbxTarget: Xcode native target. - /// - projectPath: Path to the Xcode project. + /// - scheme: Scheme manifest. + /// - project: Project manifest. + /// - generatedProject: Generated Xcode project. /// - Returns: Scheme profile action. - func profileAction(target: Target, - pbxTarget: PBXNativeTarget, - projectPath: AbsolutePath) -> XCScheme.ProfileAction? { + func profileAction(scheme: Scheme, + project: Project, + generatedProject: GeneratedProject) -> XCScheme.ProfileAction? { var buildableProductRunnable: XCScheme.BuildableProductRunnable? var macroExpansion: XCScheme.BuildableReference? - let buildableReference = self.buildableReference(target: target, pbxTarget: pbxTarget, projectPath: projectPath) + + guard let executable = scheme.runAction?.executable else { return nil } + guard let target = project.targets.first(where: { $0.name == executable }) else { return nil } + guard let pbxTarget = generatedProject.targets[executable] else { return nil } + + let buildableReference = self.buildableReference(target: target, pbxTarget: pbxTarget, projectPath: project.path) if target.product.runnable { buildableProductRunnable = XCScheme.BuildableProductRunnable(buildableReference: buildableReference, runnableDebuggingMode: "0") @@ -175,7 +250,6 @@ final class SchemesGenerator: SchemesGenerating { macroExpansion: macroExpansion) } - /// Returns the scheme buildable reference for a given target. /// /// - Parameters: /// - target: Target manifest. @@ -190,7 +264,42 @@ final class SchemesGenerator: SchemesGenerating { blueprintName: target.name, buildableIdentifier: "primary") } + + /// Returns the scheme pre/post actions. + /// + /// - Parameters: + /// - actions: pre/post action manifest. + /// - project: Project manifest. + /// - generatedProject: Generated Xcode project. + /// - Returns: Scheme actions. + func schemeActions(actions: [ExecutionAction], + project: Project, + generatedProject: GeneratedProject) -> [XCScheme.ExecutionAction] { + + /// Return Buildable Reference for Scheme Action + func schemeBuildableReference(targetName: String?, project: Project, generatedProject: GeneratedProject) -> XCScheme.BuildableReference? { + + guard let targetName = targetName else { return nil } + guard let target = project.targets.first(where: { $0.name == targetName }) else { return nil } + guard let pbxTarget = generatedProject.targets[targetName] else { return nil } + + return self.buildableReference(target: target, pbxTarget: pbxTarget, projectPath: generatedProject.path) + } + var schemeActions: [XCScheme.ExecutionAction] = [] + actions.forEach { action in + let schemeAction = XCScheme.ExecutionAction(scriptText: action.scriptText, + title: action.title, + environmentBuildable: nil) + + schemeAction.environmentBuildable = schemeBuildableReference(targetName: action.target, + project: project, + generatedProject: generatedProject) + schemeActions.append(schemeAction) + } + return schemeActions + } + /// Returns the scheme analyze action for a given target. /// /// - Returns: Scheme analyze action. @@ -200,10 +309,32 @@ final class SchemesGenerator: SchemesGenerating { /// Returns the scheme archive action for a given target. /// + /// - Parameters: + /// - scheme: Scheme manifest. + /// - project: Project manifest. + /// - generatedProject: Generated Xcode project. /// - Returns: Scheme archive action. - func archiveAction() -> XCScheme.ArchiveAction { + func archiveAction(scheme: Scheme, + project: Project, + generatedProject: GeneratedProject) -> XCScheme.ArchiveAction { + + var preActions: [XCScheme.ExecutionAction] = [] + var postActions: [XCScheme.ExecutionAction] = [] + + scheme.archiveAction.flatMap { action in + preActions = schemeActions(actions: action.preActions, + project: project, + generatedProject: generatedProject) + + postActions = schemeActions(actions: action.postActions, + project: project, + generatedProject: generatedProject) + } + return XCScheme.ArchiveAction(buildConfiguration: "Release", - revealArchiveInOrganizer: true) + revealArchiveInOrganizer: true, + preActions: preActions, + postActions: postActions) } /// Creates the directory where the schemes are stored inside the project. diff --git a/Sources/TuistKit/Models/Project.swift b/Sources/TuistKit/Models/Project.swift index f9985163b02..2a2c7e16711 100644 --- a/Sources/TuistKit/Models/Project.swift +++ b/Sources/TuistKit/Models/Project.swift @@ -17,6 +17,9 @@ class Project: Equatable { /// Project targets. let targets: [Target] + /// Project schemes + let schemes: [Scheme] + /// Project settings. let settings: Settings? @@ -33,11 +36,13 @@ class Project: Equatable { name: String, up: [Upping] = [], settings: Settings? = nil, + schemes: [Scheme] = [], targets: [Target]) { self.path = path self.name = name self.up = up self.targets = targets + self.schemes = schemes self.settings = settings } @@ -76,6 +81,10 @@ class Project: Equatable { name = try json.get("name") let targetsJSONs: [JSON] = try json.get("targets") targets = try targetsJSONs.map({ try Target(dictionary: $0, projectPath: path, fileHandler: fileHandler) }) + + let schemesJSONs: [JSON] = try json.get("schemes") + schemes = try schemesJSONs.map({ try Scheme(json: $0) }) + let upJSONs: [JSON] = try json.get("up") up = try upJSONs.compactMap({ try Up.with(dictionary: $0, projectPath: path, fileHandler: fileHandler) }) let settingsJSON: JSON? = try? json.get("settings") @@ -88,6 +97,7 @@ class Project: Equatable { return lhs.path == rhs.path && lhs.name == rhs.name && lhs.targets == rhs.targets && + lhs.schemes == rhs.schemes && lhs.settings == rhs.settings } } diff --git a/Sources/TuistKit/Models/Scheme.swift b/Sources/TuistKit/Models/Scheme.swift index 3a023d66137..627fc0a2005 100644 --- a/Sources/TuistKit/Models/Scheme.swift +++ b/Sources/TuistKit/Models/Scheme.swift @@ -9,19 +9,22 @@ class Scheme: JSONMappable, Equatable { let buildAction: BuildAction? let testAction: TestAction? let runAction: RunAction? - + let archiveAction: ArchiveAction? + // MARK: - Init init(name: String, shared: Bool = false, buildAction: BuildAction? = nil, testAction: TestAction? = nil, - runAction: RunAction? = nil) { + runAction: RunAction? = nil, + archiveAction: ArchiveAction? = nil) { self.name = name self.shared = shared self.buildAction = buildAction self.testAction = testAction self.runAction = runAction + self.archiveAction = archiveAction } required init(json: JSON) throws { @@ -30,6 +33,7 @@ class Scheme: JSONMappable, Equatable { buildAction = try? json.get("build_action") testAction = try? json.get("test_action") runAction = try? json.get("run_action") + archiveAction = try? json.get("archive_action") } // MARK: - Equatable @@ -39,7 +43,8 @@ class Scheme: JSONMappable, Equatable { lhs.shared == rhs.shared && lhs.buildAction == rhs.buildAction && lhs.testAction == rhs.testAction && - lhs.runAction == rhs.runAction + lhs.runAction == rhs.runAction && + lhs.archiveAction == rhs.archiveAction } } @@ -70,39 +75,105 @@ class Arguments: JSONMappable, Equatable { } } -class BuildAction: JSONMappable, Equatable { +class ExecutionAction: JSONMappable, Equatable { + + // MARK: - Attributes + + let title: String + let scriptText: String + let target: String? + + // MARK: - Init + + init(title: String, + scriptText: String, + target: String?) { + self.title = title + self.scriptText = scriptText + self.target = target + } + + required init(json: JSON) throws { + self.title = try json.get("title") + self.scriptText = try json.get("scriptText") + self.target = try? json.get("target") + } + + static func == (lhs: ExecutionAction, rhs: ExecutionAction) -> Bool { + return lhs.title == rhs.title && + lhs.scriptText == rhs.scriptText && + lhs.target == rhs.target + } +} + +class SerialAction: JSONMappable, Equatable { + + let preActions: [ExecutionAction] + let postActions: [ExecutionAction] + + // MARK: - Init + + init(preActions: [ExecutionAction] = [], + postActions: [ExecutionAction] = []) { + self.preActions = preActions + self.postActions = postActions + } + + required init(json: JSON) throws { + preActions = try json.get("pre_actions") + postActions = try json.get("post_actions") + } + + // MARK: - Equatable + + static func == (lhs: SerialAction, rhs: SerialAction) -> Bool { + return lhs.preActions == rhs.preActions && + lhs.postActions == rhs.postActions + } + +} +class BuildAction: SerialAction { // MARK: - Attributes let targets: [String] // MARK: - Init - init(targets: [String] = []) { + init(targets: [String], + preActions: [ExecutionAction] = [], + postActions: [ExecutionAction] = []) { self.targets = targets + super.init(preActions: preActions, postActions: postActions) } required init(json: JSON) throws { targets = try json.get("targets") + try super.init(json: json) } // MARK: - Equatable static func == (lhs: BuildAction, rhs: BuildAction) -> Bool { - return lhs.targets == rhs.targets + return lhs.targets == rhs.targets && + lhs.preActions == rhs.preActions && + lhs.postActions == rhs.postActions } } -class TestAction: JSONMappable, Equatable { +class TestAction: SerialAction { // MARK: - Attributes let targets: [String] let arguments: Arguments? let config: BuildConfiguration let coverage: Bool + // MARK: - Init init(targets: [String] = [], + preActions: [ExecutionAction] = [], + postActions: [ExecutionAction] = [], arguments: Arguments? = nil, config: BuildConfiguration = .debug, coverage: Bool = false) { @@ -110,6 +181,7 @@ class TestAction: JSONMappable, Equatable { self.arguments = arguments self.config = config self.coverage = coverage + super.init(preActions: preActions, postActions: postActions) } required init(json: JSON) throws { @@ -118,6 +190,7 @@ class TestAction: JSONMappable, Equatable { let configString: String = try json.get("config") config = BuildConfiguration(rawValue: configString)! coverage = try json.get("coverage") + try super.init(json: json) } // MARK: - Equatable @@ -126,7 +199,9 @@ class TestAction: JSONMappable, Equatable { return lhs.targets == rhs.targets && lhs.arguments == rhs.arguments && lhs.config == rhs.config && - lhs.coverage == rhs.coverage + lhs.coverage == rhs.coverage && + lhs.preActions == rhs.preActions && + lhs.postActions == rhs.postActions } } @@ -162,3 +237,32 @@ class RunAction: JSONMappable, Equatable { lhs.arguments == rhs.arguments } } + +class ArchiveAction: SerialAction { + + let config: BuildConfiguration + + // MARK: - Init + + init(config: BuildConfiguration, + preActions: [ExecutionAction] = [], + postActions: [ExecutionAction] = []) { + self.config = config + super.init(preActions: preActions, postActions: postActions) + } + + required init(json: JSON) throws { + let configString: String = try json.get("config") + config = BuildConfiguration(rawValue: configString)! + try super.init(json: json) + } + + // MARK: - Equatable + + static func == (lhs: ArchiveAction, rhs: ArchiveAction) -> Bool { + return lhs.config == rhs.config && + lhs.preActions == rhs.preActions && + lhs.postActions == rhs.postActions + } +} +