Add new option for disabling validations

This gives us an entry point for disabling specific project.yml
validations that sometimes shouldn't apply. The first example is
missingConfigs, which, if you use your .yml file in multiple projects,
can be too strict if the projects have different top level
configurations.
This commit is contained in:
Keith Smiley 2018-01-04 13:48:41 -08:00
parent 2fcf47cf5c
commit b6ef82b3df
No known key found for this signature in database
GPG Key ID: 33BA60D44C7167F8
6 changed files with 30 additions and 5 deletions

View File

@ -2,6 +2,9 @@
## Master ## Master
#### Added
- add `disabledValidations` to options to disable the `missingConfigs` project validation error [#220](https://github.com/yonaskolb/XcodeGen/pull/220) @keith
## 1.5.0 ## 1.5.0
#### Added #### Added

View File

@ -77,6 +77,8 @@ Note that target names can also be changed by adding a `name` property to a targ
- [ ] **tabWidth**: **Int** - If this is specified, the Xcode project will override the user's setting for indent width in number of spaces. - [ ] **tabWidth**: **Int** - If this is specified, the Xcode project will override the user's setting for indent width in number of spaces.
- [ ] **xcodeVersion**: **String** - The version of Xcode. This defaults to the latest version periodically. You can specify it in the format `0910` or `9.1` - [ ] **xcodeVersion**: **String** - The version of Xcode. This defaults to the latest version periodically. You can specify it in the format `0910` or `9.1`
- [ ] **deploymentTarget**: **[[Platform](#platform): String]** - A project wide deployment target can be specified for each platform otherwise the default SDK version in Xcode will be used. This will be overridden by any custom build settings that set the deployment target eg `IPHONEOS_DEPLOYMENT_TARGET`. Target specific deployment targets can also be set with [Target](#target).deploymentTarget. - [ ] **deploymentTarget**: **[[Platform](#platform): String]** - A project wide deployment target can be specified for each platform otherwise the default SDK version in Xcode will be used. This will be overridden by any custom build settings that set the deployment target eg `IPHONEOS_DEPLOYMENT_TARGET`. Target specific deployment targets can also be set with [Target](#target).deploymentTarget.
- [ ] **disabledValidations**: **[String]** - A list of validations that can be disabled if they're too strict for your use case. By default this is set to an empty array. Currently these are the available options:
- `missingConfigs`: Disable errors for configurations in yaml files that don't exist in the project itself. This can be useful if you include the same yaml file in different projects
```yaml ```yaml
options: options:

View File

@ -24,6 +24,7 @@ public struct ProjectSpec {
public var createIntermediateGroups: Bool public var createIntermediateGroups: Bool
public var bundleIdPrefix: String? public var bundleIdPrefix: String?
public var settingPresets: SettingPresets public var settingPresets: SettingPresets
public var disabledValidations: [ValidationType]
public var developmentLanguage: String? public var developmentLanguage: String?
public var usesTabs: Bool? public var usesTabs: Bool?
public var tabWidth: Int? public var tabWidth: Int?
@ -62,7 +63,8 @@ public struct ProjectSpec {
tabWidth: Int? = nil, tabWidth: Int? = nil,
usesTabs: Bool? = nil, usesTabs: Bool? = nil,
xcodeVersion: String? = nil, xcodeVersion: String? = nil,
deploymentTarget: DeploymentTarget = .init() deploymentTarget: DeploymentTarget = .init(),
disabledValidations: [ValidationType] = []
) { ) {
self.carthageBuildPath = carthageBuildPath self.carthageBuildPath = carthageBuildPath
self.createIntermediateGroups = createIntermediateGroups self.createIntermediateGroups = createIntermediateGroups
@ -74,6 +76,7 @@ public struct ProjectSpec {
self.usesTabs = usesTabs self.usesTabs = usesTabs
self.xcodeVersion = xcodeVersion self.xcodeVersion = xcodeVersion
self.deploymentTarget = deploymentTarget self.deploymentTarget = deploymentTarget
self.disabledValidations = disabledValidations
} }
public static func == (lhs: ProjectSpec.Options, rhs: ProjectSpec.Options) -> Bool { public static func == (lhs: ProjectSpec.Options, rhs: ProjectSpec.Options) -> Bool {
@ -86,7 +89,8 @@ public struct ProjectSpec {
lhs.indentWidth == rhs.indentWidth && lhs.indentWidth == rhs.indentWidth &&
lhs.usesTabs == rhs.usesTabs && lhs.usesTabs == rhs.usesTabs &&
lhs.xcodeVersion == rhs.xcodeVersion && lhs.xcodeVersion == rhs.xcodeVersion &&
lhs.deploymentTarget == rhs.deploymentTarget lhs.deploymentTarget == rhs.deploymentTarget &&
lhs.disabledValidations == rhs.disabledValidations
} }
} }
@ -207,5 +211,6 @@ extension ProjectSpec.Options: JSONObjectConvertible {
indentWidth = jsonDictionary.json(atKeyPath: "indentWidth") indentWidth = jsonDictionary.json(atKeyPath: "indentWidth")
tabWidth = jsonDictionary.json(atKeyPath: "tabWidth") tabWidth = jsonDictionary.json(atKeyPath: "tabWidth")
deploymentTarget = jsonDictionary.json(atKeyPath: "deploymentTarget") ?? DeploymentTarget() deploymentTarget = jsonDictionary.json(atKeyPath: "deploymentTarget") ?? DeploymentTarget()
disabledValidations = jsonDictionary.json(atKeyPath: "disabledValidations") ?? []
} }
} }

View File

@ -3,6 +3,10 @@ import PathKit
extension ProjectSpec { extension ProjectSpec {
public enum ValidationType: String {
case missingConfigs
}
public func validate() throws { public func validate() throws {
var errors: [SpecValidationError.ValidationError] = [] var errors: [SpecValidationError.ValidationError] = []
@ -18,7 +22,9 @@ extension ProjectSpec {
} }
for config in settings.configSettings.keys { for config in settings.configSettings.keys {
if !configs.contains(where: { $0.name.lowercased().contains(config.lowercased()) }) { if !configs.contains(where: { $0.name.lowercased().contains(config.lowercased()) }) {
errors.append(.invalidBuildSettingConfig(config)) if !options.disabledValidations.contains(.missingConfigs) {
errors.append(.invalidBuildSettingConfig(config))
}
} }
} }
return errors return errors
@ -36,7 +42,7 @@ extension ProjectSpec {
if !(basePath + configFile).exists { if !(basePath + configFile).exists {
errors.append(.invalidConfigFile(configFile: configFile, config: config)) errors.append(.invalidConfigFile(configFile: configFile, config: config))
} }
if getConfig(config) == nil { if !options.disabledValidations.contains(.missingConfigs) && getConfig(config) == nil {
errors.append(.invalidConfigFileConfig(config)) errors.append(.invalidConfigFileConfig(config))
} }
} }
@ -56,7 +62,7 @@ extension ProjectSpec {
if !(basePath + configFile).exists { if !(basePath + configFile).exists {
errors.append(.invalidTargetConfigFile(target: target.name, configFile: configFile, config: config)) errors.append(.invalidTargetConfigFile(target: target.name, configFile: configFile, config: config))
} }
if getConfig(config) == nil { if !options.disabledValidations.contains(.missingConfigs) && getConfig(config) == nil {
errors.append(.invalidConfigFileConfig(config)) errors.append(.invalidConfigFileConfig(config))
} }
} }

View File

View File

@ -1,6 +1,7 @@
import Spectre import Spectre
import XcodeGenKit import XcodeGenKit
import xcproj import xcproj
import PathKit
import ProjectSpec import ProjectSpec
func projectSpecTests() { func projectSpecTests() {
@ -101,6 +102,14 @@ func projectSpecTests() {
try expectValidationError(spec, .invalidBuildSettingConfig("invalidSettingGroupConfig")) try expectValidationError(spec, .invalidBuildSettingConfig("invalidSettingGroupConfig"))
} }
$0.it("allows non-existent configurations") {
var spec = baseSpec
spec.options = ProjectSpec.Options(disabledValidations: [.missingConfigs])
let configPath = fixturePath + "test.xcconfig"
spec.configFiles = ["missingConfiguration": configPath.string]
try spec.validate()
}
$0.it("fails with invalid target") { $0.it("fails with invalid target") {
var spec = baseSpec var spec = baseSpec
spec.targets = [Target( spec.targets = [Target(