1

I have tried multiple things in Azure DevOps (VSTS) to create CI for the iOS app but turns out that Azure DevOps doesn't support the apps that have App extensions. Is it really the case?

I'm using the OneSignal Notification Service Extension in our project which is dependent on the main target. So, when Xcode task tries to sign the app an error occurs related to the build identifiers as the Xcode main target has a different build identifier than OneSignalNotificationServiceExtension's build identifier.

❌ error: Provisioning profile "MainTargetName" has app ID "com.xyz.-", which does not match the bundle ID "com.xyz.-.OneSignalNotificationServiceExtension". (in target 'OneSignalNotificationServiceExtension' from project 'ProjectName')

I'm using an apple certificate task to install the certificates on the Microsoft hosted agent and similarly using the provisioning profile task to install the provisioning profiles. It looks like the Xcode task has a limitation that it cannot get multiple provisioning profiles so it can cater to those iOS apps with App Extension.

- task: InstallAppleCertificate@2
  displayName: 'Install Certificates'
  inputs:
    certSecureFile: '3Certificates.p12'
    certPwd: '$(P12Password)'
    keychain: 'temp'


- task: InstallAppleProvisioningProfile@1
  displayName: 'Install MainTarget provisioning profile'
  inputs:
    provisioningProfileLocation: 'secureFiles'
    provProfileSecureFile: 'MainTarget.mobileprovision'

- task: InstallAppleProvisioningProfile@1
  displayName: 'Install OneSignal provisioning profile'
  inputs:
    provisioningProfileLocation: 'secureFiles'
    provProfileSecureFile: 'OneSignal.mobileprovision'

- task: CmdLine@2
  displayName: 'CocoaPods install'
  inputs:
    script: |
      cd $(Build.SourcesDirectory)
      echo "Pod installation"
      pod install
- task: Xcode@5
  displayName: 'Xcode Build'
  inputs:
    actions: 'build'
    xcWorkspacePath: 'CICD.xcworkspace'
    scheme: 'CICD'
    xcodeVersion: 'specifyPath'
    xcodeDeveloperDir: '/Applications/Xcode_11.2.1.app'
    packageApp: true
    exportOptions: 'plist'
    exportOptionsPlist: 'CICD/Info.plist'
    signingOption: 'manual'
    signingIdentity: '$(MY_CERTIFICATE_SIGN_IDENTITY)'
    provisioningProfileUuid: '$(MainTarget_ProfileUUID)'
    provisioningProfileName: '$(MainTarget_ProfileName)'

Let me know if I'm missing something here.

Shakaib
  • 59
  • 9

3 Answers3

3

I managed to make it work with a simple way.

  • compile your projet localy with XCode
  • archive it and export it for your purpose (for me it was Testflight upload)
  • in the folder you export .ipa, you will find an "export-options.plist"
  • in the Pipeline Azure, XCode build Task specify this file in the : "export option plist" enter image description here

(you'll have to add the file in your repo and commit/push it)

and tada ! source that lead me there : https://blog.bitrise.io/new-export-options-plist-in-xcode-9

Vassily
  • 899
  • 2
  • 8
  • 19
2

Unfortunately, there is not a straight forward way for the iOS application with App extension in Azure.

  1. To make it work you'll have to do a couple of changes in the project that are recommended on this link.
  2. Afterward, you'll be able to build and archive the application using xcodebuild Docs. because you'll have a variable pointing to each provisioning profile.
  3. On your MAC try xocdebuild command in the terminal and note down the full commands to achieve a specific file.
  4. Use CmdLine@2 task in the pipeline with these commands to build, archive & export your IPA.

Note: I have posted a Gist covering the pipeline for such an iOS application.

- task: InstallAppleCertificate@2
  displayName: 'Install Certificates'
  inputs:
    certSecureFile: '3Certificates.p12'
    certPwd: '$(P12Password)'
    keychain: 'temp'

- task: InstallAppleProvisioningProfile@1
  displayName: 'Install MainTarget provisioning profile'
  inputs:
    provisioningProfileLocation: 'secureFiles'
    provProfileSecureFile: 'MainTarget.mobileprovision'

- task: InstallAppleProvisioningProfile@1
  displayName: 'Install OneSignal provisioning profile'
  inputs:
    provisioningProfileLocation: 'secureFiles'
    provProfileSecureFile: 'OneSignal.mobileprovision'

- task: CmdLine@2
  displayName: 'CocoaPods install'
  inputs:
    script: |
      cd $(Build.SourcesDirectory)
      echo "Pod installation"
      pod install

- task: CmdLine@2
  inputs:    
    script: |
      echo "Build iOS app"
      cd $(Build.SourcesDirectory)
      
      /usr/bin/xcodebuild -sdk $(sdkOption) -configuration $(configurationOption) -workspace $(workspaceName) -scheme "$(schemeName)" build -allowProvisioningUpdates CODE_SIGN_STYLE=Manual CODE_SIGN_IDENTITY="$(signingIdentity)" APP_PROFILE="$(APP_PROFILE_ID)"  EXTENSION_PROFILE="$(APP_EXT_PROFILE_ID)"
  displayName: 'Xcode Buid'

- task: CmdLine@2
  inputs:    
    script: |
      echo "Archive the iOS app"
      cd $(Build.SourcesDirectory)
      
      /usr/bin/xcodebuild -sdk $(sdkOption) -configuration $(configurationOption) -workspace $(workspaceName) -scheme "$(schemeName)" archive -allowProvisioningUpdates CODE_SIGN_STYLE=Manual CODE_SIGN_IDENTITY="$(signingIdentity)" APP_PROFILE="$(APP_PROFILE_ID)"  EXTENSION_PROFILE="$(APP_EXT_PROFILE_ID)" -archivePath $(ArchivePath)
  displayName: 'Xcode Archive'

- task: CmdLine@2
  inputs:    
    script: |
      /usr/bin/xcodebuild -exportArchive -archivePath $(ArchivePath) -exportOptionsPlist $(Build.SourcesDirectory)/MyApplication-Info.plist  -exportPath $(ExportIpaPath)
  displayName: 'Xcode Export'
Shakaib
  • 59
  • 9
0

Please check this issue, you can try building the ios App in command-line and pass the extension app name as a parameter.

Something like: xcodebuild ... -scheme "YourExtension" -CODE_SIGN_IDENTITY=xxx PROVISIONING_PROFILE=xxx CONFIGURATION_BUILD_DIR=xxx

For more details about how to build projects from the command line see here.

LoLance
  • 25,666
  • 1
  • 39
  • 73
  • Hi @LanceLi-MSFT, I have tried the command line approach which you have suggested but it doesn't cater to the multiple provisioning profiles set up in the command. And I think this kind of iOS app's CI can only be achieved with command line as of now. – Shakaib Jul 13 '20 at 10:22
  • @Shakaib Can [this link](https://stackoverflow.com/a/29605731/10910450) makes some help for you? And since the official task doesn't suggest building ios app with extension, we can use CMD task/Bash task in CI pipeline to build the app. – LoLance Jul 16 '20 at 09:41
  • 1
    Yes! that link is of good help to me and I have found it the other day. Thanks for sharing. Currently, I'm using the recommended configuration in my project suggested by **Max Chuquimia** and some other configuration along the way. I have successfully built the Xcode app using the **command line**. Will be posting my pipeline configuration once it's finalized. – Shakaib Jul 20 '20 at 16:08
  • Great, glad to know my answer makes some help. You could consider adding your solution as answer once it's finalized. See [can I](https://stackoverflow.com/help/self-answer)... – LoLance Jul 21 '20 at 01:47