Mastering CI/CD for iOS developers using Azure DevOps

Roopesh Tripathi
4 min readOct 15, 2024

--

This involves a detailed setup of pipelines, resources, environments, and integrations. This guide provides an end-to-end process to configure Azure DevOps for iOS development, handling various build environments (QA, Alpha, Staging, Production), testing, automatic reporting, and deployment.

1. Setting Up Azure DevOps Project

  • Create Azure DevOps Organization: Sign up on Azure DevOps and create an organization.
  • Create a New Project: Create a project for your iOS app under the organisation. This project will host all your pipelines, repositories, and artifacts.

2. Configuring Git Repository

  • Create Git Repository: Host your iOS app code in Azure Repos (Git-based). If needed, you can import your code from other platforms like GitHub or Bitbucket.
  • Branching Strategy: Set up a branching strategy. Common branches include develop (for QA), release (for staging), and main (for production). You can also have an alpha branch for alpha builds.

3. Setting Up Build Agents

  • Azure DevOps provides Microsoft-hosted macOS build agents for iOS apps, which can be used to build, test, and deploy iOS apps.
  • Alternatively, you can set up Self-hosted macOS Agents if you require specific configurations or resources. Instructions for setting up self-hosted agents are available here.

4. Create Azure Pipelines for CI/CD

  • Azure Pipelines allow you to automate your build, test, and deployment process for different environments (QA, Alpha, Staging, Production).

4.1 YAML Pipeline Configuration

Azure DevOps Pipelines can be written using YAML for better control and versioning. Here’s an example of a pipeline for iOS using Xcode and Fastlane for automating build and deployment:

trigger:
branches:
include:
- develop
- release
- main

pool:
vmImage: 'macOS-latest'

steps:
- task: InstallAppleCertificate@2
inputs:
certSecureFile: 'your-certificate-file.p12'
certPwd: '$(CERT_PASSWORD)'
keychain: 'temp'

- task: InstallAppleProvisioningProfile@1
inputs:
provisioningProfileLocation: 'secureFiles'
provProfileSecureFile: 'your-profile-file.mobileprovision'

- script: |
sudo gem install bundler
bundle install
bundle exec fastlane beta
displayName: 'Run Fastlane Beta Build'

- task: PublishTestResults@2
inputs:
testResultsFormat: 'JUnit'
testResultsFiles: '**/test_output/report.junit'
mergeTestResults: true

- task: PublishCodeCoverageResults@1
inputs:
summaryFileLocation: '**/coverage.json'
reportDirectory: '**/coverage'
failIfCoverageEmpty: true

Steps Breakdown:

  1. Trigger: The pipeline runs on the develop, release, and main branches.
  2. Install Certificate and Provisioning Profiles: Azure tasks install the .p12 certificates and provisioning profiles for signing the iOS app.
  3. Fastlane: Automates the build process. The beta lane in Fastlane uploads the app to TestFlight or your custom QA/Alpha environments.
  4. Publish Test Results: Runs unit and UI tests, and reports the results.
  5. Publish Code Coverage: Collects and publishes the test code coverage data.

4.2 Fastlane Configuration for Automation

Fastlane will manage builds, signing, testing, and deployments for QA, Alpha, Staging, and Production.

  1. Install Fastlane:
sudo gem install fastlane
fastlane init

2. Fastlane Fastfile Example:

default_platform(:ios)

platform :ios do
desc "Build and distribute to TestFlight for Alpha"
lane :alpha do
increment_build_number
build_app(scheme: "YourAppScheme")
upload_to_testflight(
skip_waiting_for_build_processing: true,
beta_app_review_info: {
contact_email: "test@example.com",
contact_phone: "+1234567890",
notes: "Please check for alpha testing."
}
)
end

desc "Build and deploy for production"
lane :release do
increment_build_number
build_app(scheme: "YourAppScheme")
upload_to_app_store
end

desc "Run tests and generate coverage"
lane :test do
run_tests(scheme: "YourAppScheme")
slather
end
end

5. Handling Multiple Environments (QA, Alpha, Staging, Production)

  • Use separate lanes for each environment in Fastlane. For example:
  • lane :alpha: For Alpha TestFlight builds.
  • lane :qa: For QA builds using internal deployment.
  • lane :staging: For staging environments.
  • lane :release: For App Store production deployment.
  • Use environment variables (QA_API_URL, STAGING_API_URL) to configure different backend URLs for each environment.

6. Automating Unit and UI Tests

  • Use XCTest for unit and UI tests.
  • In your pipeline, use xcodebuild test to run tests as part of the build pipeline:
- script: |
xcodebuild test \
-workspace YourApp.xcworkspace \
-scheme YourAppScheme \
-destination 'platform=iOS Simulator,name=iPhone 12'
displayName: 'Run Unit and UI Tests'
  • Use Fastlane’s scan action to run tests and generate reports.
  • Publish test results and coverage reports to Azure DevOps:
- task: PublishTestResults@2
inputs:
testResultsFormat: 'JUnit'
testResultsFiles: '**/test_output/report.junit'
- task: PublishCodeCoverageResults@1
inputs:
summaryFileLocation: '**/coverage.json'
reportDirectory: '**/coverage'
- task: PublishTestResults@2
inputs:
testResultsFormat: 'JUnit'
testResultsFiles: '**/test_output/report.junit'
- task: PublishCodeCoverageResults@1
inputs:
summaryFileLocation: '**/coverage.json'
reportDirectory: '**/coverage'

7. Automating Crash and Bug Reporting

  • Integrate Crashlytics or App Center for automatic crash and bug reporting.
  • App Center can be integrated with Azure DevOps for:
  • Monitoring crashes.
  • Tracking analytics and user feedback.
  • Automated app distribution (similar to TestFlight).
  • Fastlane Integration with Crashlytics: Add the following to your Fastfile
lane :crashlytics do
crashlytics(api_token: ENV['CRASHLYTICS_API_TOKEN'], build_secret: ENV['CRASHLYTICS_BUILD_SECRET'])
end

8. Notifications and Reporting

  • Slack Notifications: Set up Fastlane’s slack action to notify your team when builds succeed or fail.
slack(
message: "Successfully deployed new build!",
channel: "#ios-deployments"
)
  • Azure DevOps Notifications: Use Azure DevOps’ native integration with Slack or Microsoft Teams for build notifications.

9. Monitoring and Continuous Improvement

  • Track the following metrics to improve the pipeline:
  • Build Duration: Ensure builds do not take too long. Use caching for dependencies like CocoaPods or Carthage.
  • Test Success Rate: Monitor the percentage of passing/failing tests over time.
  • Code Coverage: Ensure code coverage meets thresholds for each environment (QA, Alpha, etc.).

10. Production Deployment Workflow

  • Use separate pipelines or lanes for Production deployment.
  • Automate versioning and changelog generation:
lane :release do
increment_build_number
build_app
upload_to_app_store
slack(message: "Successfully deployed to the App Store!")
end

Conclusion

Setting up a CI/CD pipeline for iOS development using Azure DevOps involves integrating key tools like Fastlane, Xcode, unit/UI testing, and crash reporting services like Crashlytics or App Center. Azure Pipelines automate the entire process from code integration, testing, and deployment to various environments, ensuring reliable and fast app delivery with proper tracking of performance, bugs, and crashes.

--

--

Roopesh Tripathi
Roopesh Tripathi

Written by Roopesh Tripathi

👋 Hello, I'm Roopesh Tripathi! 📱 Mobile Developer | iOS Enthusiast | Swift Advocate 💻 Passionate about crafting elegant and efficient mobile apps.

No responses yet