Build, test, and deploy Xcode apps
Azure Pipelines | Azure DevOps Server 2020 | Azure DevOps Server 2019 | TFS 2018 | TFS 2017
Learn how to build and deploy Xcode projects with Azure Pipelines.
- An Xcode 9+ project in a GitHub repository. If you do not have a project, see Creating an Xcode Project for an App
Create the pipeline
Sign in to your Azure DevOps organization and navigate to your project.
Go to Pipelines, and then select New Pipeline.
Walk through the steps of the wizard by first selecting GitHub as the location of your source code.
You might be redirected to GitHub to sign in. If so, enter your GitHub credentials.
When the list of repositories appears, select your repository.
You might be redirected to GitHub to install the Azure Pipelines app. If so, select Approve & install.
When the Configure tab appears, select Xcode.
When your new pipeline appears, take a look at the YAML to see what it does. When you're ready, select Save and run.
You're prompted to commit a new azure-pipelines.yml file to your repository. After you're happy with the message, select Save and run again.
If you want to watch your pipeline in action, select the build job.
You just created and ran a pipeline that we automatically created for you, because your code appeared to be a good match for the Xcode template.
You now have a working YAML pipeline (
azure-pipelines.yml) in your repository that's ready for you to customize!
When you're ready to make changes to your pipeline, select it in the Pipelines page, and then Edit the
See the sections below to learn some of the more common ways to customize your pipeline.
To make changes to the YAML file as described in this topic, select the pipeline in Pipelines page, and then select Edit to open an editor for the
You can use Azure Pipelines to build your apps with Xcode without needing to set up any infrastructure of your own. Xcode is preinstalled on Microsoft-hosted macOS agents in Azure Pipelines. You can use the macOS agents to run your builds.
For the exact versions of Xcode that are preinstalled, refer to Microsoft-hosted agents.
Create a file named azure-pipelines.yml in the root of your repository. Then, add the following snippet to your
azure-pipelines.yml file to select the appropriate agent pool:
# https://docs.microsoft.com/azure/devops/pipelines/ecosystems/xcode pool: vmImage: 'macOS-latest'
Build an app with Xcode
To build an app with Xcode, add the following snippet to your
azure-pipelines.yml file. This is a minimal snippet for building an iOS project using its default scheme, for the Simulator, and without packaging. Change values to match your project configuration. See the Xcode task for more about these options.
pool: vmImage: 'macos-latest' steps: - task: Xcode@5 inputs: actions: 'build' scheme: '' sdk: 'iphoneos' configuration: 'Release' xcWorkspacePath: '**/*.xcodeproj/project.xcworkspace' xcodeVersion: 'default' # Options: 8, 9, 10, 11, 12, default, specifyPath
Signing and provisioning
An Xcode app must be signed and provisioned to run on a device or be published to the App Store. The signing and provisioning process needs access to your P12 signing certificate and one or more provisioning profiles. The Install Apple Certificate and Install Apple Provisioning Profile tasks make these available to Xcode during a build.
See Sign your mobile app to learn more.
If your project uses Carthage with a private Carthage repository,
you can set up authentication by setting an environment variable named
GITHUB_ACCESS_TOKEN with a value of a token that has access to the repository.
Carthage will automatically detect and use this environment variable.
Do not add the secret token directly to your pipeline YAML. Instead, create a new pipeline variable with its lock enabled on the Variables pane to encrypt this value. See secret variables.
Here is an example that uses a secret variable named
myGitHubAccessToken for the value of the
GITHUB_ACCESS_TOKEN environment variable.
- script: carthage update --platform iOS env: GITHUB_ACCESS_TOKEN: $(myGitHubAccessToken)
Testing on Azure-hosted devices
Sign up with App Center first.
# App Center test # Test app packages with Visual Studio App Center - task: AppCenterTest@1 inputs: appFile: #artifactsDirectory: '$(Build.ArtifactStagingDirectory)/AppCenterTest' #prepareTests: true # Optional #frameworkOption: 'appium' # Required when prepareTests == True# Options: appium, espresso, calabash, uitest, xcuitest #appiumBuildDirectory: # Required when prepareTests == True && Framework == Appium #espressoBuildDirectory: # Optional #espressoTestApkFile: # Optional #calabashProjectDirectory: # Required when prepareTests == True && Framework == Calabash #calabashConfigFile: # Optional #calabashProfile: # Optional #calabashSkipConfigCheck: # Optional #uiTestBuildDirectory: # Required when prepareTests == True && Framework == Uitest #uitestStorePath: # Optional #uiTestStorePassword: # Optional #uitestKeyAlias: # Optional #uiTestKeyPassword: # Optional #uiTestToolsDirectory: # Optional #signInfo: # Optional #xcUITestBuildDirectory: # Optional #xcUITestIpaFile: # Optional #prepareOptions: # Optional #runTests: true # Optional #credentialsOption: 'serviceEndpoint' # Required when runTests == True# Options: serviceEndpoint, inputs #serverEndpoint: # Required when runTests == True && CredsType == ServiceEndpoint #username: # Required when runTests == True && CredsType == Inputs #password: # Required when runTests == True && CredsType == Inputs #appSlug: # Required when runTests == True #devices: # Required when runTests == True #series: 'master' # Optional #dsymDirectory: # Optional #localeOption: 'en_US' # Required when runTests == True# Options: da_DK, nl_NL, en_GB, en_US, fr_FR, de_DE, ja_JP, ru_RU, es_MX, es_ES, user #userDefinedLocale: # Optional #loginOptions: # Optional #runOptions: # Optional #skipWaitingForResults: # Optional #cliFile: # Optional #showDebugOutput: # Optional
Retain artifacts with the build record
- task: CopyFiles@2 inputs: contents: '**/*.ipa' targetFolder: '$(build.artifactStagingDirectory)' - task: PublishBuildArtifacts@1 inputs: PathtoPublish: '$(Build.ArtifactStagingDirectory)' ArtifactName: 'drop' publishLocation: 'Container'
Add the App Center Distribute task to distribute an app to a group of testers or beta users, or promote the app to Intune or the Apple App Store. A free App Center account is required (no payment is necessary).
# App Center distribute # Distribute app builds to testers and users via Visual Studio App Center - task: AppCenterDistribute@1 inputs: serverEndpoint: appSlug: appFile: #symbolsOption: 'Apple' # Optional. Options: apple #symbolsPath: # Optional #symbolsPdbFiles: '**/*.pdb' # Optional #symbolsDsymFiles: # Optional #symbolsMappingTxtFile: # Optional #symbolsIncludeParentDirectory: # Optional #releaseNotesOption: 'input' # Options: input, file #releaseNotesInput: # Required when releaseNotesOption == Input #releaseNotesFile: # Required when releaseNotesOption == File #isMandatory: false # Optional #distributionGroupId: # Optional
Apple App Store
Install the Apple App Store extension and use the following tasks to automate interaction with the App Store. By default, these tasks authenticate to Apple using a service connection that you configure.
Add the App Store Release task to automate the release of updates to existing iOS TestFlight beta apps or production apps in the App Store.
See limitations of using this task with Apple two-factor authentication, since Apple authentication is region-specific and fastlane session tokens expire quickly and must be recreated and reconfigured.
- task: AppStoreRelease@1 displayName: 'Publish to the App Store TestFlight track' inputs: serviceEndpoint: 'My Apple App Store service connection' # This service connection must be added by you appIdentifier: com.yourorganization.testapplication.etc ipaPath: '$(build.artifactstagingdirectory)/**/*.ipa' shouldSkipWaitingForProcessing: true shouldSkipSubmission: true
Add the App Store Promote task to automate the promotion of a previously submitted app from iTunes Connect to the App Store.
- task: AppStorePromote@1 displayName: 'Submit to the App Store for review' inputs: serviceEndpoint: 'My Apple App Store service connection' # This service connection must be added by you appIdentifier: com.yourorganization.testapplication.etc shouldAutoRelease: false