From 11513b4e5737d36eb4cffb16c0dddd51ea8c6702 Mon Sep 17 00:00:00 2001 From: phongvhd93 Date: Wed, 15 Apr 2026 14:53:22 +0700 Subject: [PATCH 1/4] [#688] Add XCodeSelectiveTesting lib --- template/Package.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/template/Package.swift b/template/Package.swift index 9e248d95..b20d3882 100644 --- a/template/Package.swift +++ b/template/Package.swift @@ -33,5 +33,6 @@ let package = Package( .package(url: "https://github.com/Quick/Quick.git", from: "7.6.2"), .package(url: "https://github.com/Quick/Nimble.git", from: "14.0.0"), .package(url: "https://github.com/AliSoftware/OHHTTPStubs.git", from: "9.1.0"), // Provides OHHTTPStubsSwift product + .package(url: "https://github.com/mikeger/XcodeSelectiveTesting.git", from: "0.14.2") // Selective Testing ] ) From f0683e8c2f175f4f46e7c7d4ca182850b1e8dade Mon Sep 17 00:00:00 2001 From: phongvhd93 Date: Thu, 16 Apr 2026 15:12:10 +0700 Subject: [PATCH 2/4] [#688] Update workflows --- .../workflows/automatic_pull_request_review.yml | 10 ++++++++++ template/Package.resolved | 2 +- template/Package.swift | 1 - template/fastlane/Fastfile.swift | 17 +++++++++++++++++ template/fastlane/Helpers/Test.swift | 1 + 5 files changed, 29 insertions(+), 2 deletions(-) diff --git a/.cicdtemplate/.github/workflows/automatic_pull_request_review.yml b/.cicdtemplate/.github/workflows/automatic_pull_request_review.yml index e961c911..31e2c8e6 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 iOSTemplate.xcodeproj \ + --test-plan iOSTemplate.xctestplan \ + --base-branch origin/${{ github.base_ref }} + - name: Build and Test run: bundle exec fastlane buildAndTest env: 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/Package.swift b/template/Package.swift index b20d3882..9e248d95 100644 --- a/template/Package.swift +++ b/template/Package.swift @@ -33,6 +33,5 @@ let package = Package( .package(url: "https://github.com/Quick/Quick.git", from: "7.6.2"), .package(url: "https://github.com/Quick/Nimble.git", from: "14.0.0"), .package(url: "https://github.com/AliSoftware/OHHTTPStubs.git", from: "9.1.0"), // Provides OHHTTPStubsSwift product - .package(url: "https://github.com/mikeger/XcodeSelectiveTesting.git", from: "0.14.2") // Selective Testing ] ) 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), From ae77fb4b2eae17f8069c6f5ebe9e1373087b60bf Mon Sep 17 00:00:00 2001 From: phongvhd93 Date: Fri, 17 Apr 2026 11:51:58 +0700 Subject: [PATCH 3/4] [#688] Update Tuist Script --- .../automatic_pull_request_review.yml | 6 ++ .../automatic_pull_request_review.yml | 2 +- .../iOSTemplateMaker/SetUpiOSProject.swift | 1 + template/Project.swift | 3 + .../Scheme+Initializing.swift | 64 +++++++++---------- template/{PROJECT_NAME}.xctestplan | 45 +++++++++++++ 6 files changed, 86 insertions(+), 35 deletions(-) create mode 100644 template/{PROJECT_NAME}.xctestplan 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..919f1a6c 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 iOSTemplate.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 31e2c8e6..45c8880c 100644 --- a/.cicdtemplate/.github/workflows/automatic_pull_request_review.yml +++ b/.cicdtemplate/.github/workflows/automatic_pull_request_review.yml @@ -48,7 +48,7 @@ jobs: - name: Modify test plan run: | mint run mikeger/XcodeSelectiveTesting@1c0927e5553a9ddb6b3634d6d13497651a0ef476 iOSTemplate.xcodeproj \ - --test-plan iOSTemplate.xctestplan \ + --test-plan {PROJECT_NAME}.xctestplan \ --base-branch origin/${{ github.base_ref }} - name: Build and Test 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/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/{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 +} From 8128810da18089db3d1041ba22d9e38be6ec7536 Mon Sep 17 00:00:00 2001 From: phongvhd93 Date: Fri, 17 Apr 2026 11:56:12 +0700 Subject: [PATCH 4/4] [#688] Fix the project name in workflow --- .../self-hosted-workflows/automatic_pull_request_review.yml | 2 +- .../.github/workflows/automatic_pull_request_review.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 919f1a6c..0999e0f5 100644 --- a/.cicdtemplate/.github/self-hosted-workflows/automatic_pull_request_review.yml +++ b/.cicdtemplate/.github/self-hosted-workflows/automatic_pull_request_review.yml @@ -43,7 +43,7 @@ jobs: - name: Modify test plan run: | - mint run mikeger/XcodeSelectiveTesting@1c0927e5553a9ddb6b3634d6d13497651a0ef476 iOSTemplate.xcodeproj \ + mint run mikeger/XcodeSelectiveTesting@1c0927e5553a9ddb6b3634d6d13497651a0ef476 {PROJECT_NAME}.xcodeproj \ --test-plan {PROJECT_NAME}.xctestplan \ --base-branch origin/${{ github.base_ref }} diff --git a/.cicdtemplate/.github/workflows/automatic_pull_request_review.yml b/.cicdtemplate/.github/workflows/automatic_pull_request_review.yml index 45c8880c..79c3843c 100644 --- a/.cicdtemplate/.github/workflows/automatic_pull_request_review.yml +++ b/.cicdtemplate/.github/workflows/automatic_pull_request_review.yml @@ -47,7 +47,7 @@ jobs: # using mikeger/XcodeSelectiveTesting@0.14.5 - name: Modify test plan run: | - mint run mikeger/XcodeSelectiveTesting@1c0927e5553a9ddb6b3634d6d13497651a0ef476 iOSTemplate.xcodeproj \ + mint run mikeger/XcodeSelectiveTesting@1c0927e5553a9ddb6b3634d6d13497651a0ef476 {PROJECT_NAME}.xcodeproj \ --test-plan {PROJECT_NAME}.xctestplan \ --base-branch origin/${{ github.base_ref }}