Skip to content

Commit

Permalink
Added support for custom Archive Action when defining scheme
Browse files Browse the repository at this point in the history
  • Loading branch information
grdsdev authored and rowwingman committed Nov 24, 2019
1 parent 06cdcd2 commit b5c360a
Show file tree
Hide file tree
Showing 10 changed files with 213 additions and 13 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -9,6 +9,7 @@ Please, check out guidelines: https://keepachangelog.com/en/1.0.0/
- Add `ProjectDescription.Settings.defaultSettings` none case that don't override any `Project` or `Target` settings. https://github.com/tuist/tuist/pull/698 by @rowwingman.
- `ProjectEditor` utility https://github.com/tuist/tuist/pull/702 by @pepibumur.
- Fix warnings in the project, refactor SHA256 diegest code https://github.com/tuist/tuist/pull/704 by @rowwingman.
- Define `ArchiveAction` on `Scheme` https://github.com/tuist/tuist/pull/697 by @grsouza.

## 0.19.0

Expand Down
29 changes: 28 additions & 1 deletion Sources/ProjectDescription/Scheme.swift
Expand Up @@ -8,17 +8,20 @@ public struct Scheme: Equatable, Codable {
public let buildAction: BuildAction?
public let testAction: TestAction?
public let runAction: RunAction?
public let archiveAction: ArchiveAction?

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
}
}

Expand Down Expand Up @@ -132,3 +135,27 @@ public struct RunAction: Equatable, Codable {
arguments: arguments)
}
}

// MARK: - Archive Action

public struct ArchiveAction: Equatable, Codable {
public let configurationName: String
public let revealArchiveInOrganizer: Bool
public let customArchiveName: String?
public let preActions: [ExecutionAction]
public let postActions: [ExecutionAction]

public init(
configurationName: String,
revealArchiveInOrganizer: Bool = true,
customArchiveName: String? = nil,
preActions: [ExecutionAction] = [],
postActions: [ExecutionAction] = []
) {
self.configurationName = configurationName
self.revealArchiveInOrganizer = revealArchiveInOrganizer
self.customArchiveName = customArchiveName
self.preActions = preActions
self.postActions = postActions
}
}
44 changes: 42 additions & 2 deletions Sources/TuistCore/Models/Scheme.swift
Expand Up @@ -9,19 +9,22 @@ public class Scheme: Equatable {
public let buildAction: BuildAction?
public let testAction: TestAction?
public let runAction: RunAction?
public let archiveAction: ArchiveAction?

// MARK: - Init

public 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
}

// MARK: - Equatable
Expand All @@ -31,7 +34,8 @@ public class Scheme: 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
}
}

Expand Down Expand Up @@ -174,3 +178,39 @@ public class RunAction: Equatable {
lhs.arguments == rhs.arguments
}
}

public class ArchiveAction: Equatable {
// MARK: - Attributes

public let configurationName: String
public let revealArchiveInOrganizer: Bool
public let customArchiveName: String?
public let preActions: [ExecutionAction]
public let postActions: [ExecutionAction]

// MARK: - Init

public init(
configurationName: String,
revealArchiveInOrganizer: Bool = true,
customArchiveName: String? = nil,
preActions: [ExecutionAction] = [],
postActions: [ExecutionAction] = []
) {
self.configurationName = configurationName
self.revealArchiveInOrganizer = revealArchiveInOrganizer
self.customArchiveName = customArchiveName
self.preActions = preActions
self.postActions = postActions
}

// MARK: - Equatable

public static func == (lhs: ArchiveAction, rhs: ArchiveAction) -> Bool {
return lhs.configurationName == rhs.configurationName
&& lhs.revealArchiveInOrganizer == rhs.revealArchiveInOrganizer
&& lhs.customArchiveName == rhs.customArchiveName
&& lhs.preActions == rhs.preActions
&& lhs.postActions == rhs.postActions
}
}
20 changes: 18 additions & 2 deletions Sources/TuistCoreTesting/Models/Scheme+TestData.swift
Expand Up @@ -46,16 +46,32 @@ public extension BuildAction {
}
}

public extension ArchiveAction {
static func test(configurationName: String = "Beta Release",
revealArchiveInOrganizer: Bool = true,
customArchiveName: String? = nil,
preActions: [ExecutionAction] = [],
postActions: [ExecutionAction] = []) -> ArchiveAction {
return ArchiveAction(configurationName: configurationName,
revealArchiveInOrganizer: revealArchiveInOrganizer,
customArchiveName: customArchiveName,
preActions: preActions,
postActions: postActions)
}
}

public extension Scheme {
static func test(name: String = "Test",
shared: Bool = false,
buildAction: BuildAction? = BuildAction.test(),
testAction: TestAction? = TestAction.test(),
runAction: RunAction? = RunAction.test()) -> Scheme {
runAction: RunAction? = RunAction.test(),
archiveAction: ArchiveAction? = ArchiveAction.test()) -> Scheme {
return Scheme(name: name,
shared: shared,
buildAction: buildAction,
testAction: testAction,
runAction: runAction)
runAction: runAction,
archiveAction: archiveAction)
}
}
28 changes: 26 additions & 2 deletions Sources/TuistGenerator/Generator/SchemesGenerator.swift
Expand Up @@ -73,6 +73,7 @@ final class SchemesGenerator: SchemesGenerating {
let generatedTestAction = schemeTestAction(scheme: scheme, project: project, generatedProject: generatedProject)
let generatedLaunchAction = schemeLaunchAction(scheme: scheme, project: project, generatedProject: generatedProject)
let generatedProfileAction = schemeProfileAction(scheme: scheme, project: project, generatedProject: generatedProject)
let generatedArchiveAction = schemeArchiveAction(scheme: scheme, project: project, generatedProject: generatedProject)

let scheme = XCScheme(name: scheme.name,
lastUpgradeVersion: SchemesGenerator.defaultLastUpgradeVersion,
Expand All @@ -82,7 +83,7 @@ final class SchemesGenerator: SchemesGenerating {
launchAction: generatedLaunchAction,
profileAction: generatedProfileAction,
analyzeAction: schemeAnalyzeAction(for: project),
archiveAction: schemeArchiveAction(for: project))
archiveAction: generatedArchiveAction)
try scheme.write(path: schemePath.path, override: true)
}

Expand Down Expand Up @@ -147,6 +148,29 @@ final class SchemesGenerator: SchemesGenerating {
testables: testables)
}

/// Generates the scheme archive action.
/// - Parameter scheme: Scheme manifest.
/// - Parameter project: Project manifest.
/// - Parameter generatedProject: Generated Xcode project.
/// - Returns: Scheme archive action.
func schemeArchiveAction(scheme: Scheme,
project: Project,
generatedProject: GeneratedProject) -> XCScheme.ArchiveAction {
guard let archiveAction = scheme.archiveAction else {
return defaultSchemeArchiveAction(for: project)
}

return XCScheme.ArchiveAction(buildConfiguration: archiveAction.configurationName,
revealArchiveInOrganizer: archiveAction.revealArchiveInOrganizer,
customArchiveName: archiveAction.customArchiveName,
preActions: schemeExecutionActions(actions: archiveAction.preActions,
project: project,
generatedProject: generatedProject),
postActions: schemeExecutionActions(actions: archiveAction.postActions,
project: project,
generatedProject: generatedProject))
}

/// Generates the array of BuildableReference for targets that the
/// coverage report should be generated for them.
///
Expand Down Expand Up @@ -439,7 +463,7 @@ final class SchemesGenerator: SchemesGenerating {
/// Returns the scheme archive action
///
/// - Returns: Scheme archive action.
func schemeArchiveAction(for project: Project) -> XCScheme.ArchiveAction {
func defaultSchemeArchiveAction(for project: Project) -> XCScheme.ArchiveAction {
let buildConfiguration = defaultReleaseBuildConfigurationName(in: project)
return XCScheme.ArchiveAction(buildConfiguration: buildConfiguration,
revealArchiveInOrganizer: true)
Expand Down
20 changes: 19 additions & 1 deletion Sources/TuistKit/Generator/GeneratorModelLoader.swift
Expand Up @@ -586,12 +586,14 @@ extension TuistCore.Scheme {
let buildAction = manifest.buildAction.map { TuistCore.BuildAction.from(manifest: $0) }
let testAction = manifest.testAction.map { TuistCore.TestAction.from(manifest: $0) }
let runAction = manifest.runAction.map { TuistCore.RunAction.from(manifest: $0) }
let archiveAction = manifest.archiveAction.map { TuistCore.ArchiveAction.from(manifest: $0) }

return Scheme(name: name,
shared: shared,
buildAction: buildAction,
testAction: testAction,
runAction: runAction)
runAction: runAction,
archiveAction: archiveAction)
}
}

Expand Down Expand Up @@ -636,6 +638,22 @@ extension TuistCore.RunAction {
}
}

extension TuistCore.ArchiveAction {
static func from(manifest: ProjectDescription.ArchiveAction) -> TuistCore.ArchiveAction {
let configurationName = manifest.configurationName
let revealArchiveInOrganizer = manifest.revealArchiveInOrganizer
let customArchiveName = manifest.customArchiveName
let preActions = manifest.preActions.map { TuistCore.ExecutionAction.from(manifest: $0) }
let postActions = manifest.postActions.map { TuistCore.ExecutionAction.from(manifest: $0) }

return TuistCore.ArchiveAction(configurationName: configurationName,
revealArchiveInOrganizer: revealArchiveInOrganizer,
customArchiveName: customArchiveName,
preActions: preActions,
postActions: postActions)
}
}

extension TuistCore.ExecutionAction {
static func from(manifest: ProjectDescription.ExecutionAction) -> TuistCore.ExecutionAction {
return ExecutionAction(title: manifest.title, scriptText: manifest.scriptText, target: manifest.target)
Expand Down
20 changes: 18 additions & 2 deletions Tests/TuistGeneratorTests/Generator/SchemesGeneratorTests.swift
Expand Up @@ -357,12 +357,28 @@ final class SchemeGeneratorTests: XCTestCase {
XCTAssertEqual(got.buildConfiguration, "Debug")
}

func test_schemeArchiveAction() {
let got = subject.schemeArchiveAction(for: .test())
func test_defaultSchemeArchiveAction() {
let got = subject.defaultSchemeArchiveAction(for: .test())
XCTAssertEqual(got.buildConfiguration, "Release")
XCTAssertEqual(got.revealArchiveInOrganizer, true)
}

func test_schemeArchiveAction() {
let target = Target.test(name: "App", platform: .iOS, product: .app)
let scheme = Scheme.test(archiveAction: ArchiveAction.test(configurationName: "Beta Release",
revealArchiveInOrganizer: true,
customArchiveName: "App [Beta]"))
let pbxTarget = PBXNativeTarget(name: "App")
let project = Project.test(path: AbsolutePath("/project.xcodeproj"), targets: [target])
let generatedProject = GeneratedProject.test(targets: ["App": pbxTarget])

let got = subject.schemeArchiveAction(scheme: scheme, project: project, generatedProject: generatedProject)

XCTAssertEqual(got.buildConfiguration, "Beta Release")
XCTAssertEqual(got.customArchiveName, "App [Beta]")
XCTAssertEqual(got.revealArchiveInOrganizer, true)
}

// MARK: - Private

private func generatedProject(targets: [Target]) -> GeneratedProject {
Expand Down
55 changes: 55 additions & 0 deletions docs/usage/projectswift.mdx
Expand Up @@ -673,6 +673,14 @@ A `Scheme` defines a collection of targets to `Build, Run, Test, Profile, Analyz
optional: true,
default: 'nil',
},
{
name: 'Archive action',
description: 'Action that runs the project archive.',
type: 'ArchiveAction',
typeLink: '#archive-action',
optional: true,
default: 'nil',
},
]}
/>

Expand Down Expand Up @@ -908,6 +916,53 @@ Arguments contain commandline arguments passed on launch and Environment variabl
]}
/>

### Archive Action

<PropertiesTable
properties={[
{
name: 'Configuration Name',
description:
'Indicates the build configuration to run the archive with.',
type: 'String',
optional: false,
default: '',
},
{
name: 'Reveal Archive in Organizer',
description:
'If set to true, Xcode will reveal the Organizer on completion.',
type: 'Bool',
optional: true,
default: 'true',
},
{
name: 'Custom Archive Name',
description:
'Set if you want to override Xcode's default archive name.',
type: 'String',
optional: true,
default: 'nil',
},
{
name: 'Pre-actions',
description:
'A list of actions that are executed before starting the archive process.',
type: '[ExecutionAction]',
optional: true,
default: '[]',
},
{
name: 'Post-actions',
description:
'A list of actions that are executed after the archive process.',
type: '[ExecutionAction]',
optional: true,
default: '[]',
},
]}
/>

## Settings

A `Settings` object contains an optional dictionary with build settings and relative path to an `.xcconfig` file. It is initialized with the following attributes:
Expand Down
2 changes: 2 additions & 0 deletions features/generate.feature
Expand Up @@ -180,6 +180,7 @@ Scenario: The project is an iOS application with multiple configurations (ios_ap
Then the scheme Framework2 has a build setting CUSTOM_FLAG with value "Debug" for the configuration Debug
Then the scheme Framework2 has a build setting CUSTOM_FLAG with value "Target.Beta" for the configuration Beta
Then the scheme Framework2 has a build setting CUSTOM_FLAG with value "Release" for the configuration Release
Then I should be able to archive for iOS the scheme App

Scenario: The project is an iOS application with CocoaPods dependencies (ios_app_with_pods)
Given that tuist is available
Expand Down Expand Up @@ -227,6 +228,7 @@ Scenario: The project is an iOS application with extensions (ios_app_with_extens
Then I should be able to build for iOS the scheme App
Then the product 'App.app' with destination 'Debug-iphoneos' contains extension 'StickersPackExtension'
Then the product 'App.app' with destination 'Debug-iphoneos' contains extension 'NotificationServiceExtension'
Then the product 'App.app' with destination 'Debug-iphoneos' contains extension 'NotificationServiceExtension'

Scenario: The project is an iOS application with watch app (ios_app_with_watchapp2)
Given that tuist is available
Expand Down
7 changes: 4 additions & 3 deletions fixtures/ios_app_with_multi_configs/App/Project.swift
Expand Up @@ -11,9 +11,10 @@ let settings = Settings(base: [
], configurations: configurations)

let betaScheme = Scheme(name: "App-Beta",
shared: true,
buildAction: BuildAction(targets: ["App"]),
runAction: RunAction(configurationName: "Beta", executable: "App"))
shared: true,
buildAction: BuildAction(targets: ["App"]),
runAction: RunAction(configurationName: "Beta", executable: "App"),
archiveAction: ArchiveAction(configurationName: "Beta"))

let project = Project(name: "MainApp",
settings: settings,
Expand Down

0 comments on commit b5c360a

Please sign in to comment.