From 50aedc451192cfed020ece05c837da01320cbe14 Mon Sep 17 00:00:00 2001 From: Joseph Colicchio Date: Sun, 14 Feb 2021 16:58:16 -0800 Subject: [PATCH] Feature/Store Kit Configuration (#964) * Preemptively fix compilation for latest XcodeProj * Add StoreKitConfiguration to scheme and generator * Add scheme generator test * Fix and add tests * Support StoreKitConfiguration in TargetScheme * Set default type of `storekit` to `.none` * Upgrade XcodeProj to 7.15.0 * Create struct for StoreKitConfiguration * Update tests * Add storekit configuration to test project * Update changelog * Update project spec * Fix xcodeprojs * Fix projects * Capitalize String * Update CHANGELOG.md Co-authored-by: Gemma Barlow * Refactor StoreKitConfiguration init from json * Change `forWorkspace` to `pathPrefix` and add tests * Replace StoreKitConfiguration struct with string + option * Fix tests * Update project spec * Fixup changelog * Add `See Options` to `storeKitConfiguration` in project spec Co-authored-by: Gemma Barlow --- CHANGELOG.md | 1 + Docs/ProjectSpec.md | 3 + Package.resolved | 8 +-- Sources/ProjectSpec/FileType.swift | 1 + Sources/ProjectSpec/Scheme.swift | 8 +++ Sources/ProjectSpec/SpecOptions.swift | 10 +++- Sources/ProjectSpec/TargetScheme.swift | 8 +++ Sources/XcodeGenKit/SchemeGenerator.swift | 10 +++- .../App_iOS/Configuration.storekit | 29 ++++++++++ .../Project.xcodeproj/project.pbxproj | 2 + .../xcschemes/App_Scheme.xcscheme | 3 + .../xcschemes/App_iOS Production.xcscheme | 3 + .../xcschemes/App_iOS Staging.xcscheme | 3 + .../xcschemes/App_iOS Test.xcscheme | 3 + Tests/Fixtures/TestProject/project.yml | 2 + Tests/PerformanceTests/TestProject.swift | 1 + Tests/ProjectSpecTests/ProjectSpecTests.swift | 4 +- Tests/ProjectSpecTests/SpecLoadingTests.swift | 56 ++++++++++++++++++- .../SchemeGeneratorTests.swift | 29 +++++++--- 19 files changed, 165 insertions(+), 19 deletions(-) create mode 100644 Tests/Fixtures/TestProject/App_iOS/Configuration.storekit diff --git a/CHANGELOG.md b/CHANGELOG.md index 79403fe4..2a5b3eed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ #### Added - Support for building and running on Linux platforms. Tested for compatibility with Swift 5.3+ and Ubuntu 18.04. [#988](https://github.com/yonaskolb/XcodeGen/pull/988) @elliottwilliams - Add `useBaseInternationalization` to Project Spec Options to opt out of Base Internationalization. [#961](https://github.com/yonaskolb/XcodeGen/pull/961) @liamnichols +- Add `storeKitConfiguration` to allow specifying StoreKit Configuration in Scheme and TargetScheme, supporting either xcodeproj or xcworkspace via `schemePathPrefix` option. [#964](https://github.com/yonaskolb/XcodeGen/pull/964) @jcolicchio - More detailed error message with method arguments. [#990](https://github.com/yonaskolb/XcodeGen/pull/990) @bannzai - Added `basedOnDependencyAnalysis` to Project Spec Build Script to be able to choose not to skip the script. [#992](https://github.com/yonaskolb/XcodeGen/pull/992) @myihsan - Add `BuildRule.runOncePerArchitecture` to allow running build rules once per architecture. [#950](https://github.com/yonaskolb/XcodeGen/pull/950) @sascha diff --git a/Docs/ProjectSpec.md b/Docs/ProjectSpec.md index 4cf4f2a1..58ade4d9 100644 --- a/Docs/ProjectSpec.md +++ b/Docs/ProjectSpec.md @@ -128,6 +128,7 @@ Note that target names can also be changed by adding a `name` property to a targ - [ ] **preGenCommand**: **String** - A bash command to run before the project has been generated. If the project isn't generated due to no changes when using the cache then this won't run. This is useful for running things like generating resources files before the project is regenerated. - [ ] **postGenCommand**: **String** - A bash command to run after the project has been generated. If the project isn't generated due to no changes when using the cache then this won't run. This is useful for running things like `pod install` only if the project is actually regenerated. - [ ] **useBaseInternationalization**: **Bool** If this is `false` and your project does not include resources located in a **Base.lproj** directory then `Base` will not be included in the projects 'known regions'. The default value is `true`. +- [ ] **schemePathPrefix**: **String** - A path prefix for relative paths in schemes, such as StoreKitConfiguration. The default is `"../../"`, which is suitable for non-workspace projects. For use in workspaces, use `"../"`. ```yaml options: @@ -639,6 +640,7 @@ This is a convenience used to automatically generate schemes for a target based - [ ] **environmentVariables**: **[[Environment Variable](#environment-variable)]** or **[String:String]** - environment variables for Run, Test and Profile scheme actions. When passing a dictionary, every key-value entry maps to a corresponding variable that is enabled. - [ ] **preActions**: **[[Execution Action](#execution-action)]** - Scripts that are run *before* the build action - [ ] **postActions**: **[[Execution Action](#execution-action)]** - Scripts that are run *after* the build action +- [ ] **storeKitConfiguration**: **String** - specify storekit configuration to use during run. See [Options](#options). For example, the spec below would create 3 schemes called: @@ -775,6 +777,7 @@ The different actions share some properties: - [ ] **simulateLocation**: **[Simulate Location](#simulate-location)** - `run` action can define a simulated location - [ ] **askForAppToLaunch**: **Bool** - `run` action can define the executable set to ask to launch. This defaults to false. - [ ] **launchAutomaticallySubstyle**: **String** - `run` action can define the launch automatically substyle ('2' for extensions). +- [ ] **storeKitConfiguration**: **String** - `run` action can specify a storekit configuration. See [Options](#options). ### Execution Action diff --git a/Package.resolved b/Package.resolved index e42136a4..26a8147f 100644 --- a/Package.resolved +++ b/Package.resolved @@ -15,8 +15,8 @@ "repositoryURL": "https://github.com/SwiftDocOrg/GraphViz.git", "state": { "branch": null, - "revision": "c4746cb3ff6f5e7c5d5540c40b98555521c3ee43", - "version": "0.1.3" + "revision": "70bebcf4597b9ce33e19816d6bbd4ba9b7bdf038", + "version": "0.2.0" } }, { @@ -87,8 +87,8 @@ "repositoryURL": "https://github.com/jpsim/Yams.git", "state": { "branch": null, - "revision": "88caa2e6fffdbef2e91c2022d038576062042907", - "version": "4.0.0" + "revision": "138cf1b701cf825233b92ceac919152d5aba8a3f", + "version": "4.0.1" } } ] diff --git a/Sources/ProjectSpec/FileType.swift b/Sources/ProjectSpec/FileType.swift index bc535a1d..e2620002 100644 --- a/Sources/ProjectSpec/FileType.swift +++ b/Sources/ProjectSpec/FileType.swift @@ -110,5 +110,6 @@ extension FileType { "xcfilelist": FileType(buildPhase: BuildPhaseSpec.none), "apns": FileType(buildPhase: BuildPhaseSpec.none), "pch": FileType(buildPhase: BuildPhaseSpec.none), + "storekit": FileType(buildPhase: BuildPhaseSpec.none), ] } diff --git a/Sources/ProjectSpec/Scheme.swift b/Sources/ProjectSpec/Scheme.swift index d872129d..d6481a3a 100644 --- a/Sources/ProjectSpec/Scheme.swift +++ b/Sources/ProjectSpec/Scheme.swift @@ -1,5 +1,6 @@ import Foundation import JSONUtilities +import PathKit import XcodeProj public typealias BuildType = XCScheme.BuildAction.Entry.BuildFor @@ -113,6 +114,7 @@ public struct Scheme: Equatable { public var debugEnabled: Bool public var simulateLocation: SimulateLocation? public var executable: String? + public var storeKitConfiguration: String? public var customLLDBInit: String? public init( @@ -130,6 +132,7 @@ public struct Scheme: Equatable { launchAutomaticallySubstyle: String? = nil, debugEnabled: Bool = debugEnabledDefault, simulateLocation: SimulateLocation? = nil, + storeKitConfiguration: String? = nil, customLLDBInit: String? = nil ) { self.config = config @@ -145,6 +148,7 @@ public struct Scheme: Equatable { self.launchAutomaticallySubstyle = launchAutomaticallySubstyle self.debugEnabled = debugEnabled self.simulateLocation = simulateLocation + self.storeKitConfiguration = storeKitConfiguration self.customLLDBInit = customLLDBInit } } @@ -368,6 +372,7 @@ extension Scheme.Run: JSONObjectConvertible { region = jsonDictionary.json(atKeyPath: "region") debugEnabled = jsonDictionary.json(atKeyPath: "debugEnabled") ?? Scheme.Run.debugEnabledDefault simulateLocation = jsonDictionary.json(atKeyPath: "simulateLocation") + storeKitConfiguration = jsonDictionary.json(atKeyPath: "storeKitConfiguration") executable = jsonDictionary.json(atKeyPath: "executable") // launchAutomaticallySubstyle is defined as a String in XcodeProj but its value is often @@ -415,6 +420,9 @@ extension Scheme.Run: JSONEncodable { if let simulateLocation = simulateLocation { dict["simulateLocation"] = simulateLocation.toJSONValue() } + if let storeKitConfiguration = storeKitConfiguration { + dict["storeKitConfiguration"] = storeKitConfiguration + } if let customLLDBInit = customLLDBInit { dict["customLLDBInit"] = customLLDBInit } diff --git a/Sources/ProjectSpec/SpecOptions.swift b/Sources/ProjectSpec/SpecOptions.swift index f44fb2aa..c1f0645d 100644 --- a/Sources/ProjectSpec/SpecOptions.swift +++ b/Sources/ProjectSpec/SpecOptions.swift @@ -10,6 +10,7 @@ public struct SpecOptions: Equatable { public static let generateEmptyDirectoriesDefault = false public static let findCarthageFrameworksDefault = false public static let useBaseInternationalizationDefault = true + public static let schemePathPrefixDefault = "../../" public var minimumXcodeGenVersion: Version? public var carthageBuildPath: String? @@ -35,6 +36,7 @@ public struct SpecOptions: Equatable { public var preGenCommand: String? public var postGenCommand: String? public var useBaseInternationalization: Bool + public var schemePathPrefix: String public enum ValidationType: String { case missingConfigs @@ -96,7 +98,8 @@ public struct SpecOptions: Equatable { localPackagesGroup: String? = nil, preGenCommand: String? = nil, postGenCommand: String? = nil, - useBaseInternationalization: Bool = useBaseInternationalizationDefault + useBaseInternationalization: Bool = useBaseInternationalizationDefault, + schemePathPrefix: String = schemePathPrefixDefault ) { self.minimumXcodeGenVersion = minimumXcodeGenVersion self.carthageBuildPath = carthageBuildPath @@ -122,6 +125,7 @@ public struct SpecOptions: Equatable { self.preGenCommand = preGenCommand self.postGenCommand = postGenCommand self.useBaseInternationalization = useBaseInternationalization + self.schemePathPrefix = schemePathPrefix } } @@ -154,6 +158,7 @@ extension SpecOptions: JSONObjectConvertible { preGenCommand = jsonDictionary.json(atKeyPath: "preGenCommand") postGenCommand = jsonDictionary.json(atKeyPath: "postGenCommand") useBaseInternationalization = jsonDictionary.json(atKeyPath: "useBaseInternationalization") ?? SpecOptions.useBaseInternationalizationDefault + schemePathPrefix = jsonDictionary.json(atKeyPath: "schemePathPrefix") ?? SpecOptions.schemePathPrefixDefault if jsonDictionary["fileTypes"] != nil { fileTypes = try jsonDictionary.json(atKeyPath: "fileTypes") } else { @@ -200,6 +205,9 @@ extension SpecOptions: JSONEncodable { if useBaseInternationalization != SpecOptions.useBaseInternationalizationDefault { dict["useBaseInternationalization"] = useBaseInternationalization } + if schemePathPrefix != SpecOptions.schemePathPrefixDefault { + dict["schemePathPrefix"] = schemePathPrefix + } return dict } diff --git a/Sources/ProjectSpec/TargetScheme.swift b/Sources/ProjectSpec/TargetScheme.swift index ce54f617..1beedb6a 100644 --- a/Sources/ProjectSpec/TargetScheme.swift +++ b/Sources/ProjectSpec/TargetScheme.swift @@ -11,6 +11,7 @@ public struct TargetScheme: Equatable { public var testTargets: [Scheme.Test.TestTarget] public var configVariants: [String] public var gatherCoverageData: Bool + public var storeKitConfiguration: String? public var language: String? public var region: String? public var disableMainThreadChecker: Bool @@ -25,6 +26,7 @@ public struct TargetScheme: Equatable { testTargets: [Scheme.Test.TestTarget] = [], configVariants: [String] = [], gatherCoverageData: Bool = gatherCoverageDataDefault, + storeKitConfiguration: String? = nil, language: String? = nil, region: String? = nil, disableMainThreadChecker: Bool = disableMainThreadCheckerDefault, @@ -38,6 +40,7 @@ public struct TargetScheme: Equatable { self.testTargets = testTargets self.configVariants = configVariants self.gatherCoverageData = gatherCoverageData + self.storeKitConfiguration = storeKitConfiguration self.language = language self.region = region self.disableMainThreadChecker = disableMainThreadChecker @@ -68,6 +71,7 @@ extension TargetScheme: JSONObjectConvertible { } configVariants = jsonDictionary.json(atKeyPath: "configVariants") ?? [] gatherCoverageData = jsonDictionary.json(atKeyPath: "gatherCoverageData") ?? TargetScheme.gatherCoverageDataDefault + storeKitConfiguration = jsonDictionary.json(atKeyPath: "storeKitConfiguration") language = jsonDictionary.json(atKeyPath: "language") region = jsonDictionary.json(atKeyPath: "region") disableMainThreadChecker = jsonDictionary.json(atKeyPath: "disableMainThreadChecker") ?? TargetScheme.disableMainThreadCheckerDefault @@ -95,6 +99,10 @@ extension TargetScheme: JSONEncodable { dict["gatherCoverageData"] = gatherCoverageData } + if let storeKitConfiguration = storeKitConfiguration { + dict["storeKitConfiguration"] = storeKitConfiguration + } + if disableMainThreadChecker != TargetScheme.disableMainThreadCheckerDefault { dict["disableMainThreadChecker"] = disableMainThreadChecker } diff --git a/Sources/XcodeGenKit/SchemeGenerator.swift b/Sources/XcodeGenKit/SchemeGenerator.swift index 161befbc..2729f88c 100644 --- a/Sources/XcodeGenKit/SchemeGenerator.swift +++ b/Sources/XcodeGenKit/SchemeGenerator.swift @@ -235,6 +235,12 @@ public class SchemeGenerator { locationScenarioReference = XCScheme.LocationScenarioReference(identifier: identifier, referenceType: referenceType.rawValue) } + var storeKitConfigurationFileReference: XCScheme.StoreKitConfigurationFileReference? + if let storeKitConfiguration = scheme.run?.storeKitConfiguration { + let storeKitConfigurationPath = Path(components: [project.options.schemePathPrefix, storeKitConfiguration]).simplifyingParentDirectoryReferences() + storeKitConfigurationFileReference = XCScheme.StoreKitConfigurationFileReference(identifier: storeKitConfigurationPath.string) + } + let launchAction = XCScheme.LaunchAction( runnable: shouldExecuteOnLaunch ? runnables.launch : nil, buildConfiguration: scheme.run?.config ?? defaultDebugConfig.name, @@ -253,6 +259,7 @@ public class SchemeGenerator { language: scheme.run?.language, region: scheme.run?.region, launchAutomaticallySubstyle: scheme.run?.launchAutomaticallySubstyle ?? launchAutomaticallySubstyle(for: schemeTarget), + storeKitConfigurationFileReference: storeKitConfigurationFileReference, customLLDBInitFile: scheme.run?.customLLDBInit ) @@ -362,7 +369,8 @@ extension Scheme { disableMainThreadChecker: targetScheme.disableMainThreadChecker, stopOnEveryMainThreadCheckerIssue: targetScheme.stopOnEveryMainThreadCheckerIssue, language: targetScheme.language, - region: targetScheme.region + region: targetScheme.region, + storeKitConfiguration: targetScheme.storeKitConfiguration ), test: .init( config: debugConfig, diff --git a/Tests/Fixtures/TestProject/App_iOS/Configuration.storekit b/Tests/Fixtures/TestProject/App_iOS/Configuration.storekit new file mode 100644 index 00000000..aa066b3f --- /dev/null +++ b/Tests/Fixtures/TestProject/App_iOS/Configuration.storekit @@ -0,0 +1,29 @@ +{ + "products" : [ + { + "displayPrice" : "0.00", + "familyShareable" : false, + "internalID" : "6D7919A3", + "localizations" : [ + { + "description" : "", + "displayName" : "", + "locale" : "en_US" + } + ], + "productID" : "com.xcodegen.0", + "referenceName" : null, + "type" : "Consumable" + } + ], + "settings" : { + + }, + "subscriptionGroups" : [ + + ], + "version" : { + "major" : 1, + "minor" : 0 + } +} diff --git a/Tests/Fixtures/TestProject/Project.xcodeproj/project.pbxproj b/Tests/Fixtures/TestProject/Project.xcodeproj/project.pbxproj index 8ba9c060..964356a9 100644 --- a/Tests/Fixtures/TestProject/Project.xcodeproj/project.pbxproj +++ b/Tests/Fixtures/TestProject/Project.xcodeproj/project.pbxproj @@ -656,6 +656,7 @@ 8D88C6BF7355702B74396791 /* TestProjectUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestProjectUITests.swift; sourceTree = ""; }; 93C033648A37D95027845BD3 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; 9A87A926D563773658FB87FE /* iMessageApp.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = iMessageApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 9D4AB3FCF725428EFB56F542 /* Configuration.storekit */ = {isa = PBXFileReference; path = Configuration.storekit; sourceTree = ""; }; 9F27382DD66E26C059E26EFE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; A0DC40025AB59B688E758829 /* Framework2.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Framework2.framework; sourceTree = BUILT_PRODUCTS_DIR; }; A220DE4EB3CB2E598D034D9D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; @@ -854,6 +855,7 @@ F0D48A913C087D049C8EDDD7 /* App.entitlements */, 7F1A2F579A6F79C62DDA0571 /* AppDelegate.swift */, 3797E591F302ECC0AA2FC607 /* Assets.xcassets */, + 9D4AB3FCF725428EFB56F542 /* Configuration.storekit */, C9DDE1B06BCC1CDE0ECF1589 /* Info.plist */, AAA49985DFFE797EE8416887 /* inputList.xcfilelist */, CE1F06D99242F4223D081F0D /* LaunchScreen.storyboard */, diff --git a/Tests/Fixtures/TestProject/Project.xcodeproj/xcshareddata/xcschemes/App_Scheme.xcscheme b/Tests/Fixtures/TestProject/Project.xcodeproj/xcshareddata/xcschemes/App_Scheme.xcscheme index df89ce7c..d9809d0e 100644 --- a/Tests/Fixtures/TestProject/Project.xcodeproj/xcshareddata/xcschemes/App_Scheme.xcscheme +++ b/Tests/Fixtures/TestProject/Project.xcodeproj/xcshareddata/xcschemes/App_Scheme.xcscheme @@ -93,6 +93,9 @@ + + + + + + + +