Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .arkana.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package_manager: cocoapods
package_manager: spm
environments:
- Staging
- Release
Expand Down
6 changes: 3 additions & 3 deletions .github/wiki/Bitrise.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Out of the box, the Bitrise Template has the following workflows and steps:
|---------------------------|---------------------------------------------------------|-----------------------------------------|-------------------------------------------|
| Git Clone Repository | Git Clone Repository | Git Clone Repository | Git Clone Repository |
| Bitrise.io Cache:Pull | Bitrise.io Cache:Pull | Bitrise.io Cache:Pull | Bitrise.io Cache:Pull |
| Run CocoaPods install | Run CocoaPods install | Run CocoaPods install | Run CocoaPods install |
| Resolve SPM dependencies | Resolve SPM dependencies | Resolve SPM dependencies | Resolve SPM dependencies |
| Fastlane - Build and Test | Xcode Test for iOS | Xcode Test for iOS | Xcode Test for iOS |
| Fastlane - Clean Up Xcov | Fastlane Match | Fastlane Match | Fastlane Match |
| Danger | Fastlane - Build and Upload Production App to App Store | Fastlane - Build and Upload Staging App | Fastlane: Build and Upload Production App |
Expand All @@ -26,7 +26,7 @@ Out of the box, the Bitrise Template has the following workflows and steps:
## Environment and Secrets
### App Environtment Variables
- BITRISE_PROJECT_PATH
> e.g., ExampleApp.xcodeproj or in case you're using CocoaPod, it is ExampleApp.xcworkspace.
> e.g., ExampleApp.xcodeproj.

- TEAM_ID
> This is your Apple Team ID (e.g., T3T4E84BAA), you can find it in `Membership` at Apple developer portal.
Expand Down Expand Up @@ -62,7 +62,7 @@ All four workflows have their own variables:
> Final project directory structure
```
ROOT
├── ExampleApp.xcworkspace
├── ExampleApp.xcodeproj
├── bitrise.yml
├──...
```
Expand Down
4 changes: 2 additions & 2 deletions .github/wiki/CodeMagic.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ 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 |
| Resolve SPM dependencies | Resolve SPM dependencies | Resolve SPM dependencies | Resolve SPM dependencies |
| 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 |
Expand Down Expand Up @@ -52,7 +52,7 @@ Out of the box, the CodeMagic Template has the following workflows and steps:

```
ROOT
├── ExampleApp.xcworkspace
├── ExampleApp.xcodeproj
├── codemagic.yaml
├──...
```
Expand Down
4 changes: 2 additions & 2 deletions .github/wiki/Github-Actions.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@ There are currently 4 workflows:
### Test

1. Check out the current version.
2. Install dependencies including Gem, Fastlane, and Cocoapods.
2. Install dependencies via Bundler (Fastlane, Danger, etc.) and resolve SPM packages with Tuist/Xcode.
3. Run Test on staging scheme and show result on pull request's check.

### Deploy

1. Proceed to 4 if this job is running after `Test` job
2. Check out the current version.
3. Install dependencies including Gem, Fastlane, and Cocoapods.
3. Install dependencies via Bundler (Fastlane, Danger, etc.) and resolve SPM packages with Tuist/Xcode.
4. Install provisioning profiles and certificates using Fastlane match.
5. Build archive version of the specified scheme.
6. Deploy to Firebase Distribution, TestFlight, or App Store.
Expand Down
25 changes: 4 additions & 21 deletions .github/wiki/Project-Dependencies.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,13 @@ To simplify setup for developers new to the application, as well as having a rel
The project normally contains:

- Fastlane: is the easiest way to automate beta deployments and releases for the `iOS` (also `Android`) applications. 🚀 It handles all tedious tasks, such as generating screenshots, dealing with code signing, and releasing the application.
- Cocoapods: manages dependencies for Xcode projects. Cocoapods aims to improve the engagement with, and discoverability of, third-party open-source Cocoa libraries. Developers only need to specify the dependencies in a file named `Podfile`. Cocoapods recursively resolves dependencies between libraries, fetches source code for all dependencies, and creates and maintains an Xcode workspace to build the project.
- Swift Package Manager: a tool for managing the distribution of Swift code. It’s integrated with the Swift build system to automate the process of downloading, compiling, and linking dependencies.
- Swift Package Manager: the single source of truth for runtime dependencies. All shared libraries are declared in `Project.swift` and appear in Xcode's **Package Dependencies** section.

## Dependencies

### Bundler

[Bundler](https://bundler.io/) is a Ruby package manager, think of it as a Cocoapods for ruby plugins that will be used for the project. Keeping package versions the same on all development machines and Continuous Development machines reduces unnoticed bugs from occurring. Noteworthy packages include `Fastlane`, `Firebase-cli`, and `Cocoapods`.

### Cocoapods

[Cocoapods](https://cocoapods.org/) manages iOS packages to keep consistency throughout development machines.
[Bundler](https://bundler.io/) is a Ruby package manager used for CLI tooling such as `fastlane`, `xcov`, and `danger`. Keeping package versions the same on all development machines and Continuous Development machines reduces unnoticed bugs from occurring.

### Fastlane

Expand All @@ -30,29 +25,17 @@ The main usage of [Firebase](https://firebase.google.com/) for our team is `Fire

[Alamofire](https://github.com/Alamofire/Alamofire) is a networking library for Swift projects. Alamofire is used as a base for our Networking layer to streamline API calls in all projects, allowing developers to switch between projects without an issue.

### SnapKit (pre-SwiftUI)

[SnapKit](https://github.com/SnapKit/SnapKit) is the tool for layout user interface with ease and easier to establish a team's convention. SnapKit applies Auto Layout using a more concise syntax. This allows the UI to be responsive on different devices.

### RxSwift

[RxSwift](https://github.com/ReactiveX/RxSwift) is the library for writing Swift in the reactive programming way. RxSwift added a reactive framework for Swift with syntax closely resembling other Rx frameworks. Although it is possible to implement reactive programming for Swift, RxSwift can bypass problems that arise from maintaining large plugins and allow developers from other platforms to easily understand RxSwift syntax.

### IQKeyboardManagerSwift

[IQKeyboardManager](https://github.com/hackiftekhar/IQKeyboardManager) is a plugin for `UIScrollView`. IQKeyboardManager will detect when the keyboard is showing and adjust the view so that the view is not blocked by the keyboard. IQKeyboardManager is the go-to solution because of the ease of installation and history of maintenance by the developers.

### SwiftLint

[SwiftLin](https://github.com/realm/SwiftLint) is used to enforce our team's code convention. SwiftLint is the perfect tool for this task as it is customizable, lightweight, and automate-able. Our team installs SwiftLint with `Ruby` to allow Continuous Integration machine capability to replicate local lint. SwiftLint is integrated with Xcode to display a warning and halt build when error.
[SwiftLint](https://github.com/realm/SwiftLint) is used to enforce our team's code convention. SwiftLint is the perfect tool for this task as it is customizable, lightweight, and automate-able. CI installs SwiftLint via Homebrew, and Danger runs it directly (no Pods required).

### KeychainAccess

[KeychainAccess](https://github.com/kishikawakatsumi/KeychainAccess) is a wrapper for Keychain, making storing data with Apple's encryption as convenient as using `UserDefault`.

### Sourcery

Swift code generator running on top of Stencil. [Sourcery](https://github.com/krzysztofzablocki/Sourcery) is used to generate Protocol's Mock for Unit Testing purposes. We include Sourcery in `podfile` and add a shell script to Xcode Build Phrase `./Pods/Sourcery/bin/sourcery`.
Swift code generator running on top of Stencil. [Sourcery](https://github.com/krzysztofzablocki/Sourcery) is used to generate Protocol mocks for Unit Testing purposes. The template vendors Sourcery via scripts and runs it from `Scripts/Swift/iOSTemplateMaker`.

### SwiftFormat

Expand Down
27 changes: 0 additions & 27 deletions .github/workflows/test_swiftui_install_script.yml

This file was deleted.

27 changes: 0 additions & 27 deletions .github/workflows/test_uikit_install_script.yml

This file was deleted.

15 changes: 6 additions & 9 deletions .github/workflows/test_upload_build_to_firebase.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ jobs:
build:
name: Build
runs-on: macOS-latest
env:
FASTLANE_XCODEBUILD_SETTINGS_TIMEOUT: 60
FASTLANE_XCODEBUILD_SETTINGS_RETRIES: 4
steps:
- name: Checkout Repo
uses: actions/checkout@v6
Expand Down Expand Up @@ -52,17 +55,11 @@ jobs:
- name: Bundle install
run: bundle install

- name: Cache Pods
uses: actions/cache@v4
id: cocoapodCache
with:
path: Pods
key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }}
restore-keys: |
${{ runner.os }}-pods-
- name: Install tools with mise
uses: jdx/mise-action@v3

- name: Start Install Script for Template App
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
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

- name: Start Setup Script for Template App Firebase Upload
run: swift run --package-path Scripts/Swift/iOSTemplateMaker iOSTemplateMaker make-test-firebase
Expand Down
21 changes: 14 additions & 7 deletions .github/workflows/test_upload_build_to_test_flight.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ name: Test Upload Build to TestFlight
### TEAM_ID

on:
pull_request
# Disabled by default; keep only for manual runs when needed.
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
Expand All @@ -20,12 +21,18 @@ jobs:
build:
name: Build
runs-on: macOS-latest
env:
FASTLANE_XCODEBUILD_SETTINGS_TIMEOUT: 60
FASTLANE_XCODEBUILD_SETTINGS_RETRIES: 4
steps:
- name: Checkout Repo
uses: actions/checkout@v6
with:
fetch-depth: 0

- name: Install tools with mise
uses: jdx/mise-action@v3

- name: Install SSH key
uses: webfactory/[email protected]
with:
Expand All @@ -34,17 +41,17 @@ jobs:
- name: Bundle install
run: bundle install

- name: Cache Pods
- name: Cache SPM Packages
uses: actions/cache@v4
id: cocoapodCache
id: spmCache
with:
path: Pods
key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }}
path: .build
key: ${{ runner.os }}-spm-${{ hashFiles('**/Package.resolved') }}
restore-keys: |
${{ runner.os }}-pods-
${{ runner.os }}-spm-

- name: Start Install Script for Template App
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
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

- name: Start Setup Script for Template App TestFlight Upload
run: swift run --package-path Scripts/Swift/iOSTemplateMaker iOSTemplateMaker make-test-test-flight
Expand Down
9 changes: 1 addition & 8 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,6 @@ xcuserdata/
*.xcscmblueprint
*.xccheckout

# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
#
Pods/

# fastlane
#
# It is recommended to not store the screenshots in the git repo.
Expand All @@ -74,6 +66,7 @@ Output

# Tuist
.tuist-generated
*.xcworkspace

# JetBrains IDEs

Expand Down
4 changes: 4 additions & 0 deletions .mise.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[tools]
tuist = "4.110.3"


2 changes: 1 addition & 1 deletion .tuist-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.2.0
4.110.3
11 changes: 5 additions & 6 deletions Dangerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ warn("This pull request is quite big (#{git.lines_of_code} lines changed), pleas
warn("This pull request doesn't have any labels, please consider to add labels to this pull request.") if github.pr_labels.empty?

# SwiftFormat
swiftformat.binary_path = './Pods/SwiftFormat/CommandLineTool/swiftformat'
swiftformat.exclude = %w(Pods/** **/*generated.swift)
swiftformat.binary_path = 'swiftformat'
swiftformat.exclude = %w(**/*generated.swift)
Comment on lines +10 to +11
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Find CI configuration files
fd -e yaml -e yml -e sh | grep -E '(\.github|\.circleci|bitrise|codemagic)' | head -20

Repository: nimblehq/ios-templates

Length of output: 92


🏁 Script executed:

# Search for CI workflow patterns
rg -l 'workflow|jobs|steps|script' --type=yaml | head -20

Repository: nimblehq/ios-templates

Length of output: 212


🏁 Script executed:

# Read the Dangerfile to understand the context
cat -n Dangerfile | head -50

Repository: nimblehq/ios-templates

Length of output: 1909


🏁 Script executed:

# Search for swiftformat and swiftlint references in CI/workflow files
rg 'swiftformat|swiftlint' --type=yaml -B2 -A2

Repository: nimblehq/ios-templates

Length of output: 168


🏁 Script executed:

# Search for tool installation patterns (mint, brew, etc.)
rg 'mint install|brew install|setup.*swift|SPM|cocoapods' --type=yaml -B2 -A2

Repository: nimblehq/ios-templates

Length of output: 168


🏁 Script executed:

# Read bitrise.yml to check tool installation
cat -n bitrise.yml | head -100

Repository: nimblehq/ios-templates

Length of output: 3572


🏁 Script executed:

# Read codemagic.yaml to check tool installation
cat -n codemagic.yaml | head -100

Repository: nimblehq/ios-templates

Length of output: 3819


🏁 Script executed:

# Check if Dangerfile is a template file (cookiecutter patterns)
rg 'cookiecutter|PROJECT_NAME' Dangerfile

Repository: nimblehq/ios-templates

Length of output: 212


🏁 Script executed:

# Check for Gemfile or other dependency files that might install Danger plugins
cat Gemfile 2>/dev/null || echo "No Gemfile found"

Repository: nimblehq/ios-templates

Length of output: 373


🏁 Script executed:

# Check if there are any installation instructions in README or docs
fd -e md | xargs rg -l 'swiftformat|swiftlint|setup|install' 2>/dev/null | head -5

Repository: nimblehq/ios-templates

Length of output: 93


🏁 Script executed:

# Check full bitrise.yml for bundle install or gem installation
rg 'bundle|gem' bitrise.yml -B2 -A2

Repository: nimblehq/ios-templates

Length of output: 48


🏁 Script executed:

# Check README for tool setup instructions
cat README.md | grep -A20 -B2 'setup\|install\|swift' | head -50

Repository: nimblehq/ios-templates

Length of output: 1569


🏁 Script executed:

# Verify if Dangerfile is indeed a template file
file Dangerfile && head -5 Dangerfile

Repository: nimblehq/ios-templates

Length of output: 110


Verify swiftformat and swiftlint are installed in CI environments.

The binary paths for SwiftFormat and SwiftLint (lines 10, 15) reference external CLI tools that must be available in the system PATH. The Gemfile includes the Danger wrapper gems (danger-swiftformat, danger-swiftlint), but these gems require the actual swiftformat and swiftlint binaries to be pre-installed. Ensure these tools are installed as part of your CI setup—neither bitrise.yml nor codemagic.yaml shows explicit installation steps for these binaries. Consider adding installation commands (e.g., via Homebrew, mint, or direct download) to your CI workflows.

🤖 Prompt for AI Agents
In Dangerfile around lines 10 to 11, the Danger config references external
swiftformat and swiftlint binaries but the CI configs do not install those
tools; update the CI pipelines (bitrise.yml and codemagic.yaml) to install and
put swiftformat and swiftlint on PATH before running Danger (examples: install
via Homebrew, mint, or download and place in PATH), pin desired versions, verify
installation with a quick --version check, and fail the build early with a clear
message if the binaries are missing so Danger’s swiftformat/swiftlint wrappers
will run reliably.

swiftformat.check_format

# Swiftlint
swiftlint.binary_path = './Pods/SwiftLint/swiftlint'
swiftlint.binary_path = 'swiftlint'
swiftlint.config_file = '.swiftlint.yml'
swiftlint.max_num_violations = 20
swiftlint.lint_files(
Expand All @@ -21,9 +21,9 @@ swiftlint.lint_files(
additional_swiftlint_args: '--strict'
)

xcodeproj = "./{PROJECT_NAME}.xcodeproj"
xcresultPath = "./fastlane/test_output/{PROJECT_NAME} Staging.xcresult"
scheme = "{PROJECT_NAME} Staging"
workspace = "./{PROJECT_NAME}.xcworkspace"
xcovOutputDirectory = "./fastlane/xcov_output"

# Xcode summary
Expand All @@ -35,14 +35,13 @@ xcode_summary.ignored_results { |result|
true
end
}
xcode_summary.ignored_files = 'Pods/**'
xcode_summary.inline_mode = true
xcode_summary.report xcresultPath

# Xcov
xcov.report(
scheme: scheme,
workspace: workspace,
project: xcodeproj,
output_directory: xcovOutputDirectory,
xccov_file_direct_path: xcresultPath,
only_project_targets: true,
Expand Down
3 changes: 0 additions & 3 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
source "https://rubygems.org"

gem 'arkana'
gem "cocoapods"
gem "fastlane"
gem "xcov"
gem "danger"
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)
Loading