diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 981aa2e9..a5568f2a 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,13 +1,13 @@ -https://github.com/nimblehq/ios-templates/issues/ +- Close #https://github.com/nimblehq/ios-templates/issues/ -## What happened +## What happened 👀 -Describe the big picture of your changes here to communicate to the team why we should accept this pull request. - -## Insight +Provide a description of the **changes** this pull request brings to the codebase. Additionally, when the pull request is still being worked on, a checklist of the planned changes is welcome to track progress. -Describe in details how to test the changes; referenced documentation is welcome as well. - -## Proof Of Work +## Insight 📝 -Show us the implementation: screenshots, gif, etc. +Describe in detail why this solution is the most appropriate, which solution you tried but did not go with, and how to test the changes. References to relevant documentation are welcome as well. + +## Proof Of Work 📹 + +Show us the implementation: screenshots, GIFs, etc. diff --git a/.github/wiki/CodeMagic.md b/.github/wiki/CodeMagic.md new file mode 100644 index 00000000..f12bc0c6 --- /dev/null +++ b/.github/wiki/CodeMagic.md @@ -0,0 +1,60 @@ +# CodeMagic + +Use the CodeMagic template to start a new project with CodeMagic as the CI/CD tool. + +## Workflows and Steps + +Out of the box, the CodeMagic Template has the following workflows and steps: + +| test | deploy_app_store | deploy_staging_firebase | deploy_release_firebase | +| --------------------------- | ------------------------------------------------------- | --------------------------------------------------- | ----------------------------------------------------- | +| Install bundle | Install bundle | Install bundle | Install bundle | +| Run CocoaPods install | Run CocoaPods install | Run CocoaPods install | Run CocoaPods install | +| Fastlane - Build and Test | Fastlane - Build and Test | Fastlane - Build and Test | Fastlane - Build and Test | +| Fastlane - Clean Up Xcov | Fastlane Match | Fastlane Match | Fastlane Match | +| Fastlane - Build and deploy | Fastlane - Build and Upload Production App to App Store | Fastlane - Build and Upload Staging App to Firebase | Fastlane: Build and Upload Production App to Firebase | +| Danger | N/A | N/A | N/A | + +## Trigger Map + +| Workflow | Trigger | +| ----------------------- | ----------------------- | +| test | Create or Update a PR | +| deploy_staging | Push branch `develop` | +| deploy_release_firebase | Push branch `release/*` | +| deploy_app_store | Push branch `main` | + +## Environment + +### Variables + +| Key | Description | +| --------------------------- | ------------------------------------------------------------ | +| MATCH_PASSWORD | The password is used to encrypt/decrypt the Match repository to store the distribution certificates and provisioning profiles. | +| MATCH_SSH_KEY | The SSH private key is used for cloning the Match repository that contains your distribution certificates and provisioning. | +| KEYCHAIN_PASSWORD | The password to access the keychain. | +| FIREBASE_CLI_TOKEN | [Firebase token](https://firebase.google.com/docs/cli#cli-ci-systems) for uploading build to Firebase Distributions and Analytics. | +| APPSTORE_CONNECT_API_KEY | [App Store Connect API](https://docs.fastlane.tools/actions/app_store_connect_api_key/) for uploading build to TestFlight or App Store. It should be `base64` encoded. | +| API_KEY_ID | The key identifier of your App Store Connect API key. | +| ISSUER_ID | The issuer of your App Store Connect API key. | +| BUMP_APP_STORE_BUILD_NUMBER | The boolean flag to determine if the Fastlane should bump the app store build number. | +| GITHUB_TOKEN | The token of GitHub to run Danger. | + +## Installation + +1. Follow the setup instruction in [`README.md`](https://github.com/nimblehq/ios-templates#readme). + +2. To connect the repository to CodeMagic, please follow the instruction on [Adding the app to CodeMagic](https://docs.codemagic.io/yaml-quick-start/building-a-native-ios-app). + +3. Provide all the required variables and secrets. + + The final project directory structure should be like this: + +``` +ROOT +├── ExampleApp.xcworkspace +├── codemagic.yaml +├──... +``` + +4. Push changes to SCM. \ No newline at end of file diff --git a/.github/wiki/_Sidebar.md b/.github/wiki/_Sidebar.md index f4622366..238befd9 100644 --- a/.github/wiki/_Sidebar.md +++ b/.github/wiki/_Sidebar.md @@ -15,6 +15,7 @@ - [[Github Actions]] - [[Self Hosted Github Actions]] - [[Bitrise]] +- [[CodeMagic]] - [[Fastlane]] ## Operations diff --git a/.swiftformat b/.swiftformat index 6bc4d651..472eefd4 100644 --- a/.swiftformat +++ b/.swiftformat @@ -1,5 +1,5 @@ # file options ---exclude Pods, Generated, **/*.generated.swift +--exclude Pods, Generated, **/*.generated.swift, fastlane/swift # rules --disable fileHeader diff --git a/Dangerfile b/Dangerfile index 5ccf3dff..84cb7b02 100644 --- a/Dangerfile +++ b/Dangerfile @@ -24,7 +24,7 @@ swiftlint.lint_files( ) xcresultPath = "./fastlane/test_output/{PROJECT_NAME} Staging.xcresult" -scheme = "'{PROJECT_NAME} Staging'" +scheme = "{PROJECT_NAME} Staging" workspace = "./{PROJECT_NAME}.xcworkspace" xcovOutputDirectory = "./fastlane/xcov_output" diff --git a/Workspace.swift b/Workspace.swift index 1ac6aca0..2ae058da 100644 --- a/Workspace.swift +++ b/Workspace.swift @@ -9,8 +9,7 @@ extension Workspace { name: name, projects: ["./**"], generationOptions: .options( - autogeneratedWorkspaceSchemes: - .disabled + autogeneratedWorkspaceSchemes: .disabled ) ) } diff --git a/codemagic.yaml b/codemagic.yaml new file mode 100644 index 00000000..58272b88 --- /dev/null +++ b/codemagic.yaml @@ -0,0 +1,126 @@ +workflows: + deploy_staging_firebase: + name: Deploy Staging Build To Firebase + instance_type: mac_mini_m1 + environment: + groups: + - fastlane + xcode: latest + cocoapods: default + cache: + cache_paths: + - $HOME/Library/Caches/CocoaPods + triggering: + events: + - push + branch_patterns: + - pattern: 'develop' + include: true + source: true + scripts: + - name: Install bundle + script: bundle install --path vendor/bundle + - name: Install Pods Dependencies + script: bundle exec pod install + - name: Build and Test + script: bundle exec fastlane buildAndTest + - name: Match Ad-hoc + script: bundle exec fastlane syncAdHocStagingCodeSigning + - name: Build App and Distribute to Firebase + script: bundle exec fastlane buildStagingAndUploadToFirebase + artifacts: + - ./Output/*.ipa + - ./Output/*.dSYM.zip + deploy_production_firebase: + name: Deploy Production Build To Firebase + instance_type: mac_mini_m1 + environment: + groups: + - fastlane + xcode: latest + cocoapods: default + cache: + cache_paths: + - $HOME/Library/Caches/CocoaPods + triggering: + events: + - push + branch_patterns: + - pattern: 'release/*' + include: true + source: true + scripts: + - name: Install bundle + script: bundle install --path vendor/bundle + - name: Install Pods Dependencies + script: bundle exec pod install + - name: Build and Test + script: bundle exec fastlane buildAndTest + - name: Match Ad-hoc + script: bundle exec fastlane syncAdHocProductionCodeSigning + - name: Build App and Distribute to Firebase + script: bundle exec fastlane buildProductionAndUploadToFirebase + artifacts: + - ./Output/*.ipa + - ./Output/*.dSYM.zip + deploy_app_store: + name: Deploy Build To App Store + instance_type: mac_mini_m1 + environment: + groups: + - fastlane + xcode: latest + cocoapods: default + cache: + cache_paths: + - $HOME/Library/Caches/CocoaPods + triggering: + events: + - push + branch_patterns: + - pattern: 'main' + include: true + source: true + scripts: + - name: Install bundle + script: bundle install --path vendor/bundle + - name: Install Pods Dependencies + script: bundle exec pod install + - name: Build and Test + script: bundle exec fastlane buildAndTest + - name: Match AppStore + script: bundle exec fastlane syncAppStoreCodeSigning + - name: Build App and Distribute to AppStore + script: bundle exec fastlane buildAndUploadToAppStore + artifacts: + - ./Output/*.ipa + - ./Output/*.dSYM.zip + test: + name: Test + instance_type: mac_mini_m1 + environment: + groups: + - fastlane + xcode: latest + cocoapods: default + cache: + cache_paths: + - $HOME/Library/Caches/CocoaPods + triggering: + events: + - pull_request + branch_patterns: + - pattern: '*' + include: true + source: true + scripts: + - name: Install bundle + script: bundle install --path vendor/bundle + - name: Install Pods Dependencies + script: bundle exec pod install + - name: Build and Test + script: bundle exec fastlane buildAndTest + - name: Clean Up + script: bundle exec fastlane cleanUpOutput + - name: Danger + script: bundle exec danger diff --git a/deliverable_setup.sh b/deliverable_setup.sh index 8e6411d1..445c4ca7 100644 --- a/deliverable_setup.sh +++ b/deliverable_setup.sh @@ -1,20 +1,26 @@ #!/bin/sh -read -p "Which CI/CD service do you use (Can be edited later) [(g)ithub/(b)itrise/(l)ater]: " ciService +read -p "Which CI/CD service do you use (Can be edited later) [(g)ithub/(b)itrise/(c)odemagic/(l)ater]: " ciService if [ "$ciService" = "g" -o "$ciService" = "github" ]; then echo "Setting template for Github Actions" rm bitrise.yml + rm codemagic.yaml elif [ "$ciService" = "b" -o "$ciService" = "bitrise" ]; then echo "Setting template for Bitrise" rm -rf .github/workflows + rm codemagic.yaml +elif [ "$ciService" = "c" -o "$ciService" = "codemagic" ]; then + echo "Setting template for CodeMagic" + rm -rf .github/workflows + rm bitrise.yml else echo "You can manually setup the template later." fi echo "✅ Completed" -read -n1 -p "Do you want to set up Deliverable Constants values? (Can be edited later) [Y/n]:" confirm +read -n1 -p "Do you want to set up Constants values? (Can be edited later) [Y/n]:" confirm if ! echo $confirm | grep '^[Yy]\?$'; then echo "✅ Completed" else - open -a Xcode fastlane/Constants/DeliverableConstants.rb + open -a Xcode fastlane/Constants/Constant.swift fi diff --git a/fastlane/Appfile.swift b/fastlane/Appfile.swift index a576f5c3..73a9cbac 100644 --- a/fastlane/Appfile.swift +++ b/fastlane/Appfile.swift @@ -1,7 +1,5 @@ var appIdentifier: String { return "[[APP_IDENTIFIER]]" } // The bundle identifier of your app var appleID: String { return "[[APPLE_ID]]" } // Your Apple Developer Portal username - - // For more information about the Appfile, see: // https://docs.fastlane.tools/advanced/#appfile diff --git a/fastlane/Constants/Constant.swift b/fastlane/Constants/Constant.swift index 006207f3..ab0b25f1 100644 --- a/fastlane/Constants/Constant.swift +++ b/fastlane/Constants/Constant.swift @@ -39,7 +39,9 @@ enum Constant { // MARK: Platform static var platform: PlatformType { - if EnvironmentParser.bool(key: "BITRISE_IO") { + if EnvironmentParser.bool(key: "CM_BRANCH") { + return .codeMagic + } else if EnvironmentParser.bool(key: "BITRISE_IO") { return .bitrise } else if EnvironmentParser.bool(key: "GITHUB_ACTIONS") { return .gitHubActions @@ -57,7 +59,7 @@ enum Constant { static let uploadSymbolsBinaryPath: String = "./Pods/FirebaseCrashlytics/upload-symbols" static let dSYMSuffix: String = ".dSYM.zip" - + // MARK: - Build and Version static let manualVersion: String = "" @@ -65,7 +67,7 @@ enum Constant { // MARK: - Device static let devices = ["iPhone 12 Pro Max"] - + // MARK: - Test static let testTarget: String = "\(projectName)Tests" @@ -129,7 +131,7 @@ extension Constant { enum PlatformType { - case gitHubActions, bitrise, unknown + case gitHubActions, bitrise, codeMagic, unknown } } diff --git a/fastlane/Fastfile.swift b/fastlane/Fastfile.swift index 86b58fcd..027204a0 100644 --- a/fastlane/Fastfile.swift +++ b/fastlane/Fastfile.swift @@ -150,10 +150,12 @@ class Fastfile: LaneFile { useAutomaticSigning: .userDefined(false), teamId: .userDefined(EnvironmentParser.string(key: "sigh_\(Constant.productionBundleId)_appstore_team-id")), codeSignIdentity: .userDefined("iPhone Distribution"), - profileName: .userDefined(EnvironmentParser.string(key: "sigh_\(Constant.productionBundleId)_appstore_profile-name")) + profileName: .userDefined(EnvironmentParser.string( + key: "sigh_\(Constant.productionBundleId)_appstore_profile-name" + )) ) } - + func setUpTestProjectLane() { desc("Disable Exempt Encryption") Test.disableExemptEncryption() diff --git a/fastlane/Helpers/Build.swift b/fastlane/Helpers/Build.swift index e187f5b9..4bcbf283 100644 --- a/fastlane/Helpers/Build.swift +++ b/fastlane/Helpers/Build.swift @@ -31,7 +31,7 @@ enum Build { sh(command: "echo DSYM_OUTPUT_PATH=\(dsymPath ?? "") >> $GITHUB_ENV") sh(command: "echo BUILD_NUMBER=\(buildNumber ?? "") >> $GITHUB_ENV") sh(command: "echo VERSION_NUMBER=\(Version.versionNumber) >> $GITHUB_ENV") - case .bitrise: + case .bitrise, .codeMagic: sh(command: "envman add --key BUILD_PATH --value '\(Constant.outputPath)'") default: break } @@ -39,7 +39,7 @@ enum Build { // MARK: Private - static private func build( + private static func build( environment: Constant.Environment, type: Constant.BuildType ) { diff --git a/fastlane/Helpers/Version.swift b/fastlane/Helpers/Version.swift index b52def0f..f71b0f6d 100644 --- a/fastlane/Helpers/Version.swift +++ b/fastlane/Helpers/Version.swift @@ -7,9 +7,9 @@ // enum Version { - + // MARK: - Getting - + static var versionNumber: String { get { FastlaneRunner.getVersionNumber( @@ -17,7 +17,7 @@ enum Version { target: .userDefined(Constant.projectName) ) } - + set { incrementVersionNumber( versionNumber: .userDefined(newValue), @@ -25,7 +25,7 @@ enum Version { ) } } - + static var buildNumber: String { get { FastlaneRunner.getBuildNumber(xcodeproj: .userDefined(Constant.projectPath)) diff --git a/make.sh b/make.sh index 1075aa29..8b4686ef 100644 --- a/make.sh +++ b/make.sh @@ -181,6 +181,7 @@ 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"