diff --git a/.cicdtemplate/.github/self-hosted-workflows/automatic_pull_request_review.yml b/.cicdtemplate/.github/self-hosted-workflows/automatic_pull_request_review.yml index 1013556c..0999e0f5 100644 --- a/.cicdtemplate/.github/self-hosted-workflows/automatic_pull_request_review.yml +++ b/.cicdtemplate/.github/self-hosted-workflows/automatic_pull_request_review.yml @@ -41,6 +41,12 @@ jobs: - name: Run Arkana run: bundle exec arkana + - name: Modify test plan + run: | + mint run mikeger/XcodeSelectiveTesting@1c0927e5553a9ddb6b3634d6d13497651a0ef476 {PROJECT_NAME}.xcodeproj \ + --test-plan {PROJECT_NAME}.xctestplan \ + --base-branch origin/${{ github.base_ref }} + - name: Build and Test run: bundle exec fastlane buildAndTest env: diff --git a/.cicdtemplate/.github/workflows/automatic_pull_request_review.yml b/.cicdtemplate/.github/workflows/automatic_pull_request_review.yml index e961c911..79c3843c 100644 --- a/.cicdtemplate/.github/workflows/automatic_pull_request_review.yml +++ b/.cicdtemplate/.github/workflows/automatic_pull_request_review.yml @@ -25,6 +25,9 @@ jobs: restore-keys: | ${{ runner.os }}-gems- + - name: Setup Mint + uses: irgaly/setup-mint@8566ee44b3a79d20642d1924db21c8ab0402859f # irgaly/setup-mint@v1 + - name: Setup CI environment uses: ./.github/actions/setup-ci-environment with: @@ -41,6 +44,13 @@ jobs: - name: Run Arkana run: bundle exec arkana + # using mikeger/XcodeSelectiveTesting@0.14.5 + - name: Modify test plan + run: | + mint run mikeger/XcodeSelectiveTesting@1c0927e5553a9ddb6b3634d6d13497651a0ef476 {PROJECT_NAME}.xcodeproj \ + --test-plan {PROJECT_NAME}.xctestplan \ + --base-branch origin/${{ github.base_ref }} + - name: Build and Test run: bundle exec fastlane buildAndTest env: diff --git a/scripts/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpiOSProject.swift b/scripts/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpiOSProject.swift index 4f07e02f..0abbacbe 100644 --- a/scripts/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpiOSProject.swift +++ b/scripts/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpiOSProject.swift @@ -173,6 +173,7 @@ class SetUpIOSProject { try fileManager.rename(file: "template/\(CONSTANT_PROJECT_NAME)Tests", to: "template/\(projectNameNoSpace)Tests") try fileManager.rename(file: "template/\(CONSTANT_PROJECT_NAME)KIFUITests", to: "template/\(projectNameNoSpace)KIFUITests") try fileManager.rename(file: "template/\(CONSTANT_PROJECT_NAME)", to: "template/\(projectNameNoSpace)") + try fileManager.rename(file: "template/\(CONSTANT_PROJECT_NAME).xctestplan", to: "template/\(projectNameNoSpace).xctestplan") } private func createPlaceholderFiles() throws { diff --git a/template/Package.resolved b/template/Package.resolved index 14634e22..4cd075a0 100644 --- a/template/Package.resolved +++ b/template/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "f20f61ffa814731b5dbc7abb5719681df174b8f6a45d9dbd426c5e8a3ecc538f", + "originHash" : "38800aafaa37508835c8747531d4b300ffb86052e604eef3d958cf6cff0cbadc", "pins" : [ { "identity" : "abseil-cpp-binary", diff --git a/template/Project.swift b/template/Project.swift index c6f67336..30c4febf 100644 --- a/template/Project.swift +++ b/template/Project.swift @@ -59,6 +59,9 @@ extension Project { .productionScheme(name: name), .stagingScheme(name: name), .devScheme(name: name) + ], + additionalFiles: [ + "\(name).xctestplan" ] ) } diff --git a/template/Tuist/ProjectDescriptionHelpers/Scheme+Initializing.swift b/template/Tuist/ProjectDescriptionHelpers/Scheme+Initializing.swift index 5e69d6a8..a009ce93 100644 --- a/template/Tuist/ProjectDescriptionHelpers/Scheme+Initializing.swift +++ b/template/Tuist/ProjectDescriptionHelpers/Scheme+Initializing.swift @@ -2,52 +2,48 @@ import ProjectDescription extension Scheme { public static func productionScheme(name: String) -> Scheme { - let debugConfigName = BuildConfiguration.debugProduction.name - let releaseConfigName = BuildConfiguration.releaseProduction.name - - return .scheme( + makeScheme( name: name, - shared: true, - buildAction: .buildAction(targets: ["\(name)"]), - testAction: TestAction.targets(testTargets(for: name), configuration: debugConfigName), - runAction: .runAction(configuration: debugConfigName), - archiveAction: .archiveAction(configuration: releaseConfigName) + debugConfiguration: .debugProduction, + releaseConfiguration: .releaseProduction ) } public static func stagingScheme(name: String) -> Scheme { - let debugConfigName = BuildConfiguration.debugStaging.name - let releaseConfigName = BuildConfiguration.releaseStaging.name - - return .scheme( - name: "\(name) Staging", - shared: true, - buildAction: .buildAction(targets: ["\(name)"]), - testAction: TestAction.targets(testTargets(for: name), configuration: debugConfigName), - runAction: .runAction(configuration: debugConfigName), - archiveAction: .archiveAction(configuration: releaseConfigName) + makeScheme( + name: name, + schemeSuffix: "Staging", + debugConfiguration: .debugStaging, + releaseConfiguration: .releaseStaging ) } - + public static func devScheme(name: String) -> Scheme { - let debugConfigName = BuildConfiguration.debugDev.name - let releaseConfigName = BuildConfiguration.releaseDev.name + makeScheme( + name: name, + schemeSuffix: "Dev", + debugConfiguration: .debugDev, + releaseConfiguration: .releaseDev + ) + } + + private static func makeScheme( + name: String, + schemeSuffix: String? = nil, + debugConfiguration: BuildConfiguration, + releaseConfiguration: BuildConfiguration + ) -> Scheme { + let schemeName = [name, schemeSuffix] + .compactMap { $0 } + .joined(separator: " ") return .scheme( - name: "\(name) Dev", + name: schemeName, shared: true, buildAction: .buildAction(targets: ["\(name)"]), - testAction: TestAction.targets(testTargets(for: name), configuration: debugConfigName), - runAction: .runAction(configuration: debugConfigName), - archiveAction: .archiveAction(configuration: releaseConfigName), + testAction: .testPlans([.path("\(name).xctestplan")], configuration: debugConfiguration.name), + runAction: .runAction(configuration: debugConfiguration.name), + archiveAction: .archiveAction(configuration: releaseConfiguration.name) ) } - - private static func testTargets(for name: String) -> [TestableTarget] { - [ - .testableTarget(target: TargetReference(stringLiteral: Module.domain.name + Constant.testsPath)), - .testableTarget(target: TargetReference(stringLiteral: Module.data.name + Constant.testsPath)), - .testableTarget(target: TargetReference(stringLiteral: "\(name)Tests")) - ] - } } diff --git a/template/fastlane/Fastfile.swift b/template/fastlane/Fastfile.swift index 951b05d5..97cb182b 100644 --- a/template/fastlane/Fastfile.swift +++ b/template/fastlane/Fastfile.swift @@ -168,6 +168,10 @@ class Fastfile: LaneFile { func buildAndTestLane() { desc("Build and Test project") + guard testTargetCount() > 0 else { + echo(message: "🚨 Nothing to test") + return + } Test.buildAndTest( environment: .staging, devices: Constant.devices @@ -176,6 +180,10 @@ class Fastfile: LaneFile { func buildAndTestDevLane() { desc("Build and Test dev project") + guard testTargetCount() > 0 else { + echo(message: "🚨 Nothing to test") + return + } Test.buildAndTest( environment: .dev, devices: Constant.devices @@ -268,4 +276,13 @@ class Fastfile: LaneFile { buildNumber: .userDefined("\(theLatestBuildNumber)") ) } + + private func testTargetCount(in testPlanPath: String = "\(Constant.projectName).xctestplan") -> Int { + guard let data = FileManager.default.contents(atPath: testPlanPath), + let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any], + let testTargets = json?["testTargets"] as? [Any] else { + return 0 + } + return testTargets.count + } } diff --git a/template/fastlane/Helpers/Test.swift b/template/fastlane/Helpers/Test.swift index 53ebd4cb..dc663048 100644 --- a/template/fastlane/Helpers/Test.swift +++ b/template/fastlane/Helpers/Test.swift @@ -25,6 +25,7 @@ enum Test { scheme: .userDefined(environment.scheme), devices: .userDefined(devices), onlyTesting: onlyTesting, + testplan: .userDefined("\(Constant.projectName)"), codeCoverage: .userDefined(true), outputDirectory: Constant.testOutputDirectoryPath, resultBundle: .userDefined(true), diff --git a/template/{PROJECT_NAME}.xctestplan b/template/{PROJECT_NAME}.xctestplan new file mode 100644 index 00000000..c7f15422 --- /dev/null +++ b/template/{PROJECT_NAME}.xctestplan @@ -0,0 +1,45 @@ +{ + "configurations" : [ + { + "id" : "C56A3802-C716-4C08-8B7A-53EFE53D4FE0", + "name" : "Configuration 1", + "options" : { + + } + } + ], + "defaultOptions" : { + + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:TestTemplate.xcodeproj", + "identifier" : "PLACEHOLDER", + "name" : "DomainTests" + } + }, + { + "target" : { + "containerPath" : "container:TestTemplate.xcodeproj", + "identifier" : "PLACEHOLDER", + "name" : "TestTemplateTests" + } + }, + { + "target" : { + "containerPath" : "container:TestTemplate.xcodeproj", + "identifier" : "PLACEHOLDER", + "name" : "DataTests" + } + }, + { + "target" : { + "containerPath" : "container:TestTemplate.xcodeproj", + "identifier" : "PLACEHOLDER", + "name" : "ModelTests" + } + } + ], + "version" : 1 +}