From 68d7f9388a5ae32b11a026b0586a7aab63c02fb9 Mon Sep 17 00:00:00 2001 From: Bliss Pisit Wetcha Date: Tue, 18 Jul 2023 18:21:12 +0700 Subject: [PATCH 01/16] [#494] Add SetUpiOSProject.swift. Move SetUpInterface to struct --- Scripts/Swift/Extensions/String+Utils.swift | 8 + Scripts/Swift/SetUpInterface.swift | 70 +++++--- Scripts/Swift/SetUpiOSProject.swift | 181 ++++++++++++++++++++ make.sh | 56 +----- 4 files changed, 240 insertions(+), 75 deletions(-) create mode 100644 Scripts/Swift/Extensions/String+Utils.swift create mode 100644 Scripts/Swift/SetUpiOSProject.swift diff --git a/Scripts/Swift/Extensions/String+Utils.swift b/Scripts/Swift/Extensions/String+Utils.swift new file mode 100644 index 00000000..76ccddaf --- /dev/null +++ b/Scripts/Swift/Extensions/String+Utils.swift @@ -0,0 +1,8 @@ +extension String { + + 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) + return regex.firstMatch(in: lhs, options: [], range: range) != nil + } +} diff --git a/Scripts/Swift/SetUpInterface.swift b/Scripts/Swift/SetUpInterface.swift index 44d82628..6064fbd9 100644 --- a/Scripts/Swift/SetUpInterface.swift +++ b/Scripts/Swift/SetUpInterface.swift @@ -1,25 +1,47 @@ -#!/usr/bin/swift - -import Foundation - -let fileManager = FileManager.default - -var interface = "UIKit" - -switch CommandLine.arguments[1] { -case "SwiftUI", "s", "S": - print("=> 🦅 Setting up SwiftUI") - interface = "SwiftUI" - let swiftUIAppDirectory = "tuist/Interfaces/SwiftUI/Sources/Application" - fileManager.rename( - file: "\(swiftUIAppDirectory)/App.swift", - to: "\(swiftUIAppDirectory)/\(CommandLine.arguments[2])App.swift" - ) -default: - print("=> 🦉 Setting up UIKit") - interface = "UIKit" -} -fileManager.moveFiles(in: "tuist/Interfaces/\(interface)/Project", to: "") -fileManager.moveFiles(in: "tuist/Interfaces/\(interface)/Sources", to: "{PROJECT_NAME}/Sources") -fileManager.removeItems(in: "tuist/Interfaces") +struct SetUpInterface { + + enum Interface { + + case swiftUI, uiKit + + init?(_ name: String) { + switch name.lowercased() { + case "s", "swiftui": + self = .swiftUI + case "u", "uikit": + self = .uiKit + default: return nil + } + } + + var folderName: String { + switch self { + case .swiftUI: return "SwiftUI" + case .uiKit: return "UIKit" + } + } + } + + func perform(_ interface: Interface, _ projectName: String) { + let fileManager = FileManager.default + + switch interface { + case .swiftUI: + print("=> 🦅 Setting up SwiftUI") + let swiftUIAppDirectory = "tuist/Interfaces/SwiftUI/Sources/Application" + fileManager.rename( + file: "\(swiftUIAppDirectory)/App.swift", + to: "\(swiftUIAppDirectory)/\(projectName)App.swift" + ) + case .uiKit: + print("=> 🦉 Setting up UIKit") + } + + let folderName = interface.folderName + + fileManager.moveFiles(in: "tuist/Interfaces/\(folderName)/Project", to: "") + fileManager.moveFiles(in: "tuist/Interfaces/\(folderName)/Sources", to: "TemplateApp/Sources") + fileManager.removeItems(in: "tuist/Interfaces") + } +} diff --git a/Scripts/Swift/SetUpiOSProject.swift b/Scripts/Swift/SetUpiOSProject.swift new file mode 100644 index 00000000..232903ec --- /dev/null +++ b/Scripts/Swift/SetUpiOSProject.swift @@ -0,0 +1,181 @@ +#!/usr/bin/swift + +let CONSTANT_PROJECT_NAME = "TemplateApp" +let CONSTANT_BUNDLE_PRODUCTION = "co.nimblehq.ios.templates" +let CONSTANT_BUNDLE_STAGING = "co.nimblehq.ios.templates.staging" +let CONSTANT_MINIMUM_VERSION = "" + +var bundleIdProduction = "" +var bundleIdStaging = "" +var projectName = "" +var minimumVersion = "" +var interface: SetUpInterface.Interface? + +// 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 + } +} + +func checkPackageName(_ name: String) -> Bool { + let packageNameRegex="^[a-z][a-z0-9_]*(\\.[a-z0-9_-]+)+[0-9a-z_-]$" + let valid = name ~= packageNameRegex + if !valid { + print("Please pick a valid package name with pattern {com.example.package}") + } + return valid +} + +func checkVersion(_ version: String) -> Bool { + let versionRegex="^[0-9_]+(\\.[0-9]+)+$" + let valid = version ~= versionRegex + if !valid { + print("Please pick a valid version with pattern {x.y}") + } + return valid +} + +while bundleIdProduction.isEmpty || !checkPackageName(bundleIdProduction) { + print("BUNDLE ID PRODUCTION (i.e. com.example.project):") + bundleIdProduction = readLine() ?? "" +} +while bundleIdStaging.isEmpty || !checkPackageName(bundleIdStaging) { + print("BUNDLE ID STAGING (i.e. com.example.project.staging):") + bundleIdStaging = readLine() ?? "" +} +while projectName.isEmpty { + print("PROJECT NAME (i.e. NewProject):") + projectName = readLine() ?? "" +} +while minimumVersion.isEmpty || !checkVersion(minimumVersion) { + print("iOS Minimum Version (i.e. 14.0):") + minimumVersion = readLine() ?? "14.0" +} +while interface == nil { + print("Interface [(S)wiftUI or (U)IKit]:") + interface = SetUpInterface.Interface(readLine() ?? "") +} + +// Select the Interface +SetUpInterface().perform(interface ?? .uiKit, projectName) + +print("=> 🐢 Starting init \(projectName) ...") + + +/* +# Rename files structure +echo "=> 🔎 Replacing files structure..." + + +## user define function +rename_folder(){ + local DIR=$1 + local NEW_DIR=$2 + if [ -d "$DIR" ] + then + mv ${DIR} ${NEW_DIR} + fi +} + +# Rename test folder structure +rename_folder "${CONSTANT_PROJECT_NAME}Tests" "${PROJECT_NAME_NO_SPACES}Tests" + +# Rename KIF UI Test folder structure +rename_folder "${CONSTANT_PROJECT_NAME}KIFUITests" "${PROJECT_NAME_NO_SPACES}KIFUITests" + +# Rename app folder structure +rename_folder "${CONSTANT_PROJECT_NAME}" "${PROJECT_NAME_NO_SPACES}" + +# Duplicate the env example file and rename it to env file +cp "./.env.example" "./.env" + +# Add AutoMockable.generated.swift file +mkdir -p "${PROJECT_NAME_NO_SPACES}Tests/Sources/Mocks/Sourcery" +touch "${PROJECT_NAME_NO_SPACES}Tests/Sources/Mocks/Sourcery/AutoMockable.generated.swift" + +# Add R.generated.swift file +mkdir -p "${PROJECT_NAME_NO_SPACES}/Sources/Supports/Helpers/Rswift" +touch "${PROJECT_NAME_NO_SPACES}/Sources/Supports/Helpers/Rswift/R.generated.swift" + +echo "✅ Completed" + +# Search and replace in files +echo "=> 🔎 Replacing package and package name within files..." +BUNDLE_ID_PRODUCTION_ESCAPED="${bundle_id_production//./\.}" +BUNDLE_ID_STAGING_ESCAPED="${bundle_id_staging//./\.}" +LC_ALL=C find $WORKING_DIR -type f -exec sed -i "" "s/$CONSTANT_BUNDLE_STAGING/$BUNDLE_ID_STAGING_ESCAPED/g" {} + +LC_ALL=C find $WORKING_DIR -type f -exec sed -i "" "s/$CONSTANT_BUNDLE_PRODUCTION/$BUNDLE_ID_PRODUCTION_ESCAPED/g" {} + +LC_ALL=C find $WORKING_DIR -type f -exec sed -i "" "s/$CONSTANT_PROJECT_NAME/$PROJECT_NAME_NO_SPACES/g" {} + +LC_ALL=C find $WORKING_DIR -type f -exec sed -i "" "s/$CONSTANT_MINIMUM_VERSION/$minimum_version/g" {} + +echo "✅ Completed" + +# check for tuist and install +if ! command -v tuist &> /dev/null +then + echo "Tuist could not be found" + echo "Installing tuist" + readonly TUIST_VERSION=`cat .tuist-version` + curl -Ls https://install.tuist.io | bash + tuist install ${TUIST_VERSION} +fi + +# Generate with tuist +echo "Tuist found" +tuist generate --no-open +echo "✅ Completed" + +# Install dependencies +echo "Installing gems" +bundle install + +echo "Run Arkana" +bundle exec arkana + +echo "Installing pod dependencies" +bundle exec pod install --repo-update +echo "✅ Completed" + +# Remove gitkeep files +echo "Remove gitkeep files from project" +sed -i "" "s/.*\(gitkeep\).*,//" $PROJECT_NAME_NO_SPACES.xcodeproj/project.pbxproj +echo "✅ Completed" + +# Remove Tuist files +echo "Remove tuist files" +rm -rf .tuist-version +rm -rf tuist +rm -rf Project.swift +rm -rf Workspace.swift + +# Remove script files and git/index +echo "Remove script files and git/index" +rm -rf make.sh +rm -rf .github/workflows/test_install_script.yml +rm -f .git/index +git reset + +if [[ -z "${CI}" ]]; then + rm -rf fastlane/Tests + rm -f set_up_test_testflight.sh + cat Scripts/Swift/SetUpCICDService.swift Scripts/Swift/Extensions/FileManager+Utils.swift Scripts/Swift/Helpers/SafeShell.swift > t.swift && swift t.swift && rm -rf 't.swift' + cat Scripts/Swift/SetUpDeliveryConstants.swift Scripts/Swift/Extensions/FileManager+Utils.swift Scripts/Swift/Helpers/SafeShell.swift > t.swift && swift t.swift && rm -rf 't.swift' + rm -rf Scripts +fi + + +echo "✅ Completed" + +# Done! +echo "=> 🚀 Done! App is ready to be tested 🙌" + +if [[ -z "${CI}" ]]; then + echo "=> 🛠 Opening the project." + open -a Xcode $PROJECT_NAME_NO_SPACES.xcworkspace +fi +*/ diff --git a/make.sh b/make.sh index e9162149..75b1a84d 100644 --- a/make.sh +++ b/make.sh @@ -35,10 +35,10 @@ project_name="" minimum_version="" interface="" -readonly CONSTANT_PROJECT_NAME="{PROJECT_NAME}" -readonly CONSTANT_BUNDLE_PRODUCTION="{BUNDLE_ID_PRODUCTION}" -readonly CONSTANT_BUNDLE_STAGING="{BUNDLE_ID_STAGING}" -readonly CONSTANT_MINIMUM_VERSION="{TARGET_VERSION}" +readonly CONSTANT_PROJECT_NAME="TemplateApp" +readonly CONSTANT_BUNDLE_PRODUCTION="co.nimblehq.ios.templates" +readonly CONSTANT_BUNDLE_STAGING="co.nimblehq.ios.templates.staging" +readonly CONSTANT_MINIMUM_VERSION="" while [ $# -gt 0 ] ; do case "$1" in @@ -71,53 +71,7 @@ while [ $# -gt 0 ] ; do shift done -if [ -z "$bundle_id_production" ] ; then - read -p "BUNDLE ID PRODUCTION (i.e. com.example.project):" bundle_id_production -fi - -if [ -z "$bundle_id_staging" ] ; then - read -p "BUNDLE ID STAGING (i.e. com.example.project.staging):" bundle_id_staging -fi - -if [ -z "$project_name" ] ; then - read -p "PROJECT NAME (i.e. NewProject):" project_name -fi - -if [[ -z "${CI}" ]]; then - read -p "iOS Minimum Version (i.e. 14.0):" minimum_version -fi -if [ -z "$minimum_version" ]; then - minimum_version="14.0" -fi - -if [ -z "$interface" ]; then - read -p "Interface [(S)wiftUI or (U)IKit]:" interface - if [ -z "$interface" ]; then - interface="SwiftUI" - fi -fi - -# Enforce minimum version -version_regex='^[0-9_]+(\.[0-9]+)+$' -if ! [[ $minimum_version =~ $version_regex ]]; then - echo "=> Minimum version incorrect. Reverting to default version." - minimum_version="14.0" -fi - -if [ -z "$bundle_id_production" ] || [ -z "$bundle_id_staging" ] || [ -z "$project_name" ] ; then - usage "Input cannot be blank." -fi - -# Enforce package name -regex='^[a-z][a-z0-9_]*(\.[a-z0-9_-]+)+[0-9a-z_-]$' -if ! [[ $bundle_id_production =~ $regex ]]; then - die "Invalid Package Name: $bundle_id_production (needs to follow standard pattern {com.example.package})" -fi - -# Select the Interface -cat Scripts/Swift/SetUpInterface.swift Scripts/Swift/Extensions/FileManager+Utils.swift | swift - $interface $project_name - -echo "=> 🐢 Starting init $project_name ..." +cat Scripts/Swift/SetUpiOSProject.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' # Trim spaces in APP_NAME readonly PROJECT_NAME_NO_SPACES=$(echo "$project_name" | sed "s/ //g") From 508a9df7ae1ace6697b2622eccc6aeb363c14a93 Mon Sep 17 00:00:00 2001 From: Bliss Pisit Wetcha Date: Thu, 20 Jul 2023 15:39:31 +0700 Subject: [PATCH 02/16] [#494] Add renaming to SetUpiOSProject.swift --- .../Swift/Extensions/FileManager+Utils.swift | 22 +++ Scripts/Swift/SetUpiOSProject.swift | 176 +++++++++--------- make.sh | 123 +----------- 3 files changed, 115 insertions(+), 206 deletions(-) diff --git a/Scripts/Swift/Extensions/FileManager+Utils.swift b/Scripts/Swift/Extensions/FileManager+Utils.swift index c55c4e4a..b5bcce97 100644 --- a/Scripts/Swift/Extensions/FileManager+Utils.swift +++ b/Scripts/Swift/Extensions/FileManager+Utils.swift @@ -34,6 +34,28 @@ extension FileManager { } } + func copy(file: String, to destination: String) { + let currentDirectory = currentDirectoryPath + do { + try copyItem( + atPath: "\(currentDirectory)/\(file)", + toPath:"\(currentDirectory)/\(destination)" + ) + } catch { + print("Error \(error)") + } + } + + func createFile(name: String, at directory: String) { + let currentDirectory = currentDirectoryPath + do { + try createDirectory(atPath: "\(currentDirectory)/\(directory)", withIntermediateDirectories: true, attributes: nil) + } catch { + print("Error \(error)") + } + createFile(atPath: "\(currentDirectory)\(directory)\(name)", contents: nil) + } + func removeItems(in directory: String) { let currentDirectory = currentDirectoryPath do { diff --git a/Scripts/Swift/SetUpiOSProject.swift b/Scripts/Swift/SetUpiOSProject.swift index 232903ec..53571f89 100644 --- a/Scripts/Swift/SetUpiOSProject.swift +++ b/Scripts/Swift/SetUpiOSProject.swift @@ -1,9 +1,9 @@ #!/usr/bin/swift -let CONSTANT_PROJECT_NAME = "TemplateApp" -let CONSTANT_BUNDLE_PRODUCTION = "co.nimblehq.ios.templates" -let CONSTANT_BUNDLE_STAGING = "co.nimblehq.ios.templates.staging" -let CONSTANT_MINIMUM_VERSION = "" +let CONSTANT_PROJECT_NAME = "{PROJECT_NAME}" +let CONSTANT_BUNDLE_PRODUCTION = "{BUNDLE_ID_PRODUCTION}" +let CONSTANT_BUNDLE_STAGING = "{BUNDLE_ID_STAGING}" +let CONSTANT_MINIMUM_VERSION = "{TARGET_VERSION}" var bundleIdProduction = "" var bundleIdStaging = "" @@ -11,6 +11,8 @@ var projectName = "" var minimumVersion = "" var interface: SetUpInterface.Interface? +var isCI = !(ProcessInfo.processInfo.environment["CI"] ?? "").isEmpty + // TODO: Should be replaced with ArgumentParser instead of command line for (index, argument) in CommandLine.arguments.enumerated() { switch index { @@ -23,6 +25,10 @@ for (index, argument) in CommandLine.arguments.enumerated() { } } +if isCI { + minimumVersion = "14.0" +} + func checkPackageName(_ name: String) -> Bool { let packageNameRegex="^[a-z][a-z0-9_]*(\\.[a-z0-9_-]+)+[0-9a-z_-]$" let valid = name ~= packageNameRegex @@ -61,104 +67,98 @@ while interface == nil { print("Interface [(S)wiftUI or (U)IKit]:") interface = SetUpInterface.Interface(readLine() ?? "") } - -// Select the Interface -SetUpInterface().perform(interface ?? .uiKit, projectName) +let projectNameNoSpace = projectName.trimmingCharacters(in: .whitespacesAndNewlines) print("=> 🐢 Starting init \(projectName) ...") +print("=> 🔎 Replacing files structure...") -/* -# Rename files structure -echo "=> 🔎 Replacing files structure..." - - -## user define function -rename_folder(){ - local DIR=$1 - local NEW_DIR=$2 - if [ -d "$DIR" ] - then - mv ${DIR} ${NEW_DIR} - fi -} - -# Rename test folder structure -rename_folder "${CONSTANT_PROJECT_NAME}Tests" "${PROJECT_NAME_NO_SPACES}Tests" +let fileManager = FileManager.default -# Rename KIF UI Test folder structure -rename_folder "${CONSTANT_PROJECT_NAME}KIFUITests" "${PROJECT_NAME_NO_SPACES}KIFUITests" +// Rename test folder structure +fileManager.rename(file: "\(CONSTANT_PROJECT_NAME)Tests", to: "\(projectNameNoSpace)Tests") -# Rename app folder structure -rename_folder "${CONSTANT_PROJECT_NAME}" "${PROJECT_NAME_NO_SPACES}" +// Rename KIF UI Test folder structure +fileManager.rename(file: "\(CONSTANT_PROJECT_NAME)KIFUITests", to: "\(projectNameNoSpace)KIFUITests") -# Duplicate the env example file and rename it to env file -cp "./.env.example" "./.env" +// Rename app folder structure +fileManager.rename(file: "\(CONSTANT_PROJECT_NAME)", to: "\(projectNameNoSpace)") -# Add AutoMockable.generated.swift file -mkdir -p "${PROJECT_NAME_NO_SPACES}Tests/Sources/Mocks/Sourcery" -touch "${PROJECT_NAME_NO_SPACES}Tests/Sources/Mocks/Sourcery/AutoMockable.generated.swift" +// Duplicate the env example file to env file +fileManager.copy(file: ".env.example", to: ".env") -# Add R.generated.swift file -mkdir -p "${PROJECT_NAME_NO_SPACES}/Sources/Supports/Helpers/Rswift" -touch "${PROJECT_NAME_NO_SPACES}/Sources/Supports/Helpers/Rswift/R.generated.swift" +// Add AutoMockable.generated.swift file +fileManager.createFile(name: "AutoMockable.generated.swift", at: "\(projectNameNoSpace)Tests/Sources/Mocks/Sourcery") -echo "✅ Completed" - -# Search and replace in files -echo "=> 🔎 Replacing package and package name within files..." -BUNDLE_ID_PRODUCTION_ESCAPED="${bundle_id_production//./\.}" -BUNDLE_ID_STAGING_ESCAPED="${bundle_id_staging//./\.}" -LC_ALL=C find $WORKING_DIR -type f -exec sed -i "" "s/$CONSTANT_BUNDLE_STAGING/$BUNDLE_ID_STAGING_ESCAPED/g" {} + -LC_ALL=C find $WORKING_DIR -type f -exec sed -i "" "s/$CONSTANT_BUNDLE_PRODUCTION/$BUNDLE_ID_PRODUCTION_ESCAPED/g" {} + -LC_ALL=C find $WORKING_DIR -type f -exec sed -i "" "s/$CONSTANT_PROJECT_NAME/$PROJECT_NAME_NO_SPACES/g" {} + -LC_ALL=C find $WORKING_DIR -type f -exec sed -i "" "s/$CONSTANT_MINIMUM_VERSION/$minimum_version/g" {} + -echo "✅ Completed" +// Add AutoMockable.generated.swift file +fileManager.createFile(name: "R.generated.swift", at: "\(projectNameNoSpace)/Sources/Supports/Helpers/Rswift") -# check for tuist and install -if ! command -v tuist &> /dev/null -then - echo "Tuist could not be found" - echo "Installing tuist" - readonly TUIST_VERSION=`cat .tuist-version` - curl -Ls https://install.tuist.io | bash - tuist install ${TUIST_VERSION} -fi - -# Generate with tuist -echo "Tuist found" -tuist generate --no-open -echo "✅ Completed" - -# Install dependencies -echo "Installing gems" -bundle install - -echo "Run Arkana" -bundle exec arkana +// Select the Interface +SetUpInterface().perform(interface ?? .uiKit, projectName) -echo "Installing pod dependencies" -bundle exec pod install --repo-update -echo "✅ Completed" +print("✅ Completed") + +// Search and replace in files + +print("=> 🔎 Replacing package and package name within files...") + +try fileManager.replaceAllOccurrences(of: CONSTANT_BUNDLE_STAGING, to: bundleIdStaging) +try fileManager.replaceAllOccurrences(of: CONSTANT_BUNDLE_PRODUCTION, to: bundleIdProduction) +try fileManager.replaceAllOccurrences(of: CONSTANT_PROJECT_NAME, to: projectNameNoSpace) +try fileManager.replaceAllOccurrences(of: CONSTANT_MINIMUM_VERSION, to: minimumVersion) +print("✅ Completed") + +// check for tuist and install +let tuistLocation = try safeShell("command -v tuist") +if let tuistLocation, tuistLocation.isEmpty { + print("Tuist could not be found") + print("Installing tuist") + try safeShell( + """ + readonly TUIST_VERSION=`cat .tuist-version` + curl -Ls https://install.tuist.io | bash + tuist install ${TUIST_VERSION} + """ + ) +} -# Remove gitkeep files -echo "Remove gitkeep files from project" -sed -i "" "s/.*\(gitkeep\).*,//" $PROJECT_NAME_NO_SPACES.xcodeproj/project.pbxproj -echo "✅ Completed" +// Generate with tuist +try safeShell("tuist generate --no-open") +print("✅ Completed") + +// Install dependencies +print("Installing gems") +try safeShell("bundle install") + +// Install dependencies +print("Run Arkana") +try safeShell("bundle exec arkana") + +print("Installing pod dependencies") +try safeShell("bundle exec pod install --repo-update") +print("✅ Completed") + +// Remove gitkeep files +print("Remove gitkeep files from project") +let escapedProjectNameNoSpace = projectNameNoSpace.replacingOccurrences(of: ".", with: "\\.") +try safeShell("sed -i \"\" \"s/.*\\(gitkeep\\).*,//\" \(escapedProjectNameNoSpace).xcodeproj/project.pbxproj") +print("✅ Complete") + +// Remove Tuist files +print("Remove tuist files") +fileManager.removeItems(in: ".tuist-version") +fileManager.removeItems(in: "tuist") +fileManager.removeItems(in: "Project.swift") +fileManager.removeItems(in: "Workspace.swift") + +// Remove script files and git/index +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") -# Remove Tuist files -echo "Remove tuist files" -rm -rf .tuist-version -rm -rf tuist -rm -rf Project.swift -rm -rf Workspace.swift - -# Remove script files and git/index -echo "Remove script files and git/index" -rm -rf make.sh -rm -rf .github/workflows/test_install_script.yml -rm -f .git/index -git reset +/* if [[ -z "${CI}" ]]; then rm -rf fastlane/Tests diff --git a/make.sh b/make.sh index 75b1a84d..52748774 100644 --- a/make.sh +++ b/make.sh @@ -35,10 +35,10 @@ project_name="" minimum_version="" interface="" -readonly CONSTANT_PROJECT_NAME="TemplateApp" -readonly CONSTANT_BUNDLE_PRODUCTION="co.nimblehq.ios.templates" -readonly CONSTANT_BUNDLE_STAGING="co.nimblehq.ios.templates.staging" -readonly CONSTANT_MINIMUM_VERSION="" +readonly CONSTANT_PROJECT_NAME="{PROJECT_NAME}" +readonly CONSTANT_BUNDLE_PRODUCTION="{BUNDLE_ID_PRODUCTION}" +readonly CONSTANT_BUNDLE_STAGING="{BUNDLE_ID_STAGING}" +readonly CONSTANT_MINIMUM_VERSION="{TARGET_VERSION}" while [ $# -gt 0 ] ; do case "$1" in @@ -71,117 +71,4 @@ while [ $# -gt 0 ] ; do shift done -cat Scripts/Swift/SetUpiOSProject.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' - -# Trim spaces in APP_NAME -readonly PROJECT_NAME_NO_SPACES=$(echo "$project_name" | sed "s/ //g") - -# Rename files structure -echo "=> 🔎 Replacing files structure..." - - -## user define function -rename_folder(){ - local DIR=$1 - local NEW_DIR=$2 - if [ -d "$DIR" ] - then - mv ${DIR} ${NEW_DIR} - fi -} - -# Rename test folder structure -rename_folder "${CONSTANT_PROJECT_NAME}Tests" "${PROJECT_NAME_NO_SPACES}Tests" - -# Rename KIF UI Test folder structure -rename_folder "${CONSTANT_PROJECT_NAME}KIFUITests" "${PROJECT_NAME_NO_SPACES}KIFUITests" - -# Rename app folder structure -rename_folder "${CONSTANT_PROJECT_NAME}" "${PROJECT_NAME_NO_SPACES}" - -# Duplicate the env example file and rename it to env file -cp "./.env.example" "./.env" - -# Add AutoMockable.generated.swift file -mkdir -p "${PROJECT_NAME_NO_SPACES}Tests/Sources/Mocks/Sourcery" -touch "${PROJECT_NAME_NO_SPACES}Tests/Sources/Mocks/Sourcery/AutoMockable.generated.swift" - -# Add R.generated.swift file -mkdir -p "${PROJECT_NAME_NO_SPACES}/Sources/Supports/Helpers/Rswift" -touch "${PROJECT_NAME_NO_SPACES}/Sources/Supports/Helpers/Rswift/R.generated.swift" - -echo "✅ Completed" - -# Search and replace in files -echo "=> 🔎 Replacing package and package name within files..." -BUNDLE_ID_PRODUCTION_ESCAPED="${bundle_id_production//./\.}" -BUNDLE_ID_STAGING_ESCAPED="${bundle_id_staging//./\.}" -LC_ALL=C find $WORKING_DIR -type f -exec sed -i "" "s/$CONSTANT_BUNDLE_STAGING/$BUNDLE_ID_STAGING_ESCAPED/g" {} + -LC_ALL=C find $WORKING_DIR -type f -exec sed -i "" "s/$CONSTANT_BUNDLE_PRODUCTION/$BUNDLE_ID_PRODUCTION_ESCAPED/g" {} + -LC_ALL=C find $WORKING_DIR -type f -exec sed -i "" "s/$CONSTANT_PROJECT_NAME/$PROJECT_NAME_NO_SPACES/g" {} + -LC_ALL=C find $WORKING_DIR -type f -exec sed -i "" "s/$CONSTANT_MINIMUM_VERSION/$minimum_version/g" {} + -echo "✅ Completed" - -# check for tuist and install -if ! command -v tuist &> /dev/null -then - echo "Tuist could not be found" - echo "Installing tuist" - readonly TUIST_VERSION=`cat .tuist-version` - curl -Ls https://install.tuist.io | bash - tuist install ${TUIST_VERSION} -fi - -# Generate with tuist -echo "Tuist found" -tuist generate --no-open -echo "✅ Completed" - -# Install dependencies -echo "Installing gems" -bundle install - -echo "Run Arkana" -bundle exec arkana - -echo "Installing pod dependencies" -bundle exec pod install --repo-update -echo "✅ Completed" - -# Remove gitkeep files -echo "Remove gitkeep files from project" -sed -i "" "s/.*\(gitkeep\).*,//" $PROJECT_NAME_NO_SPACES.xcodeproj/project.pbxproj -echo "✅ Completed" - -# Remove Tuist files -echo "Remove tuist files" -rm -rf .tuist-version -rm -rf tuist -rm -rf Project.swift -rm -rf Workspace.swift - -# Remove script files and git/index -echo "Remove script files and git/index" -rm -rf make.sh -rm -rf .github/workflows/test_install_script.yml -rm -f .git/index -git reset - -if [[ -z "${CI}" ]]; then - rm -rf fastlane/Tests - rm -f set_up_test_testflight.sh - cat Scripts/Swift/SetUpCICDService.swift Scripts/Swift/Extensions/FileManager+Utils.swift Scripts/Swift/Helpers/SafeShell.swift > t.swift && swift t.swift && rm -rf 't.swift' - cat Scripts/Swift/SetUpDeliveryConstants.swift Scripts/Swift/Extensions/FileManager+Utils.swift Scripts/Swift/Helpers/SafeShell.swift > t.swift && swift t.swift && rm -rf 't.swift' - rm -rf Scripts -fi - - -echo "✅ Completed" - -# Done! -echo "=> 🚀 Done! App is ready to be tested 🙌" - -if [[ -z "${CI}" ]]; then - echo "=> 🛠 Opening the project." - open -a Xcode $PROJECT_NAME_NO_SPACES.xcworkspace -fi +cat Scripts/Swift/SetUpiOSProject.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 f9117bfb9bfe0503349b2ee3fd25aa170c0a7ef0 Mon Sep 17 00:00:00 2001 From: Bliss Pisit Wetcha Date: Thu, 20 Jul 2023 17:53:10 +0700 Subject: [PATCH 03/16] [#494] Add extra scripts to main set up --- Scripts/Swift/SetUpCICDService.swift | 89 +++--- Scripts/Swift/SetUpDeliveryConstants.swift | 31 +- Scripts/Swift/SetUpInterface.swift | 5 +- Scripts/Swift/SetUpiOSProject.swift | 347 +++++++++++---------- make.sh | 2 +- 5 files changed, 240 insertions(+), 234 deletions(-) diff --git a/Scripts/Swift/SetUpCICDService.swift b/Scripts/Swift/SetUpCICDService.swift index bc8ab07b..b94d97d4 100644 --- a/Scripts/Swift/SetUpCICDService.swift +++ b/Scripts/Swift/SetUpCICDService.swift @@ -1,50 +1,51 @@ -#!/usr/bin/swift - -import Foundation - -let fileManager = FileManager.default - -enum CICDService { - case github, bitrise, codemagic, later - - init?(_ name: String) { - switch name.lowercased() { - case "g", "github": - self = .github - case "b", "bitrise": - self = .bitrise - case "c", "codemagic": - self = .codemagic - case "l", "later": - self = .later - default: - return nil +struct SetUpCICDService { + + enum CICDService { + + case github, bitrise, codemagic, later + + init?(_ name: String) { + switch name.lowercased() { + case "g", "github": + self = .github + case "b", "bitrise": + self = .bitrise + case "c", "codemagic": + self = .codemagic + case "l", "later": + self = .later + default: + return nil + } } } -} -var service: CICDService? = nil + private let fileManager = FileManager.default -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() ?? "") -} + func perform() { + 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() ?? "") + } -switch service { -case .github: - print("Setting template for Github Actions") - fileManager.removeItems(in: "bitrise.yml") - fileManager.removeItems(in: "codemagic.yaml") -case .bitrise: - print("Setting template for Bitrise") - fileManager.removeItems(in: "codemagic.yaml") - fileManager.removeItems(in: ".github/workflows") -case .codemagic: - print("Setting template for CodeMagic") - fileManager.removeItems(in: "bitrise.yml") - fileManager.removeItems(in: ".github/workflows") -case .later, .none: - print("You can manually setup the template later.") -} + switch service { + case .github: + print("Setting template for Github Actions") + fileManager.removeItems(in: "bitrise.yml") + fileManager.removeItems(in: "codemagic.yaml") + case .bitrise: + print("Setting template for Bitrise") + fileManager.removeItems(in: "codemagic.yaml") + fileManager.removeItems(in: ".github/workflows") + case .codemagic: + print("Setting template for CodeMagic") + fileManager.removeItems(in: "bitrise.yml") + fileManager.removeItems(in: ".github/workflows") + case .later, .none: + print("You can manually setup the template later.") + } -print("✅ Completed") + print("✅ Completed") + } +} diff --git a/Scripts/Swift/SetUpDeliveryConstants.swift b/Scripts/Swift/SetUpDeliveryConstants.swift index dfaf1f43..e33e8608 100644 --- a/Scripts/Swift/SetUpDeliveryConstants.swift +++ b/Scripts/Swift/SetUpDeliveryConstants.swift @@ -1,18 +1,21 @@ -#!/usr/bin/swift +struct SetUpDeliveryConstants { -import Foundation + func perform() { + print("Do you want to set up Constants values? (Can be edited later) [Y/n]: ") -let fileManager = FileManager.default + let arg = readLine() ?? "y" -print("Do you want to set up Constants values? (Can be edited later) [Y/n]: ") - -var arg = readLine() ?? "y" - -switch arg.lowercased() { - case "y", "yes", "": - let error = try safeShell("open -a Xcode fastlane/Constants/Constant.swift") - guard let error = error, !error.isEmpty else { break } - print("Could not open Xcode. Make sure Xcode is installed and try again.\nRaw error: \(error)") - default: - print("✅ Completed. You can edit this file at 'fastlane/Constants/Constant.swift'.") + switch arg.lowercased() { + case "y", "yes": + do { + let error = try safeShell("open -a Xcode fastlane/Constants/Constant.swift") + guard let error = error, !error.isEmpty else { break } + print("Could not open Xcode. Make sure Xcode is installed and try again.\nRaw error: \(error)") + } catch { + print("Error: \(error)") + } + default: + print("✅ Completed. You can edit this file at 'fastlane/Constants/Constant.swift'.") + } + } } diff --git a/Scripts/Swift/SetUpInterface.swift b/Scripts/Swift/SetUpInterface.swift index 6064fbd9..ba40dc5e 100644 --- a/Scripts/Swift/SetUpInterface.swift +++ b/Scripts/Swift/SetUpInterface.swift @@ -1,4 +1,3 @@ - struct SetUpInterface { enum Interface { @@ -23,9 +22,9 @@ struct SetUpInterface { } } - func perform(_ interface: Interface, _ projectName: String) { - let fileManager = FileManager.default + let fileManager = FileManager.default + func perform(_ interface: Interface, _ projectName: String) { switch interface { case .swiftUI: print("=> 🦅 Setting up SwiftUI") diff --git a/Scripts/Swift/SetUpiOSProject.swift b/Scripts/Swift/SetUpiOSProject.swift index 53571f89..86dec5e5 100644 --- a/Scripts/Swift/SetUpiOSProject.swift +++ b/Scripts/Swift/SetUpiOSProject.swift @@ -1,181 +1,184 @@ #!/usr/bin/swift -let CONSTANT_PROJECT_NAME = "{PROJECT_NAME}" -let CONSTANT_BUNDLE_PRODUCTION = "{BUNDLE_ID_PRODUCTION}" -let CONSTANT_BUNDLE_STAGING = "{BUNDLE_ID_STAGING}" -let CONSTANT_MINIMUM_VERSION = "{TARGET_VERSION}" - -var bundleIdProduction = "" -var bundleIdStaging = "" -var projectName = "" -var minimumVersion = "" -var interface: SetUpInterface.Interface? - -var isCI = !(ProcessInfo.processInfo.environment["CI"] ?? "").isEmpty - -// 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 +class SetUpIOSProject { + + let CONSTANT_PROJECT_NAME = "{PROJECT_NAME}" + let CONSTANT_BUNDLE_PRODUCTION = "{BUNDLE_ID_PRODUCTION}" + let CONSTANT_BUNDLE_STAGING = "{BUNDLE_ID_STAGING}" + let CONSTANT_MINIMUM_VERSION = "{TARGET_VERSION}" + + private let fileManager = FileManager.default + + var bundleIdProduction = "" + var bundleIdStaging = "" + var projectName = "" + var minimumVersion = "" + var interface: SetUpInterface.Interface? + + var isCI = !(ProcessInfo.processInfo.environment["CI"] ?? "").isEmpty + + func perform() throws { + // 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() ?? "" + } + while bundleIdStaging.isEmpty || !checkPackageName(bundleIdStaging) { + print("BUNDLE ID STAGING (i.e. com.example.project.staging):") + bundleIdStaging = readLine() ?? "" + } + while projectName.isEmpty { + print("PROJECT NAME (i.e. NewProject):") + projectName = readLine() ?? "" + } + while minimumVersion.isEmpty || !checkVersion(minimumVersion) { + print("iOS Minimum Version (i.e. 14.0):") + minimumVersion = readLine() ?? "14.0" + } + while interface == nil { + print("Interface [(S)wiftUI or (U)IKit]:") + interface = SetUpInterface.Interface(readLine() ?? "") + } + let projectNameNoSpace = projectName.trimmingCharacters(in: .whitespacesAndNewlines) + + print("=> 🐢 Starting init \(projectName) ...") + + print("=> 🔎 Replacing files structure...") + + // Rename test folder structure + fileManager.rename(file: "\(CONSTANT_PROJECT_NAME)Tests", to: "\(projectNameNoSpace)Tests") + + // Rename KIF UI Test folder structure + fileManager.rename(file: "\(CONSTANT_PROJECT_NAME)KIFUITests", to: "\(projectNameNoSpace)KIFUITests") + + // Rename app folder structure + fileManager.rename(file: "\(CONSTANT_PROJECT_NAME)", to: "\(projectNameNoSpace)") + + // Duplicate the env example file to env file + fileManager.copy(file: ".env.example", to: ".env") + + // Add AutoMockable.generated.swift file + fileManager.createFile(name: "AutoMockable.generated.swift", at: "\(projectNameNoSpace)Tests/Sources/Mocks/Sourcery") + + // Add AutoMockable.generated.swift file + fileManager.createFile(name: "R.generated.swift", at: "\(projectNameNoSpace)/Sources/Supports/Helpers/Rswift") + + // Select the Interface + SetUpInterface().perform(interface ?? .uiKit, projectName) + + print("✅ Completed") + + // Search and replace in files + + print("=> 🔎 Replacing package and package name within files...") + + try fileManager.replaceAllOccurrences(of: CONSTANT_BUNDLE_STAGING, to: bundleIdStaging) + try fileManager.replaceAllOccurrences(of: CONSTANT_BUNDLE_PRODUCTION, to: bundleIdProduction) + try fileManager.replaceAllOccurrences(of: CONSTANT_PROJECT_NAME, to: projectNameNoSpace) + try fileManager.replaceAllOccurrences(of: CONSTANT_MINIMUM_VERSION, to: minimumVersion) + print("✅ Completed") + + // check for tuist and install + let tuistLocation = try safeShell("command -v tuist") + if let tuistLocation, tuistLocation.isEmpty { + print("Tuist could not be found") + print("Installing tuist") + try safeShell( + """ + readonly TUIST_VERSION=`cat .tuist-version` + curl -Ls https://install.tuist.io | bash + tuist install ${TUIST_VERSION} + """ + ) + } + + // Generate with tuist + try safeShell("tuist generate --no-open") + print("✅ Completed") + + // Install dependencies + print("Installing gems") + try safeShell("bundle install") + + // Install dependencies + print("Run Arkana") + try safeShell("bundle exec arkana") + + print("Installing pod dependencies") + try safeShell("bundle exec pod install --repo-update") + print("✅ Completed") + + // Remove gitkeep files + print("Remove gitkeep files from project") + let escapedProjectNameNoSpace = projectNameNoSpace.replacingOccurrences(of: ".", with: "\\.") + try safeShell("sed -i \"\" \"s/.*\\(gitkeep\\).*,//\" \(escapedProjectNameNoSpace).xcodeproj/project.pbxproj") + print("✅ Complete") + + // Remove Tuist files + print("Remove tuist files") + fileManager.removeItems(in: ".tuist-version") + fileManager.removeItems(in: "tuist") + fileManager.removeItems(in: "Project.swift") + fileManager.removeItems(in: "Workspace.swift") + + // Remove script files and git/index + 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") + + if !isCI { + SetUpCICDService().perform() + SetUpDeliveryConstants().perform() + fileManager.removeItems(in: "fastlane/Tests") + fileManager.removeItems(in: "set_up_test_testflight.sh") + fileManager.removeItems(in: "Scripts") + } + + print("✅ Completed") + + // Done! + print("=> 🚀 Done! App is ready to be tested 🙌") + + if !isCI { + print("=> 🛠 Opening the project.") + try safeShell("open -a Xcode \(projectNameNoSpace).xcworkspace") + } } -} - -if isCI { - minimumVersion = "14.0" -} -func checkPackageName(_ name: String) -> Bool { - let packageNameRegex="^[a-z][a-z0-9_]*(\\.[a-z0-9_-]+)+[0-9a-z_-]$" - let valid = name ~= packageNameRegex - if !valid { - print("Please pick a valid package name with pattern {com.example.package}") + func checkPackageName(_ name: String) -> Bool { + let packageNameRegex="^[a-z][a-z0-9_]*(\\.[a-z0-9_-]+)+[0-9a-z_-]$" + let valid = name ~= packageNameRegex + if !valid { + print("Please pick a valid package name with pattern {com.example.package}") + } + return valid } - return valid -} -func checkVersion(_ version: String) -> Bool { - let versionRegex="^[0-9_]+(\\.[0-9]+)+$" - let valid = version ~= versionRegex - if !valid { - print("Please pick a valid version with pattern {x.y}") + func checkVersion(_ version: String) -> Bool { + let versionRegex="^[0-9_]+(\\.[0-9]+)+$" + let valid = version ~= versionRegex + if !valid { + print("Please pick a valid version with pattern {x.y}") + } + return valid } - return valid -} - -while bundleIdProduction.isEmpty || !checkPackageName(bundleIdProduction) { - print("BUNDLE ID PRODUCTION (i.e. com.example.project):") - bundleIdProduction = readLine() ?? "" -} -while bundleIdStaging.isEmpty || !checkPackageName(bundleIdStaging) { - print("BUNDLE ID STAGING (i.e. com.example.project.staging):") - bundleIdStaging = readLine() ?? "" -} -while projectName.isEmpty { - print("PROJECT NAME (i.e. NewProject):") - projectName = readLine() ?? "" -} -while minimumVersion.isEmpty || !checkVersion(minimumVersion) { - print("iOS Minimum Version (i.e. 14.0):") - minimumVersion = readLine() ?? "14.0" -} -while interface == nil { - print("Interface [(S)wiftUI or (U)IKit]:") - interface = SetUpInterface.Interface(readLine() ?? "") -} -let projectNameNoSpace = projectName.trimmingCharacters(in: .whitespacesAndNewlines) - -print("=> 🐢 Starting init \(projectName) ...") - -print("=> 🔎 Replacing files structure...") - -let fileManager = FileManager.default - -// Rename test folder structure -fileManager.rename(file: "\(CONSTANT_PROJECT_NAME)Tests", to: "\(projectNameNoSpace)Tests") - -// Rename KIF UI Test folder structure -fileManager.rename(file: "\(CONSTANT_PROJECT_NAME)KIFUITests", to: "\(projectNameNoSpace)KIFUITests") - -// Rename app folder structure -fileManager.rename(file: "\(CONSTANT_PROJECT_NAME)", to: "\(projectNameNoSpace)") - -// Duplicate the env example file to env file -fileManager.copy(file: ".env.example", to: ".env") - -// Add AutoMockable.generated.swift file -fileManager.createFile(name: "AutoMockable.generated.swift", at: "\(projectNameNoSpace)Tests/Sources/Mocks/Sourcery") - -// Add AutoMockable.generated.swift file -fileManager.createFile(name: "R.generated.swift", at: "\(projectNameNoSpace)/Sources/Supports/Helpers/Rswift") - -// Select the Interface -SetUpInterface().perform(interface ?? .uiKit, projectName) - -print("✅ Completed") - -// Search and replace in files - -print("=> 🔎 Replacing package and package name within files...") - -try fileManager.replaceAllOccurrences(of: CONSTANT_BUNDLE_STAGING, to: bundleIdStaging) -try fileManager.replaceAllOccurrences(of: CONSTANT_BUNDLE_PRODUCTION, to: bundleIdProduction) -try fileManager.replaceAllOccurrences(of: CONSTANT_PROJECT_NAME, to: projectNameNoSpace) -try fileManager.replaceAllOccurrences(of: CONSTANT_MINIMUM_VERSION, to: minimumVersion) -print("✅ Completed") - -// check for tuist and install -let tuistLocation = try safeShell("command -v tuist") -if let tuistLocation, tuistLocation.isEmpty { - print("Tuist could not be found") - print("Installing tuist") - try safeShell( - """ - readonly TUIST_VERSION=`cat .tuist-version` - curl -Ls https://install.tuist.io | bash - tuist install ${TUIST_VERSION} - """ - ) } -// Generate with tuist -try safeShell("tuist generate --no-open") -print("✅ Completed") - -// Install dependencies -print("Installing gems") -try safeShell("bundle install") - -// Install dependencies -print("Run Arkana") -try safeShell("bundle exec arkana") - -print("Installing pod dependencies") -try safeShell("bundle exec pod install --repo-update") -print("✅ Completed") - -// Remove gitkeep files -print("Remove gitkeep files from project") -let escapedProjectNameNoSpace = projectNameNoSpace.replacingOccurrences(of: ".", with: "\\.") -try safeShell("sed -i \"\" \"s/.*\\(gitkeep\\).*,//\" \(escapedProjectNameNoSpace).xcodeproj/project.pbxproj") -print("✅ Complete") - -// Remove Tuist files -print("Remove tuist files") -fileManager.removeItems(in: ".tuist-version") -fileManager.removeItems(in: "tuist") -fileManager.removeItems(in: "Project.swift") -fileManager.removeItems(in: "Workspace.swift") - -// Remove script files and git/index -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") - -/* - -if [[ -z "${CI}" ]]; then - rm -rf fastlane/Tests - rm -f set_up_test_testflight.sh - cat Scripts/Swift/SetUpCICDService.swift Scripts/Swift/Extensions/FileManager+Utils.swift Scripts/Swift/Helpers/SafeShell.swift > t.swift && swift t.swift && rm -rf 't.swift' - cat Scripts/Swift/SetUpDeliveryConstants.swift Scripts/Swift/Extensions/FileManager+Utils.swift Scripts/Swift/Helpers/SafeShell.swift > t.swift && swift t.swift && rm -rf 't.swift' - rm -rf Scripts -fi - - -echo "✅ Completed" - -# Done! -echo "=> 🚀 Done! App is ready to be tested 🙌" - -if [[ -z "${CI}" ]]; then - echo "=> 🛠 Opening the project." - open -a Xcode $PROJECT_NAME_NO_SPACES.xcworkspace -fi -*/ +try SetUpIOSProject().perform() diff --git a/make.sh b/make.sh index 52748774..f97fc12f 100644 --- a/make.sh +++ b/make.sh @@ -71,4 +71,4 @@ while [ $# -gt 0 ] ; do shift done -cat Scripts/Swift/SetUpiOSProject.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' +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 20759d8fc96f11fa12b7bb4393994d5e7f905635 Mon Sep 17 00:00:00 2001 From: Bliss Pisit Wetcha Date: Fri, 21 Jul 2023 12:08:27 +0700 Subject: [PATCH 04/16] [#494] Refactor funcs --- .../Swift/Extensions/FileManager+Utils.swift | 2 +- Scripts/Swift/SetUpInterface.swift | 2 +- Scripts/Swift/SetUpiOSProject.swift | 105 ++++++++++-------- make.sh | 5 - 4 files changed, 60 insertions(+), 54 deletions(-) diff --git a/Scripts/Swift/Extensions/FileManager+Utils.swift b/Scripts/Swift/Extensions/FileManager+Utils.swift index b5bcce97..db9ea36f 100644 --- a/Scripts/Swift/Extensions/FileManager+Utils.swift +++ b/Scripts/Swift/Extensions/FileManager+Utils.swift @@ -85,7 +85,7 @@ extension FileManager { if let enumerator = enumerator( at: url, includingPropertiesForKeys: [.isRegularFileKey], - options: [.skipsHiddenFiles, .skipsPackageDescendants] + options: [.skipsPackageDescendants] ) { for case let fileURL as URL in enumerator { let fileAttributes = try? fileURL.resourceValues(forKeys:[.isRegularFileKey]) diff --git a/Scripts/Swift/SetUpInterface.swift b/Scripts/Swift/SetUpInterface.swift index ba40dc5e..f34d42b8 100644 --- a/Scripts/Swift/SetUpInterface.swift +++ b/Scripts/Swift/SetUpInterface.swift @@ -22,7 +22,7 @@ struct SetUpInterface { } } - let fileManager = FileManager.default + private let fileManager = FileManager.default func perform(_ interface: Interface, _ projectName: String) { switch interface { diff --git a/Scripts/Swift/SetUpiOSProject.swift b/Scripts/Swift/SetUpiOSProject.swift index 86dec5e5..e297aa3c 100644 --- a/Scripts/Swift/SetUpiOSProject.swift +++ b/Scripts/Swift/SetUpiOSProject.swift @@ -2,22 +2,38 @@ class SetUpIOSProject { - let CONSTANT_PROJECT_NAME = "{PROJECT_NAME}" - let CONSTANT_BUNDLE_PRODUCTION = "{BUNDLE_ID_PRODUCTION}" - let CONSTANT_BUNDLE_STAGING = "{BUNDLE_ID_STAGING}" - let CONSTANT_MINIMUM_VERSION = "{TARGET_VERSION}" - + private let CONSTANT_PROJECT_NAME = "{PROJECT_NAME}" + private let CONSTANT_BUNDLE_PRODUCTION = "{BUNDLE_ID_PRODUCTION}" + private let CONSTANT_BUNDLE_STAGING = "{BUNDLE_ID_STAGING}" + private let CONSTANT_MINIMUM_VERSION = "{TARGET_VERSION}" private let fileManager = FileManager.default - var bundleIdProduction = "" - var bundleIdStaging = "" - var projectName = "" - var minimumVersion = "" - var interface: SetUpInterface.Interface? + private var bundleIdProduction = "" + private var bundleIdStaging = "" + private var projectName = "" + private var minimumVersion = "" + private var interface: SetUpInterface.Interface? + private var projectNameNoSpace: String { projectName.trimmingCharacters(in: .whitespacesAndNewlines) } + private var isCI = !(ProcessInfo.processInfo.environment["CI"] ?? "").isEmpty + + func perform() { + readArguments() + print("=> 🐢 Starting init \(projectName) ...") + replaceFileStructure() + createPlaceholderFiles() + SetUpInterface().perform(interface ?? .uiKit, projectName) + try? replaceTextInFiles() + try? runTuist() + try? installDependencies() + try? removeGitkeepFromXcodeProject() + try? removeTemplateFiles() + setUpCICD() - var isCI = !(ProcessInfo.processInfo.environment["CI"] ?? "").isEmpty + print("=> 🚀 Done! App is ready to be tested 🙌") + try? openProject() + } - func perform() throws { + private func readArguments() { // TODO: Should be replaced with ArgumentParser instead of command line for (index, argument) in CommandLine.arguments.enumerated() { switch index { @@ -48,27 +64,23 @@ class SetUpIOSProject { } while minimumVersion.isEmpty || !checkVersion(minimumVersion) { print("iOS Minimum Version (i.e. 14.0):") - minimumVersion = readLine() ?? "14.0" + let version = readLine() ?? "" + minimumVersion = !version.isEmpty ? version : "14.0" } while interface == nil { print("Interface [(S)wiftUI or (U)IKit]:") interface = SetUpInterface.Interface(readLine() ?? "") } - let projectNameNoSpace = projectName.trimmingCharacters(in: .whitespacesAndNewlines) - - print("=> 🐢 Starting init \(projectName) ...") + } + private func replaceFileStructure() { print("=> 🔎 Replacing files structure...") - - // Rename test folder structure fileManager.rename(file: "\(CONSTANT_PROJECT_NAME)Tests", to: "\(projectNameNoSpace)Tests") - - // Rename KIF UI Test folder structure fileManager.rename(file: "\(CONSTANT_PROJECT_NAME)KIFUITests", to: "\(projectNameNoSpace)KIFUITests") - - // Rename app folder structure fileManager.rename(file: "\(CONSTANT_PROJECT_NAME)", to: "\(projectNameNoSpace)") + } + private func createPlaceholderFiles() { // Duplicate the env example file to env file fileManager.copy(file: ".env.example", to: ".env") @@ -77,23 +89,18 @@ class SetUpIOSProject { // Add AutoMockable.generated.swift file fileManager.createFile(name: "R.generated.swift", at: "\(projectNameNoSpace)/Sources/Supports/Helpers/Rswift") + } - // Select the Interface - SetUpInterface().perform(interface ?? .uiKit, projectName) - - print("✅ Completed") - - // Search and replace in files - + private func replaceTextInFiles() throws { print("=> 🔎 Replacing package and package name within files...") - - try fileManager.replaceAllOccurrences(of: CONSTANT_BUNDLE_STAGING, to: bundleIdStaging) - try fileManager.replaceAllOccurrences(of: CONSTANT_BUNDLE_PRODUCTION, to: bundleIdProduction) - try fileManager.replaceAllOccurrences(of: CONSTANT_PROJECT_NAME, to: projectNameNoSpace) - try fileManager.replaceAllOccurrences(of: CONSTANT_MINIMUM_VERSION, to: minimumVersion) + fileManager.replaceAllOccurrences(of: CONSTANT_BUNDLE_STAGING, to: bundleIdStaging) + fileManager.replaceAllOccurrences(of: CONSTANT_BUNDLE_PRODUCTION, to: bundleIdProduction) + fileManager.replaceAllOccurrences(of: CONSTANT_PROJECT_NAME, to: projectNameNoSpace) + fileManager.replaceAllOccurrences(of: CONSTANT_MINIMUM_VERSION, to: minimumVersion) print("✅ Completed") + } - // check for tuist and install + private func installTuistIfNeeded() throws { let tuistLocation = try safeShell("command -v tuist") if let tuistLocation, tuistLocation.isEmpty { print("Tuist could not be found") @@ -106,12 +113,15 @@ class SetUpIOSProject { """ ) } + } - // Generate with tuist + private func runTuist() throws { + try installTuistIfNeeded() try safeShell("tuist generate --no-open") print("✅ Completed") + } - // Install dependencies + private func installDependencies() throws { print("Installing gems") try safeShell("bundle install") @@ -122,27 +132,30 @@ class SetUpIOSProject { print("Installing pod dependencies") try safeShell("bundle exec pod install --repo-update") print("✅ Completed") + } - // Remove gitkeep files + private func removeGitkeepFromXcodeProject() throws { print("Remove gitkeep files from project") let escapedProjectNameNoSpace = projectNameNoSpace.replacingOccurrences(of: ".", with: "\\.") try safeShell("sed -i \"\" \"s/.*\\(gitkeep\\).*,//\" \(escapedProjectNameNoSpace).xcodeproj/project.pbxproj") print("✅ Complete") + } - // Remove Tuist files + private func removeTemplateFiles() throws { print("Remove tuist files") fileManager.removeItems(in: ".tuist-version") fileManager.removeItems(in: "tuist") fileManager.removeItems(in: "Project.swift") fileManager.removeItems(in: "Workspace.swift") - // Remove script files and git/index 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") + } + private func setUpCICD() { if !isCI { SetUpCICDService().perform() SetUpDeliveryConstants().perform() @@ -150,19 +163,17 @@ class SetUpIOSProject { fileManager.removeItems(in: "set_up_test_testflight.sh") fileManager.removeItems(in: "Scripts") } - print("✅ Completed") + } - // Done! - print("=> 🚀 Done! App is ready to be tested 🙌") - + private func openProject() throws { if !isCI { print("=> 🛠 Opening the project.") try safeShell("open -a Xcode \(projectNameNoSpace).xcworkspace") } } - func checkPackageName(_ name: String) -> Bool { + private func checkPackageName(_ name: String) -> Bool { let packageNameRegex="^[a-z][a-z0-9_]*(\\.[a-z0-9_-]+)+[0-9a-z_-]$" let valid = name ~= packageNameRegex if !valid { @@ -171,7 +182,7 @@ class SetUpIOSProject { return valid } - func checkVersion(_ version: String) -> Bool { + private func checkVersion(_ version: String) -> Bool { let versionRegex="^[0-9_]+(\\.[0-9]+)+$" let valid = version ~= versionRegex if !valid { @@ -181,4 +192,4 @@ class SetUpIOSProject { } } -try SetUpIOSProject().perform() +SetUpIOSProject().perform() diff --git a/make.sh b/make.sh index f97fc12f..b8002381 100644 --- a/make.sh +++ b/make.sh @@ -35,11 +35,6 @@ project_name="" minimum_version="" interface="" -readonly CONSTANT_PROJECT_NAME="{PROJECT_NAME}" -readonly CONSTANT_BUNDLE_PRODUCTION="{BUNDLE_ID_PRODUCTION}" -readonly CONSTANT_BUNDLE_STAGING="{BUNDLE_ID_STAGING}" -readonly CONSTANT_MINIMUM_VERSION="{TARGET_VERSION}" - while [ $# -gt 0 ] ; do case "$1" in -h|--help) From 4975f200b1444b079c4b5ec1c5aaaffa1063d6aa Mon Sep 17 00:00:00 2001 From: Bliss Pisit Wetcha Date: Tue, 8 Aug 2023 16:24:43 +0700 Subject: [PATCH 05/16] [#494] Add filter for unnessary files --- Scripts/Swift/Extensions/FileManager+Utils.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Scripts/Swift/Extensions/FileManager+Utils.swift b/Scripts/Swift/Extensions/FileManager+Utils.swift index db9ea36f..0c64d26b 100644 --- a/Scripts/Swift/Extensions/FileManager+Utils.swift +++ b/Scripts/Swift/Extensions/FileManager+Utils.swift @@ -88,6 +88,7 @@ extension FileManager { options: [.skipsPackageDescendants] ) { for case let fileURL as URL in enumerator { + guard fileURL.absoluteString ~= "([^\\/]+\\..*)" else { continue } let fileAttributes = try? fileURL.resourceValues(forKeys:[.isRegularFileKey]) guard fileAttributes?.isRegularFile ?? false else { continue } files.append(fileURL) From 6a104b78f42932b753f6c29556d53030b19f6345 Mon Sep 17 00:00:00 2001 From: Bliss Pisit Wetcha Date: Tue, 8 Aug 2023 16:55:58 +0700 Subject: [PATCH 06/16] [#494] Add filter for unnessary files --- Scripts/Swift/Extensions/FileManager+Utils.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Scripts/Swift/Extensions/FileManager+Utils.swift b/Scripts/Swift/Extensions/FileManager+Utils.swift index 0c64d26b..6fd75e11 100644 --- a/Scripts/Swift/Extensions/FileManager+Utils.swift +++ b/Scripts/Swift/Extensions/FileManager+Utils.swift @@ -87,8 +87,9 @@ extension FileManager { includingPropertiesForKeys: [.isRegularFileKey], options: [.skipsPackageDescendants] ) { + let hiddenFolderRegex = "\(directory.replacingOccurrences(of: "/", with: "\\/"))\\/\\..*\\/" for case let fileURL as URL in enumerator { - guard fileURL.absoluteString ~= "([^\\/]+\\..*)" else { continue } + guard !(fileURL.relativePath ~= hiddenFolderRegex) else { continue } let fileAttributes = try? fileURL.resourceValues(forKeys:[.isRegularFileKey]) guard fileAttributes?.isRegularFile ?? false else { continue } files.append(fileURL) From 6fab661037fcb4631a316865c3a22d9a010e8d02 Mon Sep 17 00:00:00 2001 From: Bliss Pisit Wetcha Date: Wed, 9 Aug 2023 10:06:49 +0700 Subject: [PATCH 07/16] [#494] Fix Danger import old files --- Dangerfile | 2 -- 1 file changed, 2 deletions(-) diff --git a/Dangerfile b/Dangerfile index 84cb7b02..c19fdcd9 100644 --- a/Dangerfile +++ b/Dangerfile @@ -1,7 +1,5 @@ # frozen_string_literal: true -require './fastlane/Constants/Constants' - # Warn when there is a big PR warn("This pull request is quite big (#{git.lines_of_code} lines changed), please consider splitting it into multiple pull requests.") if git.lines_of_code > 500 From cba1e35fb04b7751e967e716acc9c1a823d1eb9b Mon Sep 17 00:00:00 2001 From: David Date: Thu, 10 Aug 2023 09:52:44 +0700 Subject: [PATCH 08/16] [#492] Create SetUpTestTestFlight.swift Remove set_up_test_test_flight.sh Update workflow to use the SetUpTestTestFlight.swift --- .../test_upload_build_to_test_flight.yml | 2 +- Scripts/Swift/SetUpTestTestFlight.swift | 16 ++++++++++++++++ set_up_test_testflight.sh | 12 ------------ 3 files changed, 17 insertions(+), 13 deletions(-) create mode 100644 Scripts/Swift/SetUpTestTestFlight.swift delete mode 100644 set_up_test_testflight.sh diff --git a/.github/workflows/test_upload_build_to_test_flight.yml b/.github/workflows/test_upload_build_to_test_flight.yml index 1606fdab..387c835b 100644 --- a/.github/workflows/test_upload_build_to_test_flight.yml +++ b/.github/workflows/test_upload_build_to_test_flight.yml @@ -47,7 +47,7 @@ jobs: run: sh make.sh --bundle-id 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: sh set_up_test_testflight.sh + run: cat Scripts/Swift/SetUpTestTestFlight.swift Scripts/Swift/Extensions/FileManager+Utils.swift | swift - env: MATCH_REPO: ${{ secrets.MATCH_REPO }} API_KEY_ID: ${{ secrets.API_KEY_ID }} diff --git a/Scripts/Swift/SetUpTestTestFlight.swift b/Scripts/Swift/SetUpTestTestFlight.swift new file mode 100644 index 00000000..950c4952 --- /dev/null +++ b/Scripts/Swift/SetUpTestTestFlight.swift @@ -0,0 +1,16 @@ +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/set_up_test_testflight.sh b/set_up_test_testflight.sh deleted file mode 100644 index c1e1290e..00000000 --- a/set_up_test_testflight.sh +++ /dev/null @@ -1,12 +0,0 @@ -readonly CONSTANT_TEAM_ID="<#teamId#>" -readonly CONSTANT_API_KEY_ID="<#API_KEY_ID#>" -readonly CONSTANT_ISSUER_ID="<#ISSUER_ID#>" -readonly CONSTANT_MATCH_REPO="git@github.com:{organization}\/{repo}.git" - -readonly WORKING_DIR=$(cd -P -- "$(dirname -- "$0")" && pwd -P) -MATCH_REPO_ESCAPED=$(echo "${MATCH_REPO//\//\\\/}") - -LC_ALL=C find $WORKING_DIR -type f -exec sed -i "" "s/$CONSTANT_TEAM_ID/$TEAM_ID/g" {} + -LC_ALL=C find $WORKING_DIR -type f -exec sed -i "" "s/$CONSTANT_API_KEY_ID/$API_KEY_ID/g" {} + -LC_ALL=C find $WORKING_DIR -type f -exec sed -i "" "s/$CONSTANT_ISSUER_ID/$ISSUER_ID/g" {} + -LC_ALL=C find $WORKING_DIR -type f -exec sed -i "" "s/$CONSTANT_MATCH_REPO/$MATCH_REPO_ESCAPED/g" {} + From f94af580a6468b66977c7d2567a5e9fcd0c33ce7 Mon Sep 17 00:00:00 2001 From: Bliss Wetchaya Date: Tue, 15 Aug 2023 15:28:53 +0700 Subject: [PATCH 09/16] [#494] Fix comment --- Scripts/Swift/SetUpiOSProject.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Scripts/Swift/SetUpiOSProject.swift b/Scripts/Swift/SetUpiOSProject.swift index e297aa3c..9ad2ac5f 100644 --- a/Scripts/Swift/SetUpiOSProject.swift +++ b/Scripts/Swift/SetUpiOSProject.swift @@ -87,7 +87,7 @@ class SetUpIOSProject { // Add AutoMockable.generated.swift file fileManager.createFile(name: "AutoMockable.generated.swift", at: "\(projectNameNoSpace)Tests/Sources/Mocks/Sourcery") - // Add AutoMockable.generated.swift file + // Add R.generated.swift file. fileManager.createFile(name: "R.generated.swift", at: "\(projectNameNoSpace)/Sources/Supports/Helpers/Rswift") } From c474f72f91959e542e35bb2b596bbd448888d45b Mon Sep 17 00:00:00 2001 From: Su Nguyen T Date: Tue, 31 Jan 2023 11:47:49 +0700 Subject: [PATCH 10/16] Revert "[Chore] [#423] Update a specific name for deploying staging build to firebase workflow" --- .../{deploy_staging_firebase.yml => deploy_Firebase.yml} | 2 +- ...ploy_production_firebase.yml => deploy_Release_Firebase.yml} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename .github/workflows/{deploy_staging_firebase.yml => deploy_Firebase.yml} (98%) rename .github/workflows/{deploy_production_firebase.yml => deploy_Release_Firebase.yml} (98%) diff --git a/.github/workflows/deploy_staging_firebase.yml b/.github/workflows/deploy_Firebase.yml similarity index 98% rename from .github/workflows/deploy_staging_firebase.yml rename to .github/workflows/deploy_Firebase.yml index d5ac0b71..70f8d6a2 100644 --- a/.github/workflows/deploy_staging_firebase.yml +++ b/.github/workflows/deploy_Firebase.yml @@ -1,4 +1,4 @@ -name: Deploy Staging Build To Firebase +name: Deploy Build To Firebase # SECRETS needed: ### SSH_PRIVATE_KEY for Match Repo diff --git a/.github/workflows/deploy_production_firebase.yml b/.github/workflows/deploy_Release_Firebase.yml similarity index 98% rename from .github/workflows/deploy_production_firebase.yml rename to .github/workflows/deploy_Release_Firebase.yml index 2b9209c9..0e5798d3 100644 --- a/.github/workflows/deploy_production_firebase.yml +++ b/.github/workflows/deploy_Release_Firebase.yml @@ -1,4 +1,4 @@ -name: Deploy Production Build To Firebase +name: Deploy Release Build To Firebase # SECRETS needed: ### SSH_PRIVATE_KEY for Match Repo From 123118fa97e1a3cbe7c5db5a313ee80d3c844522 Mon Sep 17 00:00:00 2001 From: nkhanh44 Date: Wed, 11 Jan 2023 14:39:19 +0700 Subject: [PATCH 11/16] [#423] Update names for workflows and their descriptions --- ...ploy_Release_Firebase.yml => deploy_production_firebase.yml} | 2 +- .../{deploy_Firebase.yml => deploy_staging_firebase.yml} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename .github/workflows/{deploy_Release_Firebase.yml => deploy_production_firebase.yml} (98%) rename .github/workflows/{deploy_Firebase.yml => deploy_staging_firebase.yml} (98%) diff --git a/.github/workflows/deploy_Release_Firebase.yml b/.github/workflows/deploy_production_firebase.yml similarity index 98% rename from .github/workflows/deploy_Release_Firebase.yml rename to .github/workflows/deploy_production_firebase.yml index 0e5798d3..2b9209c9 100644 --- a/.github/workflows/deploy_Release_Firebase.yml +++ b/.github/workflows/deploy_production_firebase.yml @@ -1,4 +1,4 @@ -name: Deploy Release Build To Firebase +name: Deploy Production Build To Firebase # SECRETS needed: ### SSH_PRIVATE_KEY for Match Repo diff --git a/.github/workflows/deploy_Firebase.yml b/.github/workflows/deploy_staging_firebase.yml similarity index 98% rename from .github/workflows/deploy_Firebase.yml rename to .github/workflows/deploy_staging_firebase.yml index 70f8d6a2..d5ac0b71 100644 --- a/.github/workflows/deploy_Firebase.yml +++ b/.github/workflows/deploy_staging_firebase.yml @@ -1,4 +1,4 @@ -name: Deploy Build To Firebase +name: Deploy Staging Build To Firebase # SECRETS needed: ### SSH_PRIVATE_KEY for Match Repo From fa4a6812f7693fb84f424badcb84d6fa9170a875 Mon Sep 17 00:00:00 2001 From: David Date: Tue, 22 Aug 2023 09:35:22 +0700 Subject: [PATCH 12/16] [#510] Add function remove in Keychain to remove keychain in case the runner is self-hosted Add new fastlane lane removeKeychain Add remove keychain step in github action workflow Add continue-on-error: true for step remove keychain --- .github/workflows/deploy_app_store.yml | 5 +++++ .github/workflows/deploy_production_firebase.yml | 5 +++++ .github/workflows/deploy_staging_firebase.yml | 5 +++++ .github/workflows/test_upload_build_to_firebase.yml | 5 +++++ .../workflows/test_upload_build_to_test_flight.yml | 5 +++++ fastlane/Constants/Constant.swift | 1 + fastlane/Fastfile.swift | 5 +++++ fastlane/Helpers/Keychain.swift | 11 +++++++++++ 8 files changed, 42 insertions(+) diff --git a/.github/workflows/deploy_app_store.yml b/.github/workflows/deploy_app_store.yml index c065d75b..a054675e 100644 --- a/.github/workflows/deploy_app_store.yml +++ b/.github/workflows/deploy_app_store.yml @@ -97,3 +97,8 @@ jobs: ${{ env.DSYM_OUTPUT_PATH }} env: TAG_TYPE: App_Store + + - name: Remove keychain + if: ${{ always() }} + run: bundle exec fastlane removeKeychain + continue-on-error: true diff --git a/.github/workflows/deploy_production_firebase.yml b/.github/workflows/deploy_production_firebase.yml index 2b9209c9..ad71aed9 100644 --- a/.github/workflows/deploy_production_firebase.yml +++ b/.github/workflows/deploy_production_firebase.yml @@ -91,3 +91,8 @@ jobs: ${{ env.DSYM_OUTPUT_PATH }} env: TAG_TYPE: Production_Firebase + + - name: Remove keychain + if: ${{ always() }} + run: bundle exec fastlane removeKeychain + continue-on-error: true diff --git a/.github/workflows/deploy_staging_firebase.yml b/.github/workflows/deploy_staging_firebase.yml index d5ac0b71..fff0630a 100644 --- a/.github/workflows/deploy_staging_firebase.yml +++ b/.github/workflows/deploy_staging_firebase.yml @@ -97,3 +97,8 @@ jobs: ${{ env.DSYM_OUTPUT_PATH }} env: TAG_TYPE: Staging_Firebase + + - name: Remove keychain + if: ${{ always() }} + run: bundle exec fastlane removeKeychain + continue-on-error: true diff --git a/.github/workflows/test_upload_build_to_firebase.yml b/.github/workflows/test_upload_build_to_firebase.yml index 3ccdfb6c..5f8d2655 100644 --- a/.github/workflows/test_upload_build_to_firebase.yml +++ b/.github/workflows/test_upload_build_to_firebase.yml @@ -78,3 +78,8 @@ jobs: ${{ env.DSYM_OUTPUT_PATH }} env: TAG_TYPE: Staging_Firebase + + - name: Remove keychain + if: ${{ always() }} + run: bundle exec fastlane removeKeychain + continue-on-error: true diff --git a/.github/workflows/test_upload_build_to_test_flight.yml b/.github/workflows/test_upload_build_to_test_flight.yml index 387c835b..28baf490 100644 --- a/.github/workflows/test_upload_build_to_test_flight.yml +++ b/.github/workflows/test_upload_build_to_test_flight.yml @@ -70,3 +70,8 @@ jobs: ISSUER_ID: ${{ secrets.ISSUER_ID }} SKIP_FIREBASE_DSYM: "true" BUMP_APP_STORE_BUILD_NUMBER: "true" + + - name: Remove keychain + if: ${{ always() }} + run: bundle exec fastlane removeKeychain + continue-on-error: true diff --git a/fastlane/Constants/Constant.swift b/fastlane/Constants/Constant.swift index ae8ddf83..2b434f4f 100644 --- a/fastlane/Constants/Constant.swift +++ b/fastlane/Constants/Constant.swift @@ -37,6 +37,7 @@ enum Constant { static let projectPath: String = "./\(projectName).xcodeproj" static let testOutputDirectoryPath = "./fastlane/test_output" static let infoPlistPath = "\(projectName)/Configurations/Plists/Info.plist" + static let keychainPath = "~/Library/Keychains/\(keychainName)-db" // MARK: Platform diff --git a/fastlane/Fastfile.swift b/fastlane/Fastfile.swift index ccba6fe1..a5377234 100644 --- a/fastlane/Fastfile.swift +++ b/fastlane/Fastfile.swift @@ -51,6 +51,11 @@ class Fastfile: LaneFile { environment: .production ) } + + func removeKeychainLane() { + desc("Delete keychain") + Keychain.remove() + } // MARK: - Build diff --git a/fastlane/Helpers/Keychain.swift b/fastlane/Helpers/Keychain.swift index 4482c788..e06f24a3 100644 --- a/fastlane/Helpers/Keychain.swift +++ b/fastlane/Helpers/Keychain.swift @@ -6,6 +6,8 @@ // Copyright © 2022 Nimble. All rights reserved. // +import Foundation + enum Keychain { static func create() { @@ -17,4 +19,13 @@ enum Keychain { timeout: 3600 ) } + + static func remove() { + guard FileManager.default.fileExists(atPath: Constant.keychainPath) else { + return log(message: "Couldn't find the Keychain") + } + deleteKeychain( + name: .userDefined(Constant.keychainName) + ) + } } From 71ef49ac4fb55b312efe44e76088d09271ca724b Mon Sep 17 00:00:00 2001 From: David Date: Tue, 22 Aug 2023 14:05:48 +0700 Subject: [PATCH 13/16] [#510] Clean up unused code --- fastlane/Constants/Constant.swift | 1 - fastlane/Helpers/Keychain.swift | 3 --- 2 files changed, 4 deletions(-) diff --git a/fastlane/Constants/Constant.swift b/fastlane/Constants/Constant.swift index 2b434f4f..ae8ddf83 100644 --- a/fastlane/Constants/Constant.swift +++ b/fastlane/Constants/Constant.swift @@ -37,7 +37,6 @@ enum Constant { static let projectPath: String = "./\(projectName).xcodeproj" static let testOutputDirectoryPath = "./fastlane/test_output" static let infoPlistPath = "\(projectName)/Configurations/Plists/Info.plist" - static let keychainPath = "~/Library/Keychains/\(keychainName)-db" // MARK: Platform diff --git a/fastlane/Helpers/Keychain.swift b/fastlane/Helpers/Keychain.swift index e06f24a3..522a8704 100644 --- a/fastlane/Helpers/Keychain.swift +++ b/fastlane/Helpers/Keychain.swift @@ -21,9 +21,6 @@ enum Keychain { } static func remove() { - guard FileManager.default.fileExists(atPath: Constant.keychainPath) else { - return log(message: "Couldn't find the Keychain") - } deleteKeychain( name: .userDefined(Constant.keychainName) ) From c37549f18e326eb19d361a7a0277b40266f8792d Mon Sep 17 00:00:00 2001 From: David Date: Thu, 24 Aug 2023 09:51:17 +0700 Subject: [PATCH 14/16] [#510] Update keychainName default value with "{PROJECT_NAME}" to be replaced when run make.sh Update make.sh to accept minimum-version --- fastlane/Constants/Constant.swift | 2 +- make.sh | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/fastlane/Constants/Constant.swift b/fastlane/Constants/Constant.swift index ae8ddf83..a5f96dfd 100644 --- a/fastlane/Constants/Constant.swift +++ b/fastlane/Constants/Constant.swift @@ -26,7 +26,7 @@ enum Constant { static let appleStagingTeamId = "<#teamId#>" static let appleProductionUserName = "<#userName#>" static let appleProductionTeamId = "<#teamId#>" - static let keychainName = "github_action_keychain" + static let keychainName = "{PROJECT_NAME}" static let matchURL = "git@github.com:{organization}/{repo}.git" // MARK: - Path diff --git a/make.sh b/make.sh index b8002381..61a83ee0 100644 --- a/make.sh +++ b/make.sh @@ -17,13 +17,14 @@ usage() { fi cat << EOF -Usage: $PROGNAME --bundle-id [BUNDLE_ID_PRODUCTION] --bundle-id-staging [BUNDLE_ID_STAGING] --project-name [PROJECT_NAME] +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 @@ -52,6 +53,10 @@ while [ $# -gt 0 ] ; do project_name="$2" shift ;; + -m|--minimum-version) + minimum_version="$2" + shift + ;; -i|--interface) interface="$2" shift From 3e873f814110059a1c9cde09468db2691f984e8a Mon Sep 17 00:00:00 2001 From: David Date: Thu, 24 Aug 2023 09:54:55 +0700 Subject: [PATCH 15/16] [#510] Update keychainName default value --- fastlane/Constants/Constant.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastlane/Constants/Constant.swift b/fastlane/Constants/Constant.swift index a5f96dfd..eb134fb6 100644 --- a/fastlane/Constants/Constant.swift +++ b/fastlane/Constants/Constant.swift @@ -26,7 +26,7 @@ enum Constant { static let appleStagingTeamId = "<#teamId#>" static let appleProductionUserName = "<#userName#>" static let appleProductionTeamId = "<#teamId#>" - static let keychainName = "{PROJECT_NAME}" + static let keychainName = "{PROJECT_NAME}_keychain" static let matchURL = "git@github.com:{organization}/{repo}.git" // MARK: - Path From 07ef7e558cdc6d482ddbba4f1829892063327c8b Mon Sep 17 00:00:00 2001 From: Shayokh144 Date: Fri, 25 Aug 2023 14:35:59 +0700 Subject: [PATCH 16/16] [fix] [517] Fix crash by setting appropriate string --- .../UIKit/Sources/Presentation/Modules/HomeViewController.swift | 2 +- .../Sources/Specs/Application/ApplicationSpec.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Tuist/Interfaces/UIKit/Sources/Presentation/Modules/HomeViewController.swift b/Tuist/Interfaces/UIKit/Sources/Presentation/Modules/HomeViewController.swift index a9afdb16..6196825e 100644 --- a/Tuist/Interfaces/UIKit/Sources/Presentation/Modules/HomeViewController.swift +++ b/Tuist/Interfaces/UIKit/Sources/Presentation/Modules/HomeViewController.swift @@ -7,7 +7,7 @@ final class HomeViewController: UIViewController { view.backgroundColor = .white let helloLabel = UILabel() - helloLabel.text = "Hello" + helloLabel.text = "Hello, world!" helloLabel.translatesAutoresizingMaskIntoConstraints = false view.addSubview(helloLabel) diff --git a/{PROJECT_NAME}KIFUITests/Sources/Specs/Application/ApplicationSpec.swift b/{PROJECT_NAME}KIFUITests/Sources/Specs/Application/ApplicationSpec.swift index 8dded39b..9380ba9f 100644 --- a/{PROJECT_NAME}KIFUITests/Sources/Specs/Application/ApplicationSpec.swift +++ b/{PROJECT_NAME}KIFUITests/Sources/Specs/Application/ApplicationSpec.swift @@ -23,7 +23,7 @@ final class ApplicationSpec: QuickSpec { context("when opens") { it("shows its UI components") { - self.tester().waitForView(withAccessibilityLabel: "Hello") + self.tester().waitForView(withAccessibilityLabel: "Hello, world!") } } }