Introduction to CI/CD for Swift Projects
\nModern development of mobile and desktop applications in Swift requires not only high-quality code but also a reliable process for integrating and delivering changes. Continuous Integration (CI) and Continuous Delivery (CD) are practices that allow you to automate the building, testing, and deployment of applications. GitHub Actions is a built-in GitHub tool that is ideal for Swift projects running on iOS and macOS.
\nIn this article, we will cover the complete cycle of setting up CI/CD for Swift: from basic configuration to deployment to the App Store and TestFlight. You will learn how to speed up development, avoid the "human factor," and ensure the stability of your application.
\n\nKey Components of CI/CD for Swift
\nBefore moving on to the setup, it is important to understand the stages that make up the pipeline for Swift projects:
\n- \n
- Build — compiling the project using Xcode or xcodebuild. \n
- Test — running unit tests and UI tests. \n
- Lint — checking code style (e.g., using SwiftLint). \n
- Archive — creating an .ipa or .app file for deployment. \n
- Deploy — sending the build to TestFlight or the App Store. \n
GitHub Actions allows you to combine all these steps into a single YAML file stored in the repository.
\n\nSetting Up GitHub Actions for Swift: Step-by-Step Guide
\n\n1. Creating a Workflow File
\nCreate a folder .github/workflows in the root of your repository and add a file ci.yml:
name: Swift CI/CD\n\non:\n push:\n branches: [ main, develop ]\n pull_request:\n branches: [ main ]\n\njobs:\n build-and-test:\n runs-on: macos-latest\n\n steps:\n - uses: actions/checkout@v4\n\n - name: Select Xcode version\n run: sudo xcode-select -s /Applications/Xcode_15.0.app/Contents/Developer\n\n - name: Build and test\n run: |\n xcodebuild clean test \\\n -project YourApp.xcodeproj \\\n -scheme YourApp \\\n -destination 'platform=iOS Simulator,name=iPhone 15,OS=17.0' \\\n -resultBundlePath TestResults \\\n CODE_SIGNING_ALLOWED=NO\n - name: Upload test results\n uses: actions/upload-artifact@v4\n with:\n name: test-results\n path: TestResults.xcresult\nThis workflow runs on every push to main and develop, as well as on pull requests. It performs a clean build and runs all tests on an iPhone 15 simulator with iOS 17.
\n\n2. Adding Linting and Static Analysis
\nTo maintain a consistent code style, add a step with SwiftLint:
\n- name: Run SwiftLint\n run: |\n brew install swiftlint\n swiftlint --strict\nIf you use SPM (Swift Package Manager), you can add static analysis using swift analyze (available in Swift 5.9+):
- name: Static analysis\n run: swift analyze --strict\n\n3. Setting Up CD: Deployment to TestFlight
\nFor automatic delivery of builds to TestFlight, you will need certificates and provisioning profiles. The safest way is to use GitHub Secrets to store the keys:
\njobs:\n deploy:\n needs: build-and-test\n runs-on: macos-latest\n if: github.ref == 'refs/heads/main'\n\n steps:\n - uses: actions/checkout@v4\n\n - name: Install provisioning profile\n env:\n PROVISIONING_PROFILE: ${{ secrets.PROVISIONING_PROFILE_BASE64 }}\n run: |\n echo "$PROVISIONING_PROFILE" | base64 --decode > ~/Library/MobileDevice/Provisioning\\ Profiles/profile.mobileprovision\n\n - name: Build and archive\n run: |\n xcodebuild archive \\\n -project YourApp.xcodeproj \\\n -scheme YourApp \\\n -archivePath $