Scheme config variants wrong assignment for similar config names (#976)

* Failing test for #975

* fixes #975

* chore: refactor to properly select a config from a collection with specific variant and config type
chore: updated changelog

* fix: lowercase compare on config variant names

* fix CI

* fix missing scheme for CI

* fix schemes for CI

* Update CHANGELOG.md

Co-authored-by: Yonas Kolb <yonaskolb@users.noreply.github.com>

* Update Sources/ProjectSpec/Config.swift

Co-authored-by: Yonas Kolb <yonaskolb@users.noreply.github.com>

* - fix compilation issue
- duplicated test for config variant name (uppercase/lowercase)

Co-authored-by: Yonas Kolb <yonaskolb@users.noreply.github.com>
This commit is contained in:
Stefano Mondino 2021-05-01 07:50:39 +02:00 committed by GitHub
parent 3a193eacf9
commit dfe7f28bcb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 66 additions and 26 deletions

View File

@ -58,6 +58,9 @@
[Commits](https://github.com/yonaskolb/XcodeGen/compare/2.18.0...2.19.0)
#### Fixed
- Lookup scheme config variants by whole words, fixing incorrect assignment in names that contain subtrings of each other (eg PreProd and Prod) [#976](https://github.com/yonaskolb/XcodeGen/pull/976) @stefanomondino
## 2.18.0
#### Added

View File

@ -10,10 +10,34 @@ public struct Config: Hashable {
self.type = type
}
public static var defaultConfigs: [Config] = [Config(name: "Debug", type: .debug), Config(name: "Release", type: .release)]
public static var defaultConfigs: [Config] = [Config(name: ConfigType.debug.name, type: .debug), Config(name: ConfigType.release.name, type: .release)]
}
public enum ConfigType: String {
case debug
case release
public var name: String {
rawValue.prefix(1).uppercased() + rawValue.dropFirst()
}
}
public extension Collection where Element == Config {
func first(including configVariant: String, for type: ConfigType) -> Config? {
first(where: { $0.type == type && $0.name.variantName(for: $0.type) == configVariant })
}
}
private extension String {
func variantName(for configType: ConfigType?) -> String {
self.components(separatedBy: " ")
.compactMap { component in
if component.lowercased() == (configType?.name.lowercased() ?? "") {
return nil
}
return component
}
.joined(separator: " ")
.trimmingCharacters(in: CharacterSet.whitespaces)
}
}

View File

@ -90,16 +90,16 @@ extension Project {
}
if let scheme = target.scheme {
for configVariant in scheme.configVariants {
if !configs.contains(where: { $0.name.contains(configVariant) && $0.type == .debug }) {
if configs.first(including: configVariant, for: .debug) == nil {
errors.append(.invalidTargetSchemeConfigVariant(
target: target.name,
configVariant: configVariant,
configType: .debug
))
}
if !configs.contains(where: { $0.name.contains(configVariant) && $0.type == .release }) {
if configs.first(including: configVariant, for: .release) == nil {
errors.append(.invalidTargetSchemeConfigVariant(
target: target.name,
configVariant: configVariant,

View File

@ -70,12 +70,13 @@ public class SchemeGenerator {
for configVariant in targetScheme.configVariants {
let schemeName = "\(target.name) \(configVariant)"
let debugConfig = project.configs
.first { $0.type == .debug && $0.name.contains(configVariant) }!
.first(including: configVariant, for: .debug)!
let releaseConfig = project.configs
.first { $0.type == .release && $0.name.contains(configVariant) }!
.first(including: configVariant, for: .release)!
let scheme = Scheme(
name: schemeName,
target: target,

View File

@ -116,8 +116,8 @@ extension Project {
Config(name: "Release Test", type: .release),
Config(name: "Debug Staging", type: .debug),
Config(name: "Release Staging", type: .release),
Config(name: "Debug Production", type: .debug),
Config(name: "Release Production", type: .release),
Config(name: "Debug Prod", type: .debug),
Config(name: "Release Prod", type: .release),
],
targets: targets,
aggregateTargets: [],

View File

@ -193,32 +193,44 @@ class SchemeGeneratorTests: XCTestCase {
}
$0.it("generates target schemes from config variant") {
let configVariants = ["Test", "Production"]
let configVariants = ["Test", "PreProd", "Prod"]
var target = app
target.scheme = TargetScheme(configVariants: configVariants)
// Including here a double test for custom upper/lowercase in config types
let configs: [Config] = [
Config(name: "Test Debug", type: .debug),
Config(name: "Production Debug", type: .debug),
Config(name: "PreProd debug", type: .debug),
Config(name: "Prod Debug", type: .debug),
Config(name: "Test Release", type: .release),
Config(name: "Production Release", type: .release),
Config(name: "PreProd release", type: .release),
Config(name: "Prod Release", type: .release),
]
let project = Project(name: "test", configs: configs, targets: [target, framework])
let xcodeProject = try project.generateXcodeProject()
try expect(xcodeProject.sharedData?.schemes.count) == 2
let xcscheme = try unwrap(xcodeProject.sharedData?.schemes
.first(where: { $0.name == "\(target.name) Test" }))
let buildActionEntry = try unwrap(xcscheme.buildAction?.buildActionEntries.first)
try expect(buildActionEntry.buildableReference.blueprintIdentifier.count > 0) == true
try expect(xcscheme.launchAction?.buildConfiguration) == "Test Debug"
try expect(xcscheme.testAction?.buildConfiguration) == "Test Debug"
try expect(xcscheme.profileAction?.buildConfiguration) == "Test Release"
try expect(xcscheme.analyzeAction?.buildConfiguration) == "Test Debug"
try expect(xcscheme.archiveAction?.buildConfiguration) == "Test Release"
try expect(xcodeProject.sharedData?.schemes.count) == 3
try configVariants.forEach { variantName in
let xcscheme = try unwrap(xcodeProject.sharedData?.schemes
.first(where: { $0.name == "\(target.name) \(variantName)" }))
let buildActionEntry = try unwrap(xcscheme.buildAction?.buildActionEntries.first)
try expect(buildActionEntry.buildableReference.blueprintIdentifier.count > 0) == true
if variantName == "PreProd" {
try expect(xcscheme.launchAction?.buildConfiguration) == "\(variantName) debug"
try expect(xcscheme.testAction?.buildConfiguration) == "\(variantName) debug"
try expect(xcscheme.profileAction?.buildConfiguration) == "\(variantName) release"
try expect(xcscheme.analyzeAction?.buildConfiguration) == "\(variantName) debug"
try expect(xcscheme.archiveAction?.buildConfiguration) == "\(variantName) release"
} else {
try expect(xcscheme.launchAction?.buildConfiguration) == "\(variantName) Debug"
try expect(xcscheme.testAction?.buildConfiguration) == "\(variantName) Debug"
try expect(xcscheme.profileAction?.buildConfiguration) == "\(variantName) Release"
try expect(xcscheme.analyzeAction?.buildConfiguration) == "\(variantName) Debug"
try expect(xcscheme.archiveAction?.buildConfiguration) == "\(variantName) Release"
}
}
}
$0.it("generates environment variables for target schemes") {