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.




