From 4cf4cbbddd02573e129ad92551b5592911730246 Mon Sep 17 00:00:00 2001 From: Bliss Pisit Wetcha Date: Tue, 22 Aug 2023 17:56:11 +0700 Subject: [PATCH 01/22] [#495] Add Swift package for Make --- .../workflows/test_swiftui_install_script.yml | 2 +- .../workflows/test_uikit_install_script.yml | 2 +- .../test_upload_build_to_firebase.yml | 4 +- .../test_upload_build_to_test_flight.yml | 4 +- .gitignore | 3 + Scripts/Swift/SetUpTestFirebase.swift | 16 ---- Scripts/Swift/SetUpTestTestFlight.swift | 16 ---- .../Swift/iOSTemplateMaker/Package.resolved | 14 ++++ Scripts/Swift/iOSTemplateMaker/Package.swift | 28 +++++++ Scripts/Swift/iOSTemplateMaker/README.md | 3 + .../Extensions/FileManager+Utils.swift | 0 .../Extensions/Optional+Utils.swift | 18 +++++ .../Extensions/String+Utils.swift | 3 + .../iOSTemplateMaker}/Helpers/SafeShell.swift | 0 .../iOSTemplateMaker}/SetUpCICDService.swift | 4 +- .../SetUpDeliveryConstants.swift | 0 .../iOSTemplateMaker}/SetUpInterface.swift | 2 + .../iOSTemplateMaker/SetUpTestFirebase.swift | 23 ++++++ .../SetUpTestTestFlight.swift | 23 ++++++ .../iOSTemplateMaker}/SetUpiOSProject.swift | 42 +++++----- .../iOSTemplateMaker/iOSTemplateMaker.swift | 78 +++++++++++++++++++ .../iOSTemplateMakerTests.swift | 11 +++ make.sh | 74 ------------------ 23 files changed, 236 insertions(+), 134 deletions(-) delete mode 100644 Scripts/Swift/SetUpTestFirebase.swift delete mode 100644 Scripts/Swift/SetUpTestTestFlight.swift create mode 100644 Scripts/Swift/iOSTemplateMaker/Package.resolved create mode 100644 Scripts/Swift/iOSTemplateMaker/Package.swift create mode 100644 Scripts/Swift/iOSTemplateMaker/README.md rename Scripts/Swift/{ => iOSTemplateMaker/Sources/iOSTemplateMaker}/Extensions/FileManager+Utils.swift (100%) create mode 100644 Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/Extensions/Optional+Utils.swift rename Scripts/Swift/{ => iOSTemplateMaker/Sources/iOSTemplateMaker}/Extensions/String+Utils.swift (83%) rename Scripts/Swift/{ => iOSTemplateMaker/Sources/iOSTemplateMaker}/Helpers/SafeShell.swift (100%) rename Scripts/Swift/{ => iOSTemplateMaker/Sources/iOSTemplateMaker}/SetUpCICDService.swift (95%) rename Scripts/Swift/{ => iOSTemplateMaker/Sources/iOSTemplateMaker}/SetUpDeliveryConstants.swift (100%) rename Scripts/Swift/{ => iOSTemplateMaker/Sources/iOSTemplateMaker}/SetUpInterface.swift (98%) create mode 100644 Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpTestFirebase.swift create mode 100644 Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpTestTestFlight.swift rename Scripts/Swift/{ => iOSTemplateMaker/Sources/iOSTemplateMaker}/SetUpiOSProject.swift (88%) create mode 100644 Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/iOSTemplateMaker.swift create mode 100644 Scripts/Swift/iOSTemplateMaker/Tests/iOSTemplateMakerTests/iOSTemplateMakerTests.swift delete mode 100644 make.sh diff --git a/.github/workflows/test_swiftui_install_script.yml b/.github/workflows/test_swiftui_install_script.yml index 7002abae..bded91e1 100644 --- a/.github/workflows/test_swiftui_install_script.yml +++ b/.github/workflows/test_swiftui_install_script.yml @@ -19,7 +19,7 @@ jobs: run: bundle install - name: Start Install Script for SwiftUI Template App - run: sh make.sh --bundle-id co.nimblehq.template --bundle-id-staging co.nimblehq.template.staging --project-name TemplateApp --interface SwiftUI + run: swift run --package-path Scripts/Swift/iOSTemplateMaker iOSTemplateMaker make --bundle-id-production co.nimblehq.ios.templates --bundle-id-staging co.nimblehq.ios.templates.staging --project-name TemplateApp --interface SwiftUI - name: Build and Test run: bundle exec fastlane buildAndTest diff --git a/.github/workflows/test_uikit_install_script.yml b/.github/workflows/test_uikit_install_script.yml index d5cc86e9..3f4d0a60 100644 --- a/.github/workflows/test_uikit_install_script.yml +++ b/.github/workflows/test_uikit_install_script.yml @@ -19,7 +19,7 @@ jobs: run: bundle install - name: Start Install Script for UIKit Template App - run: sh make.sh --bundle-id co.nimblehq.template --bundle-id-staging co.nimblehq.template.staging --project-name TemplateApp --interface UIKit + run: swift run --package-path Scripts/Swift/iOSTemplateMaker iOSTemplateMaker make --bundle-id-production co.nimblehq.ios.templates --bundle-id-staging co.nimblehq.ios.templates.staging --project-name TemplateApp --interface UIKit - name: Build and Test run: bundle exec fastlane buildAndTest diff --git a/.github/workflows/test_upload_build_to_firebase.yml b/.github/workflows/test_upload_build_to_firebase.yml index 5f8d2655..8b0becfc 100644 --- a/.github/workflows/test_upload_build_to_firebase.yml +++ b/.github/workflows/test_upload_build_to_firebase.yml @@ -47,10 +47,10 @@ jobs: ${{ runner.os }}-pods- - name: Start Install Script for Template App - run: sh make.sh --bundle-id co.nimblehq.ios.templates --bundle-id-staging co.nimblehq.ios.templates.staging --project-name TemplateApp --interface UIKit + run: swift run --package-path Scripts/Swift/iOSTemplateMaker iOSTemplateMaker make --bundle-id-production co.nimblehq.ios.templates --bundle-id-staging co.nimblehq.ios.templates.staging --project-name TemplateApp --interface UIKit - name: Start Setup Script for Template App Firebase Upload - run: cat Scripts/Swift/SetUpTestFirebase.swift Scripts/Swift/Extensions/FileManager+Utils.swift | swift - + run: swift run --package-path Scripts/Swift/iOSTemplateMaker iOSTemplateMaker make-test-firebase env: MATCH_REPO: ${{ secrets.MATCH_REPO }} STAGING_FIREBASE_APP_ID: ${{ secrets.STAGING_FIREBASE_APP_ID }} diff --git a/.github/workflows/test_upload_build_to_test_flight.yml b/.github/workflows/test_upload_build_to_test_flight.yml index 28baf490..9d68acba 100644 --- a/.github/workflows/test_upload_build_to_test_flight.yml +++ b/.github/workflows/test_upload_build_to_test_flight.yml @@ -44,10 +44,10 @@ jobs: ${{ runner.os }}-pods- - name: Start Install Script for Template App - run: sh make.sh --bundle-id co.nimblehq.ios.templates --bundle-id-staging co.nimblehq.ios.templates.staging --project-name TemplateApp --interface UIKit + run: swift run --package-path Scripts/Swift/iOSTemplateMaker iOSTemplateMaker make --bundle-id-production co.nimblehq.ios.templates --bundle-id-staging co.nimblehq.ios.templates.staging --project-name TemplateApp --interface UIKit - name: Start Setup Script for Template App TestFlight Upload - run: cat Scripts/Swift/SetUpTestTestFlight.swift Scripts/Swift/Extensions/FileManager+Utils.swift | swift - + run: swift run --package-path Scripts/Swift/iOSTemplateMaker iOSTemplateMaker make-test-test-flight env: MATCH_REPO: ${{ secrets.MATCH_REPO }} API_KEY_ID: ${{ secrets.API_KEY_ID }} diff --git a/.gitignore b/.gitignore index d64a8594..398c9216 100644 --- a/.gitignore +++ b/.gitignore @@ -84,3 +84,6 @@ dependencies/ # Environment .env +Scripts/Swift/iOSTemplateMaker/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +Scripts/Swift/iOSTemplateMaker/.build +Scripts/Swift/iOSTemplateMaker/.swiftpm diff --git a/Scripts/Swift/SetUpTestFirebase.swift b/Scripts/Swift/SetUpTestFirebase.swift deleted file mode 100644 index f7b36fbb..00000000 --- a/Scripts/Swift/SetUpTestFirebase.swift +++ /dev/null @@ -1,16 +0,0 @@ -let teamIdPlaceholder = "<#teamId#>" -let stagingFirebaseAppIdPlaceholder = "<#stagingFirebaseAppId#>" -let firebaseTesterGroupsPlaceholder = "<#group1#>, <#group2#>" -let matchRepoPlaceholder = "git@github.com:{organization}/{repo}.git" - -let envMatchRepo = ProcessInfo.processInfo.environment["MATCH_REPO"] ?? "" -let envStagingFirebaseAppId = ProcessInfo.processInfo.environment["STAGING_FIREBASE_APP_ID"] ?? "" -let envTeamId = ProcessInfo.processInfo.environment["TEAM_ID"] ?? "" -let firebaseTesterGroup = "nimble" - -let fileManager = FileManager.default - -fileManager.replaceAllOccurrences(of: teamIdPlaceholder, to: envTeamId) -fileManager.replaceAllOccurrences(of: stagingFirebaseAppIdPlaceholder, to: envStagingFirebaseAppId) -fileManager.replaceAllOccurrences(of: firebaseTesterGroupsPlaceholder, to: firebaseTesterGroup) -fileManager.replaceAllOccurrences(of: matchRepoPlaceholder, to: envMatchRepo) diff --git a/Scripts/Swift/SetUpTestTestFlight.swift b/Scripts/Swift/SetUpTestTestFlight.swift deleted file mode 100644 index 950c4952..00000000 --- a/Scripts/Swift/SetUpTestTestFlight.swift +++ /dev/null @@ -1,16 +0,0 @@ -let teamIdPlaceholder = "<#teamId#>" -let apiKeyIdPlaceholder = "<#API_KEY_ID#>" -let issuerIdPlaceholder = "<#ISSUER_ID#>" -let matchRepoPlaceholder = "git@github.com:{organization}/{repo}.git" - -let envMatchRepo = ProcessInfo.processInfo.environment["MATCH_REPO"] ?? "" -let envApiKey = ProcessInfo.processInfo.environment["API_KEY_ID"] ?? "" -let envIssuerId = ProcessInfo.processInfo.environment["ISSUER_ID"] ?? "" -let envTeamId = ProcessInfo.processInfo.environment["TEAM_ID"] ?? "" - -let fileManager = FileManager.default - -fileManager.replaceAllOccurrences(of: teamIdPlaceholder, to: envTeamId) -fileManager.replaceAllOccurrences(of: apiKeyIdPlaceholder, to: envApiKey) -fileManager.replaceAllOccurrences(of: issuerIdPlaceholder, to: envIssuerId) -fileManager.replaceAllOccurrences(of: matchRepoPlaceholder, to: envMatchRepo) diff --git a/Scripts/Swift/iOSTemplateMaker/Package.resolved b/Scripts/Swift/iOSTemplateMaker/Package.resolved new file mode 100644 index 00000000..d429d392 --- /dev/null +++ b/Scripts/Swift/iOSTemplateMaker/Package.resolved @@ -0,0 +1,14 @@ +{ + "pins" : [ + { + "identity" : "swift-argument-parser", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-argument-parser.git", + "state" : { + "revision" : "8f4d2753f0e4778c76d5f05ad16c74f707390531", + "version" : "1.2.3" + } + } + ], + "version" : 2 +} diff --git a/Scripts/Swift/iOSTemplateMaker/Package.swift b/Scripts/Swift/iOSTemplateMaker/Package.swift new file mode 100644 index 00000000..46e6dd43 --- /dev/null +++ b/Scripts/Swift/iOSTemplateMaker/Package.swift @@ -0,0 +1,28 @@ +// swift-tools-version: 5.7.1 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "iOSTemplateMaker", + products: [ + .executable( + name: "iOSTemplateMaker", + targets: ["iOSTemplateMaker"] + ), + ], + dependencies: [ + .package( + url: "https://github.com/apple/swift-argument-parser.git", + from: "1.0.0" + ), + ], + targets: [ + .executableTarget( + name: "iOSTemplateMaker", + dependencies: [ + .product(name: "ArgumentParser", package: "swift-argument-parser") + ] + ), + ] +) diff --git a/Scripts/Swift/iOSTemplateMaker/README.md b/Scripts/Swift/iOSTemplateMaker/README.md new file mode 100644 index 00000000..552722bb --- /dev/null +++ b/Scripts/Swift/iOSTemplateMaker/README.md @@ -0,0 +1,3 @@ +# iOSTemplateMaker + +A description of this package. diff --git a/Scripts/Swift/Extensions/FileManager+Utils.swift b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/Extensions/FileManager+Utils.swift similarity index 100% rename from Scripts/Swift/Extensions/FileManager+Utils.swift rename to Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/Extensions/FileManager+Utils.swift diff --git a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/Extensions/Optional+Utils.swift b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/Extensions/Optional+Utils.swift new file mode 100644 index 00000000..40610fbe --- /dev/null +++ b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/Extensions/Optional+Utils.swift @@ -0,0 +1,18 @@ +import Foundation + +extension Optional { + + func unwrappedOr(_ defaultValue: Wrapped) -> Wrapped { + switch self { + case .none: + return defaultValue + case let .some(value): + return value + } + } +} + +extension Optional where Wrapped == String { + + var string: String { unwrappedOr("") } +} diff --git a/Scripts/Swift/Extensions/String+Utils.swift b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/Extensions/String+Utils.swift similarity index 83% rename from Scripts/Swift/Extensions/String+Utils.swift rename to Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/Extensions/String+Utils.swift index 76ccddaf..527a0b9f 100644 --- a/Scripts/Swift/Extensions/String+Utils.swift +++ b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/Extensions/String+Utils.swift @@ -1,5 +1,8 @@ +import Foundation + extension String { + /// Match string with regex expression static func ~= (lhs: String, rhs: String) -> Bool { guard let regex = try? NSRegularExpression(pattern: rhs) else { return false } let range = NSRange(location: 0, length: lhs.utf16.count) diff --git a/Scripts/Swift/Helpers/SafeShell.swift b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/Helpers/SafeShell.swift similarity index 100% rename from Scripts/Swift/Helpers/SafeShell.swift rename to Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/Helpers/SafeShell.swift diff --git a/Scripts/Swift/SetUpCICDService.swift b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpCICDService.swift similarity index 95% rename from Scripts/Swift/SetUpCICDService.swift rename to Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpCICDService.swift index b94d97d4..a126355c 100644 --- a/Scripts/Swift/SetUpCICDService.swift +++ b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpCICDService.swift @@ -1,3 +1,5 @@ +import Foundation + struct SetUpCICDService { enum CICDService { @@ -26,7 +28,7 @@ struct SetUpCICDService { var service: CICDService? = nil while service == nil { print("Which CI/CD service do you use (Can be edited later) [(g)ithub/(b)itrise/(c)odemagic/(l)ater]: ") - service = CICDService(readLine() ?? "") + service = CICDService(readLine().string) } switch service { diff --git a/Scripts/Swift/SetUpDeliveryConstants.swift b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpDeliveryConstants.swift similarity index 100% rename from Scripts/Swift/SetUpDeliveryConstants.swift rename to Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpDeliveryConstants.swift diff --git a/Scripts/Swift/SetUpInterface.swift b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpInterface.swift similarity index 98% rename from Scripts/Swift/SetUpInterface.swift rename to Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpInterface.swift index f34d42b8..295af3b1 100644 --- a/Scripts/Swift/SetUpInterface.swift +++ b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpInterface.swift @@ -1,3 +1,5 @@ +import Foundation + struct SetUpInterface { enum Interface { diff --git a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpTestFirebase.swift b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpTestFirebase.swift new file mode 100644 index 00000000..5f23b513 --- /dev/null +++ b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpTestFirebase.swift @@ -0,0 +1,23 @@ +import Foundation + +struct SetUpTestFirebase { + + private let teamIdPlaceholder = "<#teamId#>" + private let stagingFirebaseAppIdPlaceholder = "<#stagingFirebaseAppId#>" + private let firebaseTesterGroupsPlaceholder = "<#group1#>, <#group2#>" + private let matchRepoPlaceholder = "git@github.com:{organization}/{repo}.git" + + private let firebaseTesterGroup = "nimble" + private let fileManager = FileManager.default + + let matchRepo: String + let stagingFirebaseAppId: String + let teamId: String + + func perform() { + fileManager.replaceAllOccurrences(of: teamIdPlaceholder, to: teamId) + fileManager.replaceAllOccurrences(of: stagingFirebaseAppIdPlaceholder, to: stagingFirebaseAppId) + fileManager.replaceAllOccurrences(of: firebaseTesterGroupsPlaceholder, to: firebaseTesterGroup) + fileManager.replaceAllOccurrences(of: matchRepoPlaceholder, to: matchRepo) + } +} diff --git a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpTestTestFlight.swift b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpTestTestFlight.swift new file mode 100644 index 00000000..5dd58752 --- /dev/null +++ b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpTestTestFlight.swift @@ -0,0 +1,23 @@ +import Foundation + +struct SetUpTestTestFlight { + + private let teamIdPlaceholder = "<#teamId#>" + private let apiKeyIdPlaceholder = "<#API_KEY_ID#>" + private let issuerIdPlaceholder = "<#ISSUER_ID#>" + private let matchRepoPlaceholder = "git@github.com:{organization}/{repo}.git" + + private let fileManager = FileManager.default + + let matchRepo: String + let apiKey: String + let issuerId: String + let teamId: String + + func perform() { + fileManager.replaceAllOccurrences(of: teamIdPlaceholder, to: teamId) + fileManager.replaceAllOccurrences(of: apiKeyIdPlaceholder, to: apiKey) + fileManager.replaceAllOccurrences(of: issuerIdPlaceholder, to: issuerId) + fileManager.replaceAllOccurrences(of: matchRepoPlaceholder, to: matchRepo) + } +} diff --git a/Scripts/Swift/SetUpiOSProject.swift b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpiOSProject.swift similarity index 88% rename from Scripts/Swift/SetUpiOSProject.swift rename to Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpiOSProject.swift index 9ad2ac5f..89d759ac 100644 --- a/Scripts/Swift/SetUpiOSProject.swift +++ b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpiOSProject.swift @@ -1,4 +1,4 @@ -#!/usr/bin/swift +import Foundation class SetUpIOSProject { @@ -14,7 +14,21 @@ class SetUpIOSProject { private var minimumVersion = "" private var interface: SetUpInterface.Interface? private var projectNameNoSpace: String { projectName.trimmingCharacters(in: .whitespacesAndNewlines) } - private var isCI = !(ProcessInfo.processInfo.environment["CI"] ?? "").isEmpty + private var isCI = !((ProcessInfo.processInfo.environment["CI"]).string).isEmpty + + init( + bundleIdProduction: String = "", + bundleIdStaging: String = "", + projectName: String = "", + minimumVersion: String = "", + interface: String = "" + ) { + self.bundleIdProduction = bundleIdProduction + self.bundleIdStaging = bundleIdStaging + self.projectName = projectName + self.minimumVersion = minimumVersion + self.interface = .init(interface) + } func perform() { readArguments() @@ -34,42 +48,30 @@ class SetUpIOSProject { } private func readArguments() { - // TODO: Should be replaced with ArgumentParser instead of command line - for (index, argument) in CommandLine.arguments.enumerated() { - switch index { - case 1: bundleIdProduction = argument - case 2: bundleIdStaging = argument - case 3: projectName = argument - case 4: minimumVersion = argument - case 5: interface = .init(argument) - default: break - } - } - if isCI { minimumVersion = "14.0" } while bundleIdProduction.isEmpty || !checkPackageName(bundleIdProduction) { print("BUNDLE ID PRODUCTION (i.e. com.example.project):") - bundleIdProduction = readLine() ?? "" + bundleIdProduction = readLine().string } while bundleIdStaging.isEmpty || !checkPackageName(bundleIdStaging) { print("BUNDLE ID STAGING (i.e. com.example.project.staging):") - bundleIdStaging = readLine() ?? "" + bundleIdStaging = readLine().string } while projectName.isEmpty { print("PROJECT NAME (i.e. NewProject):") - projectName = readLine() ?? "" + projectName = readLine().string } while minimumVersion.isEmpty || !checkVersion(minimumVersion) { print("iOS Minimum Version (i.e. 14.0):") - let version = readLine() ?? "" + let version = readLine().string minimumVersion = !version.isEmpty ? version : "14.0" } while interface == nil { print("Interface [(S)wiftUI or (U)IKit]:") - interface = SetUpInterface.Interface(readLine() ?? "") + interface = SetUpInterface.Interface(readLine().string) } } @@ -191,5 +193,3 @@ class SetUpIOSProject { return valid } } - -SetUpIOSProject().perform() diff --git a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/iOSTemplateMaker.swift b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/iOSTemplateMaker.swift new file mode 100644 index 00000000..fc8c3fd4 --- /dev/null +++ b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/iOSTemplateMaker.swift @@ -0,0 +1,78 @@ +import ArgumentParser +import Foundation + +@main +struct iOSTemplateMaker: ParsableCommand { + + static let configuration: CommandConfiguration = CommandConfiguration( + abstract: "Set up an iOS Project", + subcommands: [Make.self, MakeTestFirebase.self, MakeTestTestFlight.self], + defaultSubcommand: Make.self + ) +} + +extension iOSTemplateMaker { + + struct Make: ParsableCommand { + + @Option(help: "The production id (i.e. com.example.package)") + var bundleIdProduction: String? + @Option(help: "The staging id (i.e. com.example.package.staging)") + var bundleIdStaging: String? + @Option(help: "The project name (i.e. MyApp)") + var projectName: String? + @Option(help: "The minimum iOS version (14.0)") + var minimumVersion: String? + @Option(help: "The user interface frameword (SwiftUI or UIKit)") + var interface: String? + + mutating func run() { + SetUpIOSProject( + bundleIdProduction: bundleIdProduction.string, + bundleIdStaging: bundleIdStaging.string, + projectName: projectName.string, + minimumVersion: minimumVersion.string, + interface: interface.string + ).perform() + } + } +} + +extension iOSTemplateMaker { + + struct MakeTestFirebase: ParsableCommand { + + mutating func run() { + let envMatchRepo = ProcessInfo.processInfo.environment["MATCH_REPO"].string + let envStagingFirebaseAppId = ProcessInfo.processInfo.environment["STAGING_FIREBASE_APP_ID"].string + let envTeamId = ProcessInfo.processInfo.environment["TEAM_ID"].string + + SetUpTestFirebase( + matchRepo: envMatchRepo, + stagingFirebaseAppId: envStagingFirebaseAppId, + teamId: envTeamId + ).perform() + } + } +} + + +extension iOSTemplateMaker { + + struct MakeTestTestFlight: ParsableCommand { + + mutating func run() { + let envMatchRepo = ProcessInfo.processInfo.environment["MATCH_REPO"].string + let envApiKey = ProcessInfo.processInfo.environment["API_KEY_ID"].string + let envIssuerId = ProcessInfo.processInfo.environment["ISSUER_ID"].string + let envTeamId = ProcessInfo.processInfo.environment["TEAM_ID"].string + + SetUpTestTestFlight( + matchRepo: envMatchRepo, + apiKey: envApiKey, + issuerId: envIssuerId, + teamId: envTeamId + ).perform() + } + } +} diff --git a/Scripts/Swift/iOSTemplateMaker/Tests/iOSTemplateMakerTests/iOSTemplateMakerTests.swift b/Scripts/Swift/iOSTemplateMaker/Tests/iOSTemplateMakerTests/iOSTemplateMakerTests.swift new file mode 100644 index 00000000..bae860b5 --- /dev/null +++ b/Scripts/Swift/iOSTemplateMaker/Tests/iOSTemplateMakerTests/iOSTemplateMakerTests.swift @@ -0,0 +1,11 @@ +import XCTest +@testable import iOSTemplateMaker + +final class iOSTemplateMakerTests: XCTestCase { + func testExample() throws { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct + // results. + XCTAssertEqual(iOSTemplateMaker().text, "Hello, World!") + } +} diff --git a/make.sh b/make.sh deleted file mode 100644 index 61a83ee0..00000000 --- a/make.sh +++ /dev/null @@ -1,74 +0,0 @@ -#!/bin/sh -set -e - -# Script inspired by https://gist.github.com/szeidner/613fe4652fc86f083cefa21879d5522b - -readonly PROGNAME=$(basename $0) -readonly WORKING_DIR=$(cd -P -- "$(dirname -- "$0")" && pwd -P) - -die() { - echo "$PROGNAME: $*" >&2 - exit 1 -} - -usage() { - if [ "$*" != "" ] ; then - echo "Error: $*" - fi - - cat << EOF -Usage: $PROGNAME --bundle-id [BUNDLE_ID_PRODUCTION] --bundle-id-staging [BUNDLE_ID_STAGING] --project-name [PROJECT_NAME] --minimum-version [MINIMUM_VERSION] --interface [INTERFACE] -Set up an iOS app from tuist template. -Options: --h, --help display this usage message and exit --b, --bundle-id [BUNDLE_ID_PRODUCTION] the production id (i.e. com.example.package) --s, --bundle-id-staging [BUNDLE_ID_STAGING] the staging id (i.e. com.example.package.staging) --n, --project-name [PROJECT_NAME] the project name (i.e. MyApp) --m, --minimum-version [MINIMUM_VERSION] the minimum version of the project (i.e. 14.0) --i, --interface [INTERFACE] the user interface frameword (SwiftUI or UIKit) -EOF - exit 1 -} - -bundle_id_production="" -bundle_id_staging="" -project_name="" -minimum_version="" -interface="" - -while [ $# -gt 0 ] ; do - case "$1" in - -h|--help) - usage - ;; - -b|--bundle-id) - bundle_id_production="$2" - shift - ;; - -s|--bundle-id-staging) - bundle_id_staging="$2" - shift - ;; - -n|--project-name) - project_name="$2" - shift - ;; - -m|--minimum-version) - minimum_version="$2" - shift - ;; - -i|--interface) - interface="$2" - shift - ;; - -*) - usage "Unknown option '$1'" - ;; - *) - usage "Too many arguments" - ;; - esac - shift -done - -cat Scripts/Swift/SetUpiOSProject.swift Scripts/Swift/SetUpCICDService.swift Scripts/Swift/SetUpDeliveryConstants.swift Scripts/Swift/SetUpInterface.swift Scripts/Swift/Extensions/FileManager+Utils.swift Scripts/Swift/Extensions/String+Utils.swift Scripts/Swift/Helpers/SafeShell.swift > t.swift && swift t.swift $bundle_id_production $bundle_id_staging $project_name "$minimum_version" $interface && rm -rf 't.swift' From 0c2d1d4f15242d12df19cc1f889d44059e428440 Mon Sep 17 00:00:00 2001 From: Bliss Pisit Wetcha Date: Wed, 30 Aug 2023 12:56:46 +0700 Subject: [PATCH 02/22] [#495] Modify readme for Swift command --- .github/wiki/Deliverable-Configurations.md | 2 +- .github/wiki/Getting-Started.md | 14 +++++++++++++- .github/wiki/Selecting-User-Interface.md | 2 +- .gitignore | 4 +--- README.md | 4 ++-- Scripts/Swift/iOSTemplateMaker/README.md | 3 --- .../Sources/iOSTemplateMaker/SetUpiOSProject.swift | 2 -- .../Tests/iOSTemplateMakerTests/.gitkeep | 0 .../iOSTemplateMakerTests.swift | 11 ----------- 9 files changed, 18 insertions(+), 24 deletions(-) delete mode 100644 Scripts/Swift/iOSTemplateMaker/README.md create mode 100644 Scripts/Swift/iOSTemplateMaker/Tests/iOSTemplateMakerTests/.gitkeep delete mode 100644 Scripts/Swift/iOSTemplateMaker/Tests/iOSTemplateMakerTests/iOSTemplateMakerTests.swift diff --git a/.github/wiki/Deliverable-Configurations.md b/.github/wiki/Deliverable-Configurations.md index 1568bc23..74aac6d0 100644 --- a/.github/wiki/Deliverable-Configurations.md +++ b/.github/wiki/Deliverable-Configurations.md @@ -6,7 +6,7 @@ The file [DeliverableConstants.rb](https://github.com/nimblehq/ios-templates/blo ## Use the template -1. Running the `make.sh` script will ask if the developer wants to configure the `DeliverableConstants` file. +1. Running the `iOSTemplateMaker` script will ask if the developer wants to configure the `DeliverableConstants` file. 2. When confirming with the prompt, the template will launch Xcode to modify the `DeliverableConstants` file. ## Configure later diff --git a/.github/wiki/Getting-Started.md b/.github/wiki/Getting-Started.md index 0d2af9ad..542bf5fa 100644 --- a/.github/wiki/Getting-Started.md +++ b/.github/wiki/Getting-Started.md @@ -9,5 +9,17 @@ 2. Clone your repository 3. Setup the project by running the following command in your terminal: ```bash - sh make.sh --bundle-id [BUNDLE_ID_PRODUCTION] --bundle-id-staging [BUNDLE_ID_STAGING] --project-name [PROJECT_NAME] + swift run --package-path Scripts/Swift/iOSTemplateMaker iOSTemplateMaker make ``` + +## Options + +Options are optional and will be prompted if not provided. Example is provided in (brackets). + +- `--bundle-id-production`: The application's bundle id for production variant. (co.nimblehq.project) +- `--bundle-id-staging`: The application's bundle id for staging variant. (co.nimblehq.project.staging) +- `--project-name`: The name of the project. (Project) +- `--minimum-version`: The minimum version of the iOS application. (14.0) +- `--interface`: The user interface. (UIKit or SwiftUI) + +``` diff --git a/.github/wiki/Selecting-User-Interface.md b/.github/wiki/Selecting-User-Interface.md index 80482ea7..3d07a4a3 100644 --- a/.github/wiki/Selecting-User-Interface.md +++ b/.github/wiki/Selecting-User-Interface.md @@ -7,5 +7,5 @@ Current the template supports setup with two user interfaces: To select a user interface when creating a project pass the argument `--interface [SwiftUI or UIKit]` with the `make` script. ```bash - sh make.sh --bundle-id [BUNDLE_ID_PRODUCTION] --bundle-id-staging [BUNDLE_ID_STAGING] --project-name [PROJECT_NAME] --interface SwiftUI + swift run --package-path Scripts/Swift/iOSTemplateMaker iOSTemplateMaker make --interface SwiftUI ``` diff --git a/.gitignore b/.gitignore index 398c9216..f641b291 100644 --- a/.gitignore +++ b/.gitignore @@ -84,6 +84,4 @@ dependencies/ # Environment .env -Scripts/Swift/iOSTemplateMaker/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist -Scripts/Swift/iOSTemplateMaker/.build -Scripts/Swift/iOSTemplateMaker/.swiftpm +Scripts/Swift/iOSTemplateMaker/.* diff --git a/README.md b/README.md index 648e5158..86f4b12b 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ Our optimized iOS template used in our projects using Xcode Templates 2. Clone your repository 3. Setup the project by running the following command in your terminal: ```bash - sh make.sh --bundle-id [BUNDLE_ID_PRODUCTION] --bundle-id-staging [BUNDLE_ID_STAGING] --project-name [PROJECT_NAME] + swift run --package-path Scripts/Swift/iOSTemplateMaker iOSTemplateMaker make ``` ## Full Documentation @@ -53,4 +53,4 @@ We love open source and do our part in sharing our work with the community! See [our other projects][community] or [hire our team][hire] to help build your product. [community]: https://github.com/nimblehq -[hire]: https://nimblehq.co/ \ No newline at end of file +[hire]: https://nimblehq.co/ diff --git a/Scripts/Swift/iOSTemplateMaker/README.md b/Scripts/Swift/iOSTemplateMaker/README.md deleted file mode 100644 index 552722bb..00000000 --- a/Scripts/Swift/iOSTemplateMaker/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# iOSTemplateMaker - -A description of this package. diff --git a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpiOSProject.swift b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpiOSProject.swift index 89d759ac..ebda3ffb 100644 --- a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpiOSProject.swift +++ b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpiOSProject.swift @@ -151,7 +151,6 @@ class SetUpIOSProject { fileManager.removeItems(in: "Workspace.swift") print("Remove script files and git/index") - fileManager.removeItems(in: "make.sh") fileManager.removeItems(in: ".github/workflows/test_install_script.yml") fileManager.removeItems(in: ".git/index") try safeShell("git reset") @@ -162,7 +161,6 @@ class SetUpIOSProject { SetUpCICDService().perform() SetUpDeliveryConstants().perform() fileManager.removeItems(in: "fastlane/Tests") - fileManager.removeItems(in: "set_up_test_testflight.sh") fileManager.removeItems(in: "Scripts") } print("✅ Completed") diff --git a/Scripts/Swift/iOSTemplateMaker/Tests/iOSTemplateMakerTests/.gitkeep b/Scripts/Swift/iOSTemplateMaker/Tests/iOSTemplateMakerTests/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Scripts/Swift/iOSTemplateMaker/Tests/iOSTemplateMakerTests/iOSTemplateMakerTests.swift b/Scripts/Swift/iOSTemplateMaker/Tests/iOSTemplateMakerTests/iOSTemplateMakerTests.swift deleted file mode 100644 index bae860b5..00000000 --- a/Scripts/Swift/iOSTemplateMaker/Tests/iOSTemplateMakerTests/iOSTemplateMakerTests.swift +++ /dev/null @@ -1,11 +0,0 @@ -import XCTest -@testable import iOSTemplateMaker - -final class iOSTemplateMakerTests: XCTestCase { - func testExample() throws { - // This is an example of a functional test case. - // Use XCTAssert and related functions to verify your tests produce the correct - // results. - XCTAssertEqual(iOSTemplateMaker().text, "Hello, World!") - } -} From 0e72643cc1b9a1e0a0a61fef68043d6b86a1bcef Mon Sep 17 00:00:00 2001 From: Bliss Pisit Wetcha Date: Wed, 30 Aug 2023 13:53:38 +0700 Subject: [PATCH 03/22] [#495] Add helper for Env --- .github/wiki/Getting-Started.md | 4 ++++ .../Helpers/EnvironmentValue.swift | 15 ++++++++++++ .../Models/EnvironmentKey.swift | 23 +++++++++++++++++++ .../iOSTemplateMaker/SetUpiOSProject.swift | 2 +- .../iOSTemplateMaker/iOSTemplateMaker.swift | 14 +++++------ 5 files changed, 50 insertions(+), 8 deletions(-) create mode 100644 Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/Helpers/EnvironmentValue.swift create mode 100644 Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/Models/EnvironmentKey.swift diff --git a/.github/wiki/Getting-Started.md b/.github/wiki/Getting-Started.md index 542bf5fa..a6f6ea48 100644 --- a/.github/wiki/Getting-Started.md +++ b/.github/wiki/Getting-Started.md @@ -22,4 +22,8 @@ Options are optional and will be prompted if not provided. Example is provided i - `--minimum-version`: The minimum version of the iOS application. (14.0) - `--interface`: The user interface. (UIKit or SwiftUI) +### Example + +``` +swift run --package-path Scripts/Swift/iOSTemplateMaker iOSTemplateMaker make --bundle-id-production co.nimblehq.ios.templates --bundle-id-staging co.nimblehq.ios.templates.staging --project-name TemplateApp --interface SwiftUI ``` diff --git a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/Helpers/EnvironmentValue.swift b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/Helpers/EnvironmentValue.swift new file mode 100644 index 00000000..295b69c8 --- /dev/null +++ b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/Helpers/EnvironmentValue.swift @@ -0,0 +1,15 @@ +// +// EnvironmentValue.swift +// +// +// Created by Bliss on 30/8/23. +// + +import Foundation + +enum EnvironmentValue { + + static func value(for key: String) -> String? { + ProcessInfo.processInfo.environment[key] + } +} diff --git a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/Models/EnvironmentKey.swift b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/Models/EnvironmentKey.swift new file mode 100644 index 00000000..8fc4fa20 --- /dev/null +++ b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/Models/EnvironmentKey.swift @@ -0,0 +1,23 @@ +// +// EnvironmentKey.swift +// +// +// Created by Bliss on 30/8/23. +// + +enum EnvironmentKey: String { + + case matchRepo = "MATCH_REPO" + case stagingFirebaseAppId = "STAGING_FIREBASE_APP_ID" + case teamId = "TEAM_ID" + case apiKey = "API_KEY_ID" + case issuerId = "ISSUER_ID" + case isCI = "CI" +} + +extension EnvironmentValue { + + static func value(for key: EnvironmentKey) -> String? { + Self.value(for: key.rawValue) + } +} diff --git a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpiOSProject.swift b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpiOSProject.swift index ebda3ffb..b4b1d27d 100644 --- a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpiOSProject.swift +++ b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpiOSProject.swift @@ -14,7 +14,7 @@ class SetUpIOSProject { private var minimumVersion = "" private var interface: SetUpInterface.Interface? private var projectNameNoSpace: String { projectName.trimmingCharacters(in: .whitespacesAndNewlines) } - private var isCI = !((ProcessInfo.processInfo.environment["CI"]).string).isEmpty + private var isCI = !((EnvironmentValue.value(for: .isCI)).string).isEmpty init( bundleIdProduction: String = "", diff --git a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/iOSTemplateMaker.swift b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/iOSTemplateMaker.swift index fc8c3fd4..eeac8595 100644 --- a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/iOSTemplateMaker.swift +++ b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/iOSTemplateMaker.swift @@ -43,9 +43,9 @@ extension iOSTemplateMaker { struct MakeTestFirebase: ParsableCommand { mutating func run() { - let envMatchRepo = ProcessInfo.processInfo.environment["MATCH_REPO"].string - let envStagingFirebaseAppId = ProcessInfo.processInfo.environment["STAGING_FIREBASE_APP_ID"].string - let envTeamId = ProcessInfo.processInfo.environment["TEAM_ID"].string + let envMatchRepo = EnvironmentValue.value(for: .matchRepo).string + let envStagingFirebaseAppId = EnvironmentValue.value(for: .stagingFirebaseAppId).string + let envTeamId = EnvironmentValue.value(for: .teamId).string SetUpTestFirebase( matchRepo: envMatchRepo, @@ -62,10 +62,10 @@ extension iOSTemplateMaker { struct MakeTestTestFlight: ParsableCommand { mutating func run() { - let envMatchRepo = ProcessInfo.processInfo.environment["MATCH_REPO"].string - let envApiKey = ProcessInfo.processInfo.environment["API_KEY_ID"].string - let envIssuerId = ProcessInfo.processInfo.environment["ISSUER_ID"].string - let envTeamId = ProcessInfo.processInfo.environment["TEAM_ID"].string + let envMatchRepo = EnvironmentValue.value(for: .matchRepo).string + let envApiKey = EnvironmentValue.value(for: .apiKey).string + let envIssuerId = EnvironmentValue.value(for: .issuerId).string + let envTeamId = EnvironmentValue.value(for: .teamId).string SetUpTestTestFlight( matchRepo: envMatchRepo, From 3fcb78945e97b6622df72c9a7a1cea77c2d85279 Mon Sep 17 00:00:00 2001 From: Bliss Pisit Wetcha Date: Wed, 30 Aug 2023 18:31:56 +0700 Subject: [PATCH 04/22] [#495] Remove template workflows when using template --- .../automatic_pull_request_review.yml | 0 .../deploy_app_store.yml | 0 .../deploy_production_firebase.yml | 0 .../deploy_staging_firebase.yml | 0 .../draft_a_new_release.yml | 0 .../publish_docs_to_wiki.yml | 19 +++++++++++++++++++ .../Extensions/FileManager+Utils.swift | 9 +++++++-- .../iOSTemplateMaker/SetUpCICDService.swift | 4 ++++ .../iOSTemplateMaker/iOSTemplateMaker.swift | 2 +- 9 files changed, 31 insertions(+), 3 deletions(-) rename .github/{workflows => project_workflows}/automatic_pull_request_review.yml (100%) rename .github/{workflows => project_workflows}/deploy_app_store.yml (100%) rename .github/{workflows => project_workflows}/deploy_production_firebase.yml (100%) rename .github/{workflows => project_workflows}/deploy_staging_firebase.yml (100%) rename .github/{workflows => project_workflows}/draft_a_new_release.yml (100%) create mode 100644 .github/project_workflows/publish_docs_to_wiki.yml diff --git a/.github/workflows/automatic_pull_request_review.yml b/.github/project_workflows/automatic_pull_request_review.yml similarity index 100% rename from .github/workflows/automatic_pull_request_review.yml rename to .github/project_workflows/automatic_pull_request_review.yml diff --git a/.github/workflows/deploy_app_store.yml b/.github/project_workflows/deploy_app_store.yml similarity index 100% rename from .github/workflows/deploy_app_store.yml rename to .github/project_workflows/deploy_app_store.yml diff --git a/.github/workflows/deploy_production_firebase.yml b/.github/project_workflows/deploy_production_firebase.yml similarity index 100% rename from .github/workflows/deploy_production_firebase.yml rename to .github/project_workflows/deploy_production_firebase.yml diff --git a/.github/workflows/deploy_staging_firebase.yml b/.github/project_workflows/deploy_staging_firebase.yml similarity index 100% rename from .github/workflows/deploy_staging_firebase.yml rename to .github/project_workflows/deploy_staging_firebase.yml diff --git a/.github/workflows/draft_a_new_release.yml b/.github/project_workflows/draft_a_new_release.yml similarity index 100% rename from .github/workflows/draft_a_new_release.yml rename to .github/project_workflows/draft_a_new_release.yml diff --git a/.github/project_workflows/publish_docs_to_wiki.yml b/.github/project_workflows/publish_docs_to_wiki.yml new file mode 100644 index 00000000..dc71b021 --- /dev/null +++ b/.github/project_workflows/publish_docs_to_wiki.yml @@ -0,0 +1,19 @@ +name: Publish docs to Wiki + +on: + push: + paths: + - .github/wiki/** + branches: + - main + - master + +jobs: + publish_docs_to_wiki: + name: Publish Wiki + uses: nimblehq/github-actions-workflows/.github/workflows/publish_wiki.yml@0.1.0 + with: + USER_NAME: team-nimblehq + USER_EMAIL: dev@nimblehq.co + secrets: + USER_TOKEN: ${{ secrets.NIMBLE_DEV_TOKEN }} diff --git a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/Extensions/FileManager+Utils.swift b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/Extensions/FileManager+Utils.swift index 6fd75e11..cf7852da 100644 --- a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/Extensions/FileManager+Utils.swift +++ b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/Extensions/FileManager+Utils.swift @@ -46,13 +46,18 @@ extension FileManager { } } - func createFile(name: String, at directory: String) { + func createDirectory(path: String) { let currentDirectory = currentDirectoryPath do { - try createDirectory(atPath: "\(currentDirectory)/\(directory)", withIntermediateDirectories: true, attributes: nil) + try createDirectory(atPath: "\(currentDirectory)/\(path)", withIntermediateDirectories: true, attributes: nil) } catch { print("Error \(error)") } + } + + func createFile(name: String, at directory: String) { + let currentDirectory = currentDirectoryPath + createDirectory(path: directory) createFile(atPath: "\(currentDirectory)\(directory)\(name)", contents: nil) } diff --git a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpCICDService.swift b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpCICDService.swift index a126355c..06436a46 100644 --- a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpCICDService.swift +++ b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpCICDService.swift @@ -36,6 +36,10 @@ struct SetUpCICDService { print("Setting template for Github Actions") fileManager.removeItems(in: "bitrise.yml") fileManager.removeItems(in: "codemagic.yaml") + fileManager.removeItems(in: ".github/workflows") + fileManager.createDirectory(path: ".github/workflows") + fileManager.moveFiles(in: ".github/project_workflows", to: ".github/workflows") + fileManager.removeItems(in: ".github/project_workflows") case .bitrise: print("Setting template for Bitrise") fileManager.removeItems(in: "codemagic.yaml") diff --git a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/iOSTemplateMaker.swift b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/iOSTemplateMaker.swift index eeac8595..ea1b341d 100644 --- a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/iOSTemplateMaker.swift +++ b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/iOSTemplateMaker.swift @@ -23,7 +23,7 @@ extension iOSTemplateMaker { var projectName: String? @Option(help: "The minimum iOS version (14.0)") var minimumVersion: String? - @Option(help: "The user interface frameword (SwiftUI or UIKit)") + @Option(help: "The user interface framework (SwiftUI or UIKit)") var interface: String? mutating func run() { From a5dd60bfccc913db6d6df6641290f5091453a733 Mon Sep 17 00:00:00 2001 From: Bliss Pisit Wetcha Date: Thu, 28 Sep 2023 11:40:24 +0700 Subject: [PATCH 05/22] [#495] Fix uikit script --- .../Sources/iOSTemplateMaker/SetUpInterface.swift | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpInterface.swift b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpInterface.swift index 295af3b1..6479b77f 100644 --- a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpInterface.swift +++ b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpInterface.swift @@ -7,12 +7,13 @@ struct SetUpInterface { case swiftUI, uiKit init?(_ name: String) { - switch name.lowercased() { - case "s", "swiftui": + let name = name.lowercased() + if name == "s" || name == "swiftui" { self = .swiftUI - case "u", "uikit": + } else if name == "u" || name == "uikit" { self = .uiKit - default: return nil + } else { + return nil } } From 87b99d87dcd2112be2a609dc3f57c672e3d1e892 Mon Sep 17 00:00:00 2001 From: Bliss Pisit Wetcha Date: Wed, 4 Oct 2023 12:33:25 +0700 Subject: [PATCH 06/22] [#495] Fix interface script --- .../Sources/iOSTemplateMaker/SetUpInterface.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpInterface.swift b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpInterface.swift index 6479b77f..9024ea87 100644 --- a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpInterface.swift +++ b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpInterface.swift @@ -43,7 +43,7 @@ struct SetUpInterface { let folderName = interface.folderName fileManager.moveFiles(in: "tuist/Interfaces/\(folderName)/Project", to: "") - fileManager.moveFiles(in: "tuist/Interfaces/\(folderName)/Sources", to: "TemplateApp/Sources") + fileManager.moveFiles(in: "tuist/Interfaces/\(folderName)/Sources", to: "\(projectName)/Sources") fileManager.removeItems(in: "tuist/Interfaces") } } From a7b948adc1f0314543ca883610f3cc3784c4a849 Mon Sep 17 00:00:00 2001 From: Bliss Pisit Wetcha Date: Wed, 4 Oct 2023 12:37:43 +0700 Subject: [PATCH 07/22] [#495] Fix removal script --- .../Sources/iOSTemplateMaker/SetUpiOSProject.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpiOSProject.swift b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpiOSProject.swift index b4b1d27d..2204973a 100644 --- a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpiOSProject.swift +++ b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpiOSProject.swift @@ -151,7 +151,8 @@ class SetUpIOSProject { fileManager.removeItems(in: "Workspace.swift") print("Remove script files and git/index") - fileManager.removeItems(in: ".github/workflows/test_install_script.yml") + fileManager.removeItems(in: ".github/workflows/test_uikit_install_script.yml") + fileManager.removeItems(in: ".github/workflows/test_swiftui_install_script.yml") fileManager.removeItems(in: ".git/index") try safeShell("git reset") } From 6a8546d3e59b871371eb7508eb23685bcf79115e Mon Sep 17 00:00:00 2001 From: Bliss Pisit Wetcha Date: Wed, 4 Oct 2023 13:01:37 +0700 Subject: [PATCH 08/22] [#495] Skip Rename swift build --- .../Sources/iOSTemplateMaker/Extensions/FileManager+Utils.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/Extensions/FileManager+Utils.swift b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/Extensions/FileManager+Utils.swift index cf7852da..eef093a7 100644 --- a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/Extensions/FileManager+Utils.swift +++ b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/Extensions/FileManager+Utils.swift @@ -93,8 +93,10 @@ extension FileManager { options: [.skipsPackageDescendants] ) { let hiddenFolderRegex = "\(directory.replacingOccurrences(of: "/", with: "\\/"))\\/\\..*\\/" + let swiftScriptBuildDirectory = "Scripts/Swift/iOSTemplateMaker/.build".lowercased() for case let fileURL as URL in enumerator { guard !(fileURL.relativePath ~= hiddenFolderRegex) else { continue } + guard !(fileURL.relativePath.lowercased().contains(swiftScriptBuildDirectory)) else { continue } let fileAttributes = try? fileURL.resourceValues(forKeys:[.isRegularFileKey]) guard fileAttributes?.isRegularFile ?? false else { continue } files.append(fileURL) From e3fb966e633801333ee409ca1f4b64d9173f122d Mon Sep 17 00:00:00 2001 From: Bliss Pisit Wetcha Date: Wed, 4 Oct 2023 13:07:13 +0700 Subject: [PATCH 09/22] [#495] Skip Rename png --- .../iOSTemplateMaker/Extensions/FileManager+Utils.swift | 9 +++++---- .../Sources/iOSTemplateMaker/SetUpiOSProject.swift | 1 - 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/Extensions/FileManager+Utils.swift b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/Extensions/FileManager+Utils.swift index eef093a7..77b3979a 100644 --- a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/Extensions/FileManager+Utils.swift +++ b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/Extensions/FileManager+Utils.swift @@ -71,7 +71,9 @@ extension FileManager { } func replaceAllOccurrences(of original: String, to replacing: String) { - let files = try? allFiles(in: currentDirectoryPath) + let swiftScriptBuildDirectory = "Scripts/Swift/iOSTemplateMaker/.build".lowercased() + let pngImage = ".png" + let files = try? allFiles(in: currentDirectoryPath, skips: [swiftScriptBuildDirectory, pngImage]) guard let files else { return print("Cannot find any files in current directory") } for file in files { do { @@ -84,7 +86,7 @@ extension FileManager { } } - private func allFiles(in directory: String) throws -> [URL] { + private func allFiles(in directory: String, skips: [String] = []) throws -> [URL] { let url = URL(fileURLWithPath: directory) var files = [URL]() if let enumerator = enumerator( @@ -93,10 +95,9 @@ extension FileManager { options: [.skipsPackageDescendants] ) { let hiddenFolderRegex = "\(directory.replacingOccurrences(of: "/", with: "\\/"))\\/\\..*\\/" - let swiftScriptBuildDirectory = "Scripts/Swift/iOSTemplateMaker/.build".lowercased() for case let fileURL as URL in enumerator { guard !(fileURL.relativePath ~= hiddenFolderRegex) else { continue } - guard !(fileURL.relativePath.lowercased().contains(swiftScriptBuildDirectory)) else { continue } + guard !(skips.contains(where: { fileURL.relativePath.lowercased().contains($0) })) else { continue } let fileAttributes = try? fileURL.resourceValues(forKeys:[.isRegularFileKey]) guard fileAttributes?.isRegularFile ?? false else { continue } files.append(fileURL) diff --git a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpiOSProject.swift b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpiOSProject.swift index 2204973a..412b7a1b 100644 --- a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpiOSProject.swift +++ b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpiOSProject.swift @@ -161,7 +161,6 @@ class SetUpIOSProject { if !isCI { SetUpCICDService().perform() SetUpDeliveryConstants().perform() - fileManager.removeItems(in: "fastlane/Tests") fileManager.removeItems(in: "Scripts") } print("✅ Completed") From 07ea0ff5ff9a713189a01f4b6ee50cc5977b68d2 Mon Sep 17 00:00:00 2001 From: nkhanh44 Date: Thu, 28 Sep 2023 22:03:40 +0700 Subject: [PATCH 10/22] [#515] Remove all Rx things --- Tuist/Interfaces/UIKit/Project/Podfile | 10 ++----- .../NetworkAPI/Core/NetworkAPIProtocol.swift | 30 +++++++------------ .../Sources/Data/NetworkAPI/NetworkAPI.swift | 8 +++-- 3 files changed, 18 insertions(+), 30 deletions(-) diff --git a/Tuist/Interfaces/UIKit/Project/Podfile b/Tuist/Interfaces/UIKit/Project/Podfile index dee619b6..cf4fbd43 100644 --- a/Tuist/Interfaces/UIKit/Project/Podfile +++ b/Tuist/Interfaces/UIKit/Project/Podfile @@ -5,8 +5,6 @@ inhibit_all_warnings! def testing_pods pod 'Quick' pod 'Nimble' - pod 'RxNimble', subspecs: ['RxBlocking', 'RxTest'] - pod 'RxSwift' pod 'Sourcery' pod 'SwiftFormat/CLI' end @@ -16,11 +14,9 @@ target '{PROJECT_NAME}' do pod 'Kingfisher' pod 'SnapKit' - # Rx - pod 'RxAlamofire' - pod 'RxCocoa' - pod 'RxDataSources' - pod 'RxSwift' + # Backend + pod 'Alamofire' + pod 'JSONAPIMapper', :git => 'https://github.com/nimblehq/JSONMapper', :tag => '1.1.1' # Storage pod 'KeychainAccess' diff --git a/Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/Core/NetworkAPIProtocol.swift b/Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/Core/NetworkAPIProtocol.swift index c8be3e5b..fb6a161d 100644 --- a/Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/Core/NetworkAPIProtocol.swift +++ b/Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/Core/NetworkAPIProtocol.swift @@ -3,12 +3,14 @@ // import Alamofire -import RxAlamofire -import RxSwift +import Combine protocol NetworkAPIProtocol { - func performRequest(_ configuration: RequestConfiguration, for type: T.Type) -> Single + func performRequest( + _ configuration: RequestConfiguration, + for type: T.Type + ) -> AnyPublisher } extension NetworkAPIProtocol { @@ -17,28 +19,16 @@ extension NetworkAPIProtocol { session: Session, configuration: RequestConfiguration, decoder: JSONDecoder - ) -> Single { - return session.rx.request( - configuration.method, + ) -> AnyPublisher { + return session.request( configuration.url, + method: configuration.method, parameters: configuration.parameters, encoding: configuration.encoding, headers: configuration.headers, interceptor: configuration.interceptor ) - .responseData() - .flatMap { _, data -> Observable in - Observable.create { observer in - do { - let decodable = try decoder.decode(T.self, from: data) - observer.on(.next(decodable)) - } catch { - observer.on(.error(error)) - } - observer.on(.completed) - return Disposables.create() - } - } - .asSingle() + .publishDecodable(type: T.self, decoder: decoder) + .value() } } diff --git a/Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/NetworkAPI.swift b/Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/NetworkAPI.swift index a713490e..413a003c 100644 --- a/Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/NetworkAPI.swift +++ b/Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/NetworkAPI.swift @@ -3,8 +3,7 @@ // import Alamofire -import Foundation -import RxSwift +import Combine final class NetworkAPI: NetworkAPIProtocol { @@ -14,7 +13,10 @@ final class NetworkAPI: NetworkAPIProtocol { self.decoder = decoder } - func performRequest(_ configuration: RequestConfiguration, for type: T.Type) -> Single { + func performRequest( + _ configuration: RequestConfiguration, + for type: T.Type + ) -> AnyPublisher { request( session: Session(), configuration: configuration, From 78dafeba3c5991d20e34f6c0ed2ffb737c84c5c2 Mon Sep 17 00:00:00 2001 From: nkhanh44 Date: Mon, 2 Oct 2023 17:01:11 +0700 Subject: [PATCH 11/22] [#515] Add asyn await to network layer --- .../NetworkAPI/Core/NetworkAPIProtocol.swift | 38 ++++++++++++------- .../Sources/Data/NetworkAPI/NetworkAPI.swift | 5 +-- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/Core/NetworkAPIProtocol.swift b/Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/Core/NetworkAPIProtocol.swift index fb6a161d..ff17c8a9 100644 --- a/Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/Core/NetworkAPIProtocol.swift +++ b/Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/Core/NetworkAPIProtocol.swift @@ -3,14 +3,13 @@ // import Alamofire -import Combine protocol NetworkAPIProtocol { func performRequest( _ configuration: RequestConfiguration, for type: T.Type - ) -> AnyPublisher + ) async throws -> T } extension NetworkAPIProtocol { @@ -19,16 +18,29 @@ extension NetworkAPIProtocol { session: Session, configuration: RequestConfiguration, decoder: JSONDecoder - ) -> AnyPublisher { - return session.request( - configuration.url, - method: configuration.method, - parameters: configuration.parameters, - encoding: configuration.encoding, - headers: configuration.headers, - interceptor: configuration.interceptor - ) - .publishDecodable(type: T.self, decoder: decoder) - .value() + ) async throws -> T { + try await withCheckedThrowingContinuation { continuation in + session.request( + configuration.url, + method: configuration.method, + parameters: configuration.parameters, + encoding: configuration.encoding, + headers: configuration.headers, + interceptor: configuration.interceptor + ) + .response { response in + switch response.result { + case let .success(data): + do { + let decodedData = try decoder.decode(T.self, from: data ?? Data()) + continuation.resume(returning: decodedData) + } catch { + continuation.resume(throwing: error) + } + case let .failure(error): + continuation.resume(throwing: error) + } + } + } } } diff --git a/Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/NetworkAPI.swift b/Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/NetworkAPI.swift index 413a003c..d52c2081 100644 --- a/Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/NetworkAPI.swift +++ b/Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/NetworkAPI.swift @@ -3,7 +3,6 @@ // import Alamofire -import Combine final class NetworkAPI: NetworkAPIProtocol { @@ -16,8 +15,8 @@ final class NetworkAPI: NetworkAPIProtocol { func performRequest( _ configuration: RequestConfiguration, for type: T.Type - ) -> AnyPublisher { - request( + ) async throws -> T { + try await request( session: Session(), configuration: configuration, decoder: decoder From 1f226eb6adf157bf7d277339fab759c07956d629 Mon Sep 17 00:00:00 2001 From: nkhanh44 Date: Wed, 4 Oct 2023 15:15:39 +0700 Subject: [PATCH 12/22] [#515] Refactor NetworkAPIProtocol --- .../NetworkAPI/Core/NetworkAPIProtocol.swift | 33 ++++++------------- 1 file changed, 10 insertions(+), 23 deletions(-) diff --git a/Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/Core/NetworkAPIProtocol.swift b/Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/Core/NetworkAPIProtocol.swift index ff17c8a9..c2ee0030 100644 --- a/Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/Core/NetworkAPIProtocol.swift +++ b/Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/Core/NetworkAPIProtocol.swift @@ -19,28 +19,15 @@ extension NetworkAPIProtocol { configuration: RequestConfiguration, decoder: JSONDecoder ) async throws -> T { - try await withCheckedThrowingContinuation { continuation in - session.request( - configuration.url, - method: configuration.method, - parameters: configuration.parameters, - encoding: configuration.encoding, - headers: configuration.headers, - interceptor: configuration.interceptor - ) - .response { response in - switch response.result { - case let .success(data): - do { - let decodedData = try decoder.decode(T.self, from: data ?? Data()) - continuation.resume(returning: decodedData) - } catch { - continuation.resume(throwing: error) - } - case let .failure(error): - continuation.resume(throwing: error) - } - } - } + try await session.request( + configuration.url, + method: configuration.method, + parameters: configuration.parameters, + encoding: configuration.encoding, + headers: configuration.headers, + interceptor: configuration.interceptor + ) + .serializingDecodable(T.self) + .value } } From 034edaea3ac6fdc2e0990fa29d7a62a9622525a4 Mon Sep 17 00:00:00 2001 From: nkhanh44 Date: Wed, 4 Oct 2023 22:14:28 +0700 Subject: [PATCH 13/22] [#515] Refactor NetworkAPIProtocol and move them to shared folder --- .../NetworkAPI/Core/NetworkAPIProtocol.swift | 34 ---------------- .../Sources/Data/NetworkAPI/NetworkAPI.swift | 26 ------------- .../NetworkAPI/Core/NetworkAPIError.swift | 11 ------ .../Core/RequestConfiguration.swift | 39 ------------------- .../Data/NetworkAPI/Interceptors/.gitkeep | 0 .../Sources/Data/NetworkAPI/Models/.gitkeep | 0 .../NetworkAPI/RequestConfigurations/.gitkeep | 0 .../UIKit/Sources/Data/Repositories/.gitkeep | 0 .../NetworkAPI/Core/NetworkAPIError.swift | 0 .../NetworkAPI/Core/NetworkAPIProtocol.swift | 0 .../Core/RequestConfiguration.swift | 0 .../Data/NetworkAPI/Interceptors/.gitkeep | 0 .../Sources/Data/NetworkAPI/Models/.gitkeep | 0 .../Sources/Data/NetworkAPI/NetworkAPI.swift | 0 .../NetworkAPI/RequestConfigurations/.gitkeep | 0 .../Sources/Data/Repositories/.gitkeep | 0 16 files changed, 110 deletions(-) delete mode 100644 Tuist/Interfaces/SwiftUI/Sources/Data/NetworkAPI/Core/NetworkAPIProtocol.swift delete mode 100644 Tuist/Interfaces/SwiftUI/Sources/Data/NetworkAPI/NetworkAPI.swift delete mode 100644 Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/Core/NetworkAPIError.swift delete mode 100644 Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/Core/RequestConfiguration.swift delete mode 100644 Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/Interceptors/.gitkeep delete mode 100644 Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/Models/.gitkeep delete mode 100644 Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/RequestConfigurations/.gitkeep delete mode 100644 Tuist/Interfaces/UIKit/Sources/Data/Repositories/.gitkeep rename {Tuist/Interfaces/SwiftUI => {PROJECT_NAME}}/Sources/Data/NetworkAPI/Core/NetworkAPIError.swift (100%) rename {Tuist/Interfaces/UIKit => {PROJECT_NAME}}/Sources/Data/NetworkAPI/Core/NetworkAPIProtocol.swift (100%) rename {Tuist/Interfaces/SwiftUI => {PROJECT_NAME}}/Sources/Data/NetworkAPI/Core/RequestConfiguration.swift (100%) rename {Tuist/Interfaces/SwiftUI => {PROJECT_NAME}}/Sources/Data/NetworkAPI/Interceptors/.gitkeep (100%) rename {Tuist/Interfaces/SwiftUI => {PROJECT_NAME}}/Sources/Data/NetworkAPI/Models/.gitkeep (100%) rename {Tuist/Interfaces/UIKit => {PROJECT_NAME}}/Sources/Data/NetworkAPI/NetworkAPI.swift (100%) rename {Tuist/Interfaces/SwiftUI => {PROJECT_NAME}}/Sources/Data/NetworkAPI/RequestConfigurations/.gitkeep (100%) rename {Tuist/Interfaces/SwiftUI => {PROJECT_NAME}}/Sources/Data/Repositories/.gitkeep (100%) diff --git a/Tuist/Interfaces/SwiftUI/Sources/Data/NetworkAPI/Core/NetworkAPIProtocol.swift b/Tuist/Interfaces/SwiftUI/Sources/Data/NetworkAPI/Core/NetworkAPIProtocol.swift deleted file mode 100644 index fb6a161d..00000000 --- a/Tuist/Interfaces/SwiftUI/Sources/Data/NetworkAPI/Core/NetworkAPIProtocol.swift +++ /dev/null @@ -1,34 +0,0 @@ -// -// NetworkAPIProtocol.swift -// - -import Alamofire -import Combine - -protocol NetworkAPIProtocol { - - func performRequest( - _ configuration: RequestConfiguration, - for type: T.Type - ) -> AnyPublisher -} - -extension NetworkAPIProtocol { - - func request( - session: Session, - configuration: RequestConfiguration, - decoder: JSONDecoder - ) -> AnyPublisher { - return session.request( - configuration.url, - method: configuration.method, - parameters: configuration.parameters, - encoding: configuration.encoding, - headers: configuration.headers, - interceptor: configuration.interceptor - ) - .publishDecodable(type: T.self, decoder: decoder) - .value() - } -} diff --git a/Tuist/Interfaces/SwiftUI/Sources/Data/NetworkAPI/NetworkAPI.swift b/Tuist/Interfaces/SwiftUI/Sources/Data/NetworkAPI/NetworkAPI.swift deleted file mode 100644 index 413a003c..00000000 --- a/Tuist/Interfaces/SwiftUI/Sources/Data/NetworkAPI/NetworkAPI.swift +++ /dev/null @@ -1,26 +0,0 @@ -// -// NetworkAPI.swift -// - -import Alamofire -import Combine - -final class NetworkAPI: NetworkAPIProtocol { - - private let decoder: JSONDecoder - - init(decoder: JSONDecoder = JSONDecoder()) { - self.decoder = decoder - } - - func performRequest( - _ configuration: RequestConfiguration, - for type: T.Type - ) -> AnyPublisher { - request( - session: Session(), - configuration: configuration, - decoder: decoder - ) - } -} diff --git a/Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/Core/NetworkAPIError.swift b/Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/Core/NetworkAPIError.swift deleted file mode 100644 index 78c72199..00000000 --- a/Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/Core/NetworkAPIError.swift +++ /dev/null @@ -1,11 +0,0 @@ -// -// NetworkAPIError.swift -// - -import Foundation - -enum NetworkAPIError: Error { - - case generic - case dataNotFound -} diff --git a/Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/Core/RequestConfiguration.swift b/Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/Core/RequestConfiguration.swift deleted file mode 100644 index 32ddb9d3..00000000 --- a/Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/Core/RequestConfiguration.swift +++ /dev/null @@ -1,39 +0,0 @@ -// -// RequestConfiguration.swift -// - -import Alamofire -import Foundation - -protocol RequestConfiguration { - - var baseURL: String { get } - - var endpoint: String { get } - - var method: HTTPMethod { get } - - var url: URLConvertible { get } - - var parameters: Parameters? { get } - - var encoding: ParameterEncoding { get } - - var headers: HTTPHeaders? { get } - - var interceptor: RequestInterceptor? { get } -} - -extension RequestConfiguration { - - var url: URLConvertible { - let url = URL(string: baseURL)?.appendingPathComponent(endpoint) - return url?.absoluteString ?? "\(baseURL)\(endpoint)" - } - - var parameters: Parameters? { nil } - - var headers: HTTPHeaders? { nil } - - var interceptor: RequestInterceptor? { nil } -} diff --git a/Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/Interceptors/.gitkeep b/Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/Interceptors/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/Models/.gitkeep b/Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/Models/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/RequestConfigurations/.gitkeep b/Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/RequestConfigurations/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/Tuist/Interfaces/UIKit/Sources/Data/Repositories/.gitkeep b/Tuist/Interfaces/UIKit/Sources/Data/Repositories/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/Tuist/Interfaces/SwiftUI/Sources/Data/NetworkAPI/Core/NetworkAPIError.swift b/{PROJECT_NAME}/Sources/Data/NetworkAPI/Core/NetworkAPIError.swift similarity index 100% rename from Tuist/Interfaces/SwiftUI/Sources/Data/NetworkAPI/Core/NetworkAPIError.swift rename to {PROJECT_NAME}/Sources/Data/NetworkAPI/Core/NetworkAPIError.swift diff --git a/Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/Core/NetworkAPIProtocol.swift b/{PROJECT_NAME}/Sources/Data/NetworkAPI/Core/NetworkAPIProtocol.swift similarity index 100% rename from Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/Core/NetworkAPIProtocol.swift rename to {PROJECT_NAME}/Sources/Data/NetworkAPI/Core/NetworkAPIProtocol.swift diff --git a/Tuist/Interfaces/SwiftUI/Sources/Data/NetworkAPI/Core/RequestConfiguration.swift b/{PROJECT_NAME}/Sources/Data/NetworkAPI/Core/RequestConfiguration.swift similarity index 100% rename from Tuist/Interfaces/SwiftUI/Sources/Data/NetworkAPI/Core/RequestConfiguration.swift rename to {PROJECT_NAME}/Sources/Data/NetworkAPI/Core/RequestConfiguration.swift diff --git a/Tuist/Interfaces/SwiftUI/Sources/Data/NetworkAPI/Interceptors/.gitkeep b/{PROJECT_NAME}/Sources/Data/NetworkAPI/Interceptors/.gitkeep similarity index 100% rename from Tuist/Interfaces/SwiftUI/Sources/Data/NetworkAPI/Interceptors/.gitkeep rename to {PROJECT_NAME}/Sources/Data/NetworkAPI/Interceptors/.gitkeep diff --git a/Tuist/Interfaces/SwiftUI/Sources/Data/NetworkAPI/Models/.gitkeep b/{PROJECT_NAME}/Sources/Data/NetworkAPI/Models/.gitkeep similarity index 100% rename from Tuist/Interfaces/SwiftUI/Sources/Data/NetworkAPI/Models/.gitkeep rename to {PROJECT_NAME}/Sources/Data/NetworkAPI/Models/.gitkeep diff --git a/Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/NetworkAPI.swift b/{PROJECT_NAME}/Sources/Data/NetworkAPI/NetworkAPI.swift similarity index 100% rename from Tuist/Interfaces/UIKit/Sources/Data/NetworkAPI/NetworkAPI.swift rename to {PROJECT_NAME}/Sources/Data/NetworkAPI/NetworkAPI.swift diff --git a/Tuist/Interfaces/SwiftUI/Sources/Data/NetworkAPI/RequestConfigurations/.gitkeep b/{PROJECT_NAME}/Sources/Data/NetworkAPI/RequestConfigurations/.gitkeep similarity index 100% rename from Tuist/Interfaces/SwiftUI/Sources/Data/NetworkAPI/RequestConfigurations/.gitkeep rename to {PROJECT_NAME}/Sources/Data/NetworkAPI/RequestConfigurations/.gitkeep diff --git a/Tuist/Interfaces/SwiftUI/Sources/Data/Repositories/.gitkeep b/{PROJECT_NAME}/Sources/Data/Repositories/.gitkeep similarity index 100% rename from Tuist/Interfaces/SwiftUI/Sources/Data/Repositories/.gitkeep rename to {PROJECT_NAME}/Sources/Data/Repositories/.gitkeep From 6658c62ee21614bd803dc6390e25ac796f8790d3 Mon Sep 17 00:00:00 2001 From: Bliss Pisit Wetcha Date: Wed, 4 Oct 2023 18:04:41 +0700 Subject: [PATCH 14/22] [#508] Add network test --- Tuist/Interfaces/SwiftUI/Project/Podfile | 1 + Tuist/Interfaces/UIKit/Project/Podfile | 1 + {PROJECT_NAME}Tests/Sources/Dummy/.gitkeep | 0 .../Sources/Dummy/DummyNetworkModel.swift | 14 ++++ .../Dummy/DummyRequestConfiguration.swift | 29 +++++++++ .../Data/NetworkAPI/NetworkAPISpec.swift | 64 +++++++++++++++++++ .../Sources/Utilities/.gitkeep | 0 .../Sources/Utilities/NetworkStubber.swift | 32 ++++++++++ 8 files changed, 141 insertions(+) delete mode 100644 {PROJECT_NAME}Tests/Sources/Dummy/.gitkeep create mode 100644 {PROJECT_NAME}Tests/Sources/Dummy/DummyNetworkModel.swift create mode 100644 {PROJECT_NAME}Tests/Sources/Dummy/DummyRequestConfiguration.swift create mode 100644 {PROJECT_NAME}Tests/Sources/Specs/Data/NetworkAPI/NetworkAPISpec.swift delete mode 100644 {PROJECT_NAME}Tests/Sources/Utilities/.gitkeep create mode 100644 {PROJECT_NAME}Tests/Sources/Utilities/NetworkStubber.swift diff --git a/Tuist/Interfaces/SwiftUI/Project/Podfile b/Tuist/Interfaces/SwiftUI/Project/Podfile index 6dbc2e01..7a0d2eed 100644 --- a/Tuist/Interfaces/SwiftUI/Project/Podfile +++ b/Tuist/Interfaces/SwiftUI/Project/Podfile @@ -7,6 +7,7 @@ def testing_pods pod 'Nimble', '~> 11.0' pod 'Sourcery' pod 'SwiftFormat/CLI' + pod 'OHHTTPStubs/Swift', :configurations => ['Debug Staging', 'Debug Production'] end target '{PROJECT_NAME}' do diff --git a/Tuist/Interfaces/UIKit/Project/Podfile b/Tuist/Interfaces/UIKit/Project/Podfile index cf4fbd43..d5bdbf53 100644 --- a/Tuist/Interfaces/UIKit/Project/Podfile +++ b/Tuist/Interfaces/UIKit/Project/Podfile @@ -7,6 +7,7 @@ def testing_pods pod 'Nimble' pod 'Sourcery' pod 'SwiftFormat/CLI' + pod 'OHHTTPStubs/Swift', :configurations => ['Debug Staging', 'Debug Production'] end target '{PROJECT_NAME}' do diff --git a/{PROJECT_NAME}Tests/Sources/Dummy/.gitkeep b/{PROJECT_NAME}Tests/Sources/Dummy/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/{PROJECT_NAME}Tests/Sources/Dummy/DummyNetworkModel.swift b/{PROJECT_NAME}Tests/Sources/Dummy/DummyNetworkModel.swift new file mode 100644 index 00000000..e6dfb70c --- /dev/null +++ b/{PROJECT_NAME}Tests/Sources/Dummy/DummyNetworkModel.swift @@ -0,0 +1,14 @@ +// +// DummyNetworkModel.swift +// + +import Foundation + +struct DummyNetworkModel: Decodable { + + static let json = + """ + {"message": "Hello"} + """ + let message: String +} diff --git a/{PROJECT_NAME}Tests/Sources/Dummy/DummyRequestConfiguration.swift b/{PROJECT_NAME}Tests/Sources/Dummy/DummyRequestConfiguration.swift new file mode 100644 index 00000000..1359b72b --- /dev/null +++ b/{PROJECT_NAME}Tests/Sources/Dummy/DummyRequestConfiguration.swift @@ -0,0 +1,29 @@ +// +// DummyRequestConfiguration.swift +// + +import Alamofire + +@testable import {PROJECT_NAME} + +struct DummyRequestConfiguration: RequestConfiguration { + + var baseURL: String { "https://example.com" } + + var endpoint: String { "" } + + var method: Alamofire.HTTPMethod { .get } + + var encoding: Alamofire.ParameterEncoding { URLEncoding.queryString } +} + +extension DummyRequestConfiguration: RequestConfigurationStubable { + + var sampleData: Data { + DummyNetworkModel.json.data(using: .utf8) ?? Data() + } + + var path: String { + (try? url.asURL().path).string + } +} diff --git a/{PROJECT_NAME}Tests/Sources/Specs/Data/NetworkAPI/NetworkAPISpec.swift b/{PROJECT_NAME}Tests/Sources/Specs/Data/NetworkAPI/NetworkAPISpec.swift new file mode 100644 index 00000000..c26bbdd0 --- /dev/null +++ b/{PROJECT_NAME}Tests/Sources/Specs/Data/NetworkAPI/NetworkAPISpec.swift @@ -0,0 +1,64 @@ +// +// NetworkAPISpec.swift +// + +import Nimble +import Quick + +@testable import {PROJECT_NAME} + +final class NetworkAPISpec: QuickSpec { + + override func spec() { + + describe("a NetworkAPI") { + + var networkAPI: NetworkAPI! + var requestConfiguration: DummyRequestConfiguration! + + describe("its performRequest") { + + beforeEach { + requestConfiguration = DummyRequestConfiguration() + } + + afterEach { + NetworkStubber.removeAllStubs() + } + + context("when network returns value") { + + beforeEach { + NetworkStubber.stub(requestConfiguration) + networkAPI = NetworkAPI() + } + + it("returns message as Hello") { + let response = try await networkAPI.performRequest( + requestConfiguration, + for: DummyNetworkModel.self + ) + expect(response.message) == "Hello" + } + } + + context("when network returns error") { + + beforeEach { + NetworkStubber.stub(requestConfiguration, data: Data(), statusCode: 400) + networkAPI = NetworkAPI() + } + + it("throws error") { + await expect { + try await networkAPI.performRequest( + requestConfiguration, + for: DummyNetworkModel.self + ) + }.to(throwError()) + } + } + } + } + } +} diff --git a/{PROJECT_NAME}Tests/Sources/Utilities/.gitkeep b/{PROJECT_NAME}Tests/Sources/Utilities/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/{PROJECT_NAME}Tests/Sources/Utilities/NetworkStubber.swift b/{PROJECT_NAME}Tests/Sources/Utilities/NetworkStubber.swift new file mode 100644 index 00000000..85ccb721 --- /dev/null +++ b/{PROJECT_NAME}Tests/Sources/Utilities/NetworkStubber.swift @@ -0,0 +1,32 @@ +// +// NetworkStubber.swift +// + +import OHHTTPStubs + +protocol RequestConfigurationStubable { + + var sampleData: Data { get } + var path: String { get } +} + +enum NetworkStubber { + + static func removeAllStubs() { + HTTPStubs.removeAllStubs() + } + + static func stub( + _ request: RequestConfigurationStubable, + data: Data? = nil, + statusCode: Int32 = 200 + ) { + OHHTTPStubs.stub(condition: isPath(request.path)) { _ in + HTTPStubsResponse( + data: data ?? request.sampleData, + statusCode: statusCode, + headers: nil + ) + } + } +} From d917c5796ff5adc94053eff2e7c7ba349e92b346 Mon Sep 17 00:00:00 2001 From: Bliss Pisit Wetcha Date: Thu, 5 Oct 2023 09:44:39 +0700 Subject: [PATCH 15/22] [#508] Update Quick and Nimble to support Async --- Tuist/Interfaces/UIKit/Project/Podfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Tuist/Interfaces/UIKit/Project/Podfile b/Tuist/Interfaces/UIKit/Project/Podfile index d5bdbf53..ab75d34b 100644 --- a/Tuist/Interfaces/UIKit/Project/Podfile +++ b/Tuist/Interfaces/UIKit/Project/Podfile @@ -1,10 +1,10 @@ -platform :ios, '11.0' +platform :ios, '13.0' use_frameworks! inhibit_all_warnings! def testing_pods - pod 'Quick' - pod 'Nimble' + pod 'Quick', '~> 6.0' + pod 'Nimble', '~> 11.0' pod 'Sourcery' pod 'SwiftFormat/CLI' pod 'OHHTTPStubs/Swift', :configurations => ['Debug Staging', 'Debug Production'] From 7151ff8ab310caff09bd9c88b74fffb3d4b1c95d Mon Sep 17 00:00:00 2001 From: Bliss Pisit Wetcha Date: Fri, 6 Oct 2023 11:10:32 +0700 Subject: [PATCH 16/22] [#508] Add folder for Data layer Dummy --- .../Sources/Dummy/{ => Data}/DummyNetworkModel.swift | 0 .../Sources/Dummy/{ => Data}/DummyRequestConfiguration.swift | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {PROJECT_NAME}Tests/Sources/Dummy/{ => Data}/DummyNetworkModel.swift (100%) rename {PROJECT_NAME}Tests/Sources/Dummy/{ => Data}/DummyRequestConfiguration.swift (100%) diff --git a/{PROJECT_NAME}Tests/Sources/Dummy/DummyNetworkModel.swift b/{PROJECT_NAME}Tests/Sources/Dummy/Data/DummyNetworkModel.swift similarity index 100% rename from {PROJECT_NAME}Tests/Sources/Dummy/DummyNetworkModel.swift rename to {PROJECT_NAME}Tests/Sources/Dummy/Data/DummyNetworkModel.swift diff --git a/{PROJECT_NAME}Tests/Sources/Dummy/DummyRequestConfiguration.swift b/{PROJECT_NAME}Tests/Sources/Dummy/Data/DummyRequestConfiguration.swift similarity index 100% rename from {PROJECT_NAME}Tests/Sources/Dummy/DummyRequestConfiguration.swift rename to {PROJECT_NAME}Tests/Sources/Dummy/Data/DummyRequestConfiguration.swift From be01e392a39add05c1e72666813e47be71c9a611 Mon Sep 17 00:00:00 2001 From: Bliss Pisit Wetcha Date: Fri, 6 Oct 2023 11:17:47 +0700 Subject: [PATCH 17/22] [#508] Fix build Rx --- Tuist/Interfaces/UIKit/Project/.sourcery.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/Tuist/Interfaces/UIKit/Project/.sourcery.yml b/Tuist/Interfaces/UIKit/Project/.sourcery.yml index 29469316..492262a4 100644 --- a/Tuist/Interfaces/UIKit/Project/.sourcery.yml +++ b/Tuist/Interfaces/UIKit/Project/.sourcery.yml @@ -7,6 +7,3 @@ output: args: autoMockableTestableImports: - {PROJECT_NAME} - autoMockableImports: - - RxSwift - - RxCocoa From fa5826a270713c102337cc6ccd813df95945163f Mon Sep 17 00:00:00 2001 From: Bliss Pisit Wetcha Date: Fri, 6 Oct 2023 15:41:38 +0700 Subject: [PATCH 18/22] [#530] Fix build --- Gemfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Gemfile b/Gemfile index 2b20351d..1b8283e2 100644 --- a/Gemfile +++ b/Gemfile @@ -9,6 +9,8 @@ gem "danger-swiftlint" gem "danger-xcode_summary" gem 'danger-swiftformat' gem 'danger-xcov' +# Fix issue with Cocoapods 13.0 when activesupport is 7.1.0 +gem 'activesupport', '~> 7.0.0', '>= 7.0.8' plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile') eval_gemfile(plugins_path) if File.exist?(plugins_path) From ed8c984ed685cc708c628937bd2c66e318b3745e Mon Sep 17 00:00:00 2001 From: Bliss Pisit Wetcha Date: Thu, 5 Oct 2023 12:14:37 +0700 Subject: [PATCH 19/22] [#482] Update Quick and Nimble with better support for async --- Tuist/Interfaces/SwiftUI/Project/Podfile | 4 ++-- Tuist/Interfaces/UIKit/Project/Podfile | 4 ++-- .../Sources/Specs/Application/ApplicationSpec.swift | 6 +++--- .../Sources/Utilities/KIFSpec.swift | 10 ++++++++++ .../Sources/Specs/Data/NetworkAPI/NetworkAPISpec.swift | 2 +- .../Extensions/Foundation/OptionalUnwrapSpec.swift | 2 +- 6 files changed, 19 insertions(+), 9 deletions(-) create mode 100644 {PROJECT_NAME}KIFUITests/Sources/Utilities/KIFSpec.swift diff --git a/Tuist/Interfaces/SwiftUI/Project/Podfile b/Tuist/Interfaces/SwiftUI/Project/Podfile index 7a0d2eed..5c5a1e9a 100644 --- a/Tuist/Interfaces/SwiftUI/Project/Podfile +++ b/Tuist/Interfaces/SwiftUI/Project/Podfile @@ -3,8 +3,8 @@ use_frameworks! inhibit_all_warnings! def testing_pods - pod 'Quick', '~> 6.0' - pod 'Nimble', '~> 11.0' + pod 'Quick', '~> 7.0' + pod 'Nimble', '~> 12.0' pod 'Sourcery' pod 'SwiftFormat/CLI' pod 'OHHTTPStubs/Swift', :configurations => ['Debug Staging', 'Debug Production'] diff --git a/Tuist/Interfaces/UIKit/Project/Podfile b/Tuist/Interfaces/UIKit/Project/Podfile index ab75d34b..1d90e584 100644 --- a/Tuist/Interfaces/UIKit/Project/Podfile +++ b/Tuist/Interfaces/UIKit/Project/Podfile @@ -3,8 +3,8 @@ use_frameworks! inhibit_all_warnings! def testing_pods - pod 'Quick', '~> 6.0' - pod 'Nimble', '~> 11.0' + pod 'Quick', '~> 7.0' + pod 'Nimble', '~> 12.0' pod 'Sourcery' pod 'SwiftFormat/CLI' pod 'OHHTTPStubs/Swift', :configurations => ['Debug Staging', 'Debug Production'] diff --git a/{PROJECT_NAME}KIFUITests/Sources/Specs/Application/ApplicationSpec.swift b/{PROJECT_NAME}KIFUITests/Sources/Specs/Application/ApplicationSpec.swift index 9380ba9f..238a4b10 100644 --- a/{PROJECT_NAME}KIFUITests/Sources/Specs/Application/ApplicationSpec.swift +++ b/{PROJECT_NAME}KIFUITests/Sources/Specs/Application/ApplicationSpec.swift @@ -6,9 +6,9 @@ import Foundation import Nimble import Quick -final class ApplicationSpec: QuickSpec { +final class ApplicationSpec: KIFSpec { - override func spec() { + override class func spec() { describe("a {PROJECT_NAME} screen") { @@ -23,7 +23,7 @@ final class ApplicationSpec: QuickSpec { context("when opens") { it("shows its UI components") { - self.tester().waitForView(withAccessibilityLabel: "Hello, world!") + tester().waitForView(withAccessibilityLabel: "Hello, world!") } } } diff --git a/{PROJECT_NAME}KIFUITests/Sources/Utilities/KIFSpec.swift b/{PROJECT_NAME}KIFUITests/Sources/Utilities/KIFSpec.swift new file mode 100644 index 00000000..15b2e17a --- /dev/null +++ b/{PROJECT_NAME}KIFUITests/Sources/Utilities/KIFSpec.swift @@ -0,0 +1,10 @@ +// +// KIFSpec.swift +// + +import Quick + +class KIFSpec: QuickSpec { + + static let kifDelegate = XCTestCase() +} diff --git a/{PROJECT_NAME}Tests/Sources/Specs/Data/NetworkAPI/NetworkAPISpec.swift b/{PROJECT_NAME}Tests/Sources/Specs/Data/NetworkAPI/NetworkAPISpec.swift index c26bbdd0..1795c9d9 100644 --- a/{PROJECT_NAME}Tests/Sources/Specs/Data/NetworkAPI/NetworkAPISpec.swift +++ b/{PROJECT_NAME}Tests/Sources/Specs/Data/NetworkAPI/NetworkAPISpec.swift @@ -9,7 +9,7 @@ import Quick final class NetworkAPISpec: QuickSpec { - override func spec() { + override class func spec() { describe("a NetworkAPI") { diff --git a/{PROJECT_NAME}Tests/Sources/Specs/Supports/Extensions/Foundation/OptionalUnwrapSpec.swift b/{PROJECT_NAME}Tests/Sources/Specs/Supports/Extensions/Foundation/OptionalUnwrapSpec.swift index c6952037..71d436f7 100644 --- a/{PROJECT_NAME}Tests/Sources/Specs/Supports/Extensions/Foundation/OptionalUnwrapSpec.swift +++ b/{PROJECT_NAME}Tests/Sources/Specs/Supports/Extensions/Foundation/OptionalUnwrapSpec.swift @@ -9,7 +9,7 @@ import Quick final class OptionalUnwrapSpec: QuickSpec { - override func spec() { + override class func spec() { describe("an string optional") { var value: String? From d2905e6a2e96c244f98ff32f989b88916937339d Mon Sep 17 00:00:00 2001 From: Bliss Pisit Wetcha Date: Thu, 5 Oct 2023 12:22:01 +0700 Subject: [PATCH 20/22] [#482] Update KIF --- .../Sources/Utilities/KIF+Swift.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/{PROJECT_NAME}KIFUITests/Sources/Utilities/KIF+Swift.swift b/{PROJECT_NAME}KIFUITests/Sources/Utilities/KIF+Swift.swift index b7b69cd9..66696b28 100644 --- a/{PROJECT_NAME}KIFUITests/Sources/Utilities/KIF+Swift.swift +++ b/{PROJECT_NAME}KIFUITests/Sources/Utilities/KIF+Swift.swift @@ -5,13 +5,13 @@ import KIF -extension XCTestCase { +extension KIFSpec { - func tester(file: String = #file, _ line: Int = #line) -> KIFUITestActor { - return KIFUITestActor(inFile: file, atLine: line, delegate: self) + static func tester(file: String = #file, _ line: Int = #line) -> KIFUITestActor { + return KIFUITestActor(inFile: file, atLine: line, delegate: kifDelegate) } - func system(file: String = #file, _ line: Int = #line) -> KIFSystemTestActor { - return KIFSystemTestActor(inFile: file, atLine: line, delegate: self) + static func system(file: String = #file, _ line: Int = #line) -> KIFSystemTestActor { + return KIFSystemTestActor(inFile: file, atLine: line, delegate: kifDelegate) } } From 3b6e33a4a96dff1b71e39e2af62df48b780a9243 Mon Sep 17 00:00:00 2001 From: Bliss Pisit Wetcha Date: Thu, 5 Oct 2023 12:23:49 +0700 Subject: [PATCH 21/22] [#482] Update Async spec --- .../Sources/Specs/Data/NetworkAPI/NetworkAPISpec.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/{PROJECT_NAME}Tests/Sources/Specs/Data/NetworkAPI/NetworkAPISpec.swift b/{PROJECT_NAME}Tests/Sources/Specs/Data/NetworkAPI/NetworkAPISpec.swift index 1795c9d9..23e388c7 100644 --- a/{PROJECT_NAME}Tests/Sources/Specs/Data/NetworkAPI/NetworkAPISpec.swift +++ b/{PROJECT_NAME}Tests/Sources/Specs/Data/NetworkAPI/NetworkAPISpec.swift @@ -7,7 +7,7 @@ import Quick @testable import {PROJECT_NAME} -final class NetworkAPISpec: QuickSpec { +final class NetworkAPISpec: AsyncSpec { override class func spec() { From 6f4e9393781b20196c62031b0b4bf272f13e0c51 Mon Sep 17 00:00:00 2001 From: David Date: Thu, 26 Oct 2023 15:21:46 +0700 Subject: [PATCH 22/22] [487] Update swiftlint implicit_return rule --- .swiftlint.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.swiftlint.yml b/.swiftlint.yml index 4ca7db79..e7d3d235 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -106,6 +106,7 @@ implicit_return: included: - closure - getter + - function custom_rules: multiline_collection_one_per_line: