Azure DevOps Flutter CI/CD pipeline for iOS and watchOS app fails to publish to TestFlight


I have an existing Azure DevOps pipeline to build the Flutter iOS app. This app includes the Watch app and Watch app extension.

I use manual signing with an Apple Distribution certificate (.p12), and three .mobileprovision profiles (for the main app, watchkit, and watchkit extension).

The build pipeline builds an IPA file and starts to upload the file to the TestFlight using Fastlane.

Here we get the error:

Error: Asset validation failed Invalid Code Signature Identifier. The identifier "com.apple.WK" in your code signature for "App" must match its Bundle Identifier "com.org.app.watchkitapp"

Here is a pipeline code:

stages:
  - stage: iOSStage
    pool:
      vmImage: 'macos-latest'
    dependsOn: []
    displayName: iOS
    jobs:

      - job: iOSJob
        displayName: iOS
        variables:
          FLUTTER_XCODE_CODE_SIGN_IDENTITY: ""
          FLUTTER_XCODE_CODE_SIGNING_REQUIRED: NO
          FLUTTER_XCODE_CODE_SIGNING_ALLOWED: NO
        steps:
          - task: InstallAppleProvisioningProfile@1
            displayName: Install main app provisioning profile
            inputs:
              provisioningProfileLocation: 'secureFiles'
              provProfileSecureFile: 'baseapp_provisioning.mobileprovision'

          # Install WatchKit extension provisioning profile
          - task: InstallAppleProvisioningProfile@1
            displayName: Install WatchKit extension provisioning profile
            inputs:
              provisioningProfileLocation: 'secureFiles'
              provProfileSecureFile: 'watchkitapp_provisioning.mobileprovision'

          # Install WatchKit app provisioning profile
          - task: InstallAppleProvisioningProfile@1
            displayName: Install WatchKit app provisioning profile
            inputs:
              provisioningProfileLocation: 'secureFiles'
              provProfileSecureFile: 'watchkitextension_provisioning.mobileprovision'


          # replace "iosKey" and "yourPwd" with your secure file name and password
          - task: InstallAppleCertificate@2
            displayName: Install certificate
            inputs:
              certSecureFile: 'apple_distribution.p12'
              certPwd: '$(PASS)'
              keychain: 'temp'
              setUpPartitionIdACLForPrivateKey: true

          - task: FlutterInstall@0
            displayName: "Install Flutter SDK"
            inputs:
              mode: 'auto'
              channel: 'stable'
              version: 'latest'

          - task: FlutterCommand@0
            displayName: "Run Flutter diagnostics"
            inputs:
              projectDirectory: '.'
              arguments: 'doctor -v'

          - script: |
              gem install cocoapods

          # adjust path to the *.plist file
          - task: FlutterBuild@0
            displayName: "Build application"
            inputs:
              target: ipa
              projectDirectory: '$(Build.SourcesDirectory)'
              buildName: '$(Build.BuildNumber)'
              exportOptionsPlist: 'ios/ExportOptions.plist'
              debugMode: false
              profileMode: false
              verboseMode: true
              
          - task: CopyFiles@2
            displayName: "Copy app to staging directory"
            inputs:
              sourceFolder: '$(Agent.BuildDirectory)'
              contents: '**/ipa/*.ipa'
              targetFolder: '$(Build.StagingDirectory)'
              flattenFolders: true

          - task: PublishBuildArtifacts@1
            displayName: "Publish IPA file"
            inputs:
              PathtoPublish: '$(Build.ArtifactStagingDirectory)'
              ArtifactName: 'IPA'
              publishLocation: 'Container'

          - task: AppStoreRelease@1
            displayName: "Publish to the App Store TestFlight track"
            inputs:
              authType: 'ApiKey'
              apiKeyId: 'some-key-id'
              apiKeyIssuerId: 'some-issuer-id'
              apitoken: 'base64-api-token'
              releaseTrack: 'TestFlight'
              appIdentifier: 'com.org.app'
              appType: 'iOS'
              ipaPath: '$(Build.ArtifactStagingDirectory)/**/*.ipa'
              shouldSkipWaitingForProcessing: true
              shouldSkipSubmission: true
              appSpecificId: '1234'
              teamId: 'some-id'
              teamName: 'my-team'
            enabled: true
            timeoutInMinutes: 30
            retryCountOnTaskFailure: 1

And the ExportOptions.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>compileBitcode</key>
    <false/> <!-- Adjust based on your preference -->
    <key>uploadBitcode</key>
    <false/> <!-- Adjust based on your preference -->
    <key>uploadSymbols</key>
    <false/> <!-- Adjust based on your preference -->
    <key>stripSwiftSymbols</key>
    <true/>
    <key>teamID</key>
    <string>SOME-TEAM-ID</string>
    <key>method</key>
    <string>app-store</string>
    <key>signingStyle</key>
    <string>manual</string>
    <key>signingCertificate</key>
    <string>Apple Distribution: ORG (ORG_ID)</string> <!-- Replace with your certificate name -->
    <key>provisioningProfiles</key>
    <dict>
        <key>com.org.app</key>
        <string>baseapp_provisioning</string> <!-- Replace with your provisioning profile name -->
        <key>com.org.app.watchkitapp</key>
        <string>watchkitapp_provisioning</string> <!-- Replace with your provisioning profile name -->
        <key>com.org.app.watchkitapp.watchkitextension</key>
        <string>watchkitextension_provisioning</string> <!-- Replace with your provisioning profile name -->
    </dict>
</dict>
</plist>

I’m stuck on this error for several days and don’t have an idea where else to look for solution.

I tried to generate different types of certificate (.p12) and .mobileprovision profiles. I tried different flags for signing in the pipeline, but I can’t get past this error.

I suppose the problem is either with iOS (watchOS) settings, ExportOptions, DevOps build pipeline, or certificates.

If everything would work this pipeline should publish IPA file to the TestFlight.

Latest articles

spot_imgspot_img

Related articles

Leave a reply

Please enter your comment!
Please enter your name here

spot_imgspot_img