Xcode 14 beta code signing issues when SPM targets include resources

Any updates on the issue? How this can be solved?
I am using SPM and I am receiving similar errors. What I've noticed is that those errors come from packages/local packages that have Resources - basically Xcode14/SPM tries to codesign resource package bundles, but this is not supported.

I am distributing the app through fastlane and am not able to resolve the issue. What I've tried already:

  • use automatic signing on CI side
  • use manual signing on CI side & pass code signing related env vars via build_app xcargs / codesigning_identity arguments

I submitted a TSI to Apple after closing of the feedback.
The answer was, that when passing PROVISIONING_PROFILE_SPECIFIER or PROVISIONING_PROFILE to xcodebuild, that setting is applied every target that subsequently built for Xcode 14 (as known...). The suggested approach was to set these vars not via xcodebuild, but instead setting them to each target individually. This led us to our solution:

We set the PROVISIONING_PROFILE_SPECIFIER etc. to custom vars, here MY_ PROVISIONING_PROFILE_SPECIFIER in build settings. Then we passed them via args. These are the corresponding lines from our Azure Devobs job.

    - task: InstallAppleCertificate@2
      displayName: 'Install Apple Certificates'
      inputs:
        certSecureFile: ${{ parameters.ADHOC_CERTIFICATE }}
        certPwd:  ${{ parameters.ADHOC_CERTIFICATE_PASSWORD }}
        keychain: 'temp'

    - task: InstallAppleProvisioningProfile@1
      displayName: 'Install Apple Provisioning Profile'
      inputs:
        provisioningProfileLocation: 'secureFiles'
        provProfileSecureFile: ${{ parameters.ADHOC_PROVISIONING_PROFILE }}

    - task: Bash@3
      displayName: 'Build exportOptions.plist file'
      inputs:
        targetType: 'inline'
        script: |
          /usr/libexec/PlistBuddy -c "Add :method string ad-hoc" $(system.defaultworkingdirectory)/export.plist
          /usr/libexec/PlistBuddy -c "Add :provisioningProfiles dict" $(system.defaultworkingdirectory)/export.plist
          /usr/libexec/PlistBuddy -c "Add :provisioningProfiles:${{ parameters.ADHOC_BUNDLE_ID }} string $(APPLE_PROV_PROFILE_UUID)" $(system.defaultworkingdirectory)/export.plist
          /usr/libexec/PlistBuddy -c "Add :signingCertificate string $(APPLE_CERTIFICATE_SIGNING_IDENTITY)" $(system.defaultworkingdirectory)/export.plist
          /usr/libexec/PlistBuddy -c "Add :signingStyle string manual" $(system.defaultworkingdirectory)/export.plist
          /usr/libexec/PlistBuddy -c "Add :teamID string ${{ parameters.ADHOC_TEAM_ID }}" $(system.defaultworkingdirectory)/export.plist

...

    - task: Xcode@5
      displayName: 'Build and Archive'
      inputs:
        # Currently, Xcode 13 is the default. Therefore, the version needs to be changed to Xcode 14.
        xcodeVersion: 'specifyPath'
        xcodeDeveloperDir: '/Applications/Xcode_14.0.app'
        # By default, 'packageApp: true' will already build and archive the app so don't do anything here.
        # https://developercommunity.visualstudio.com/content/problem/1222720/why-is-xcode-ado-task-building-our-ios-project-twi.html
        actions: 'clean'
        scheme: ${{ parameters.SCHEME }}
        sdk: ${{ parameters.SDK }}
        configuration: 'Release'
        xcWorkspacePath: '**/*.xcodeproj/project.xcworkspace'
        signingOption: 'default'
        packageApp: true
        archivePath: '$(system.defaultworkingdirectory)/build/${{ parameters.SCHEME }}.xcarchive'
        exportPath: '$(system.defaultworkingdirectory)/build'
        # At this point we deliberately do not use the parameters signingIdentity and provisioningProfileUuid. 
        # When we do use them, they are applied to the app and all Swift packages in the app (new since Xcode 14). However, these often do not support signing. 
        # The parameters passed here are only applied to the app itself (see build setting and project.yml).
        args: '-destination generic/platform=iOS -verbose MY_PROVISIONING_PROFILE_SPECIFIER=$(APPLE_PROV_PROFILE_UUID) MY_CODE_SIGN_IDENTITY="$(APPLE_CERTIFICATE_SIGNING_IDENTITY)" MY_DEVELOPMENT_TEAM=${{ parameters.ADHOC_TEAM_ID }}'
        exportOptions: 'plist'
        exportOptionsPlist: '$(system.defaultworkingdirectory)/export.plist'

Thanks @honkmaster !
Your response was super helpful! It helped me understand how xcodebuild works right now with the new Xcode14. I came up with a little different solution. Let me explain.

The issue with new Xcode14

The fastlane's build_app lane was configured in a way so it was taking the xcconfig file as a parameter.
The environment variables from xcconfig file were passed to the xcodebuild command that was invoked under the hood when the build_app lane was run.

Starting from Xcode14 when codesigning env variables (e.g. PROVISIONING_PROFILE_SPECIFIER, CODE_SIGN_IDENTITY) are passed as parameters to xcodebuild, that setting is applied to every target (even the target from SPM package) and this results in codesigning failure as not every SPM target supports codesigning.

Solution

The solution is to configure codesigning only for the app target. This can be done in Build Settings.
On the target level, we can assign codesigning related parameters:

  • PROVISIONING_PROFILE_SPECIFIER
  • CODE_SIGN_IDENTITY
  • CODE_SIGN_STYLE
  • DEVELOPMENT_TEAM
    Those parameters are taken from the xcconfig file, so from now xcconfig file will be only used for the target configuration.

On a fastlane side, we were previously passing xcconfig file as a parameter to build_app lane. This resulted in passing all the env vars that were inside xcconfig to the xcodebuild script. With that setting, xcodebuild was taking the codesign related env vars and it was applying those env vars to every target (not only the main app target) - we do not want such behaviour.
By getting rid of passing xcconfig, the xcodebuild applies codesigning parameters to only the app target and the app builds successfully.

1 Like

So one needs to pass xconfig file to xcodebuild in order to sign the target only?

The xcodebuild applies codesigning parameters to only the app target, because those parameters are only defined for that particular target in Build Settings. Like this:

I am not passing xcconfig to xcodebuild currently.

Thank you all for your contribution. I managed to solve my Xcode14.0 issue with azure's pipeline.

So here is what I did:

  1. I created the export plist file.
  2. I used 'default' for signing option in xcodebuild; the target's build settings are set to auto.
  3. I passed "CODE_SIGNING_REQUIRED=Yes CODE_SIGNING_ALLOWED=No" as argument to xcodebuild.
  4. profit!

To my understanding, in this way xcodebuild will skip signing the binaries when archiving, and then it will use the plist to sign the .ipa when exporting the archive.

Here's how the .yml looks like for exporting the archive:

- task: Bash@3
  displayName: 'Build export.plist file'
  inputs:
    targetType: 'inline'
    script:
      /usr/libexec/PlistBuddy -c "Add :method string app-store" $(Pipeline.Workspace)/export.plist &&
      /usr/libexec/PlistBuddy -c "Add :provisioningProfiles dict" $(Pipeline.Workspace)/export.plist &&
      /usr/libexec/PlistBuddy -c "Add :provisioningProfiles:$(appIdentifier) string $(APPLE_PROV_PROFILE_UUID)" $(Pipeline.Workspace)/export.plist &&
      /usr/libexec/PlistBuddy -c "Add :signingCertificate string $(APPLE_CERTIFICATE_SIGNING_IDENTITY)" $(Pipeline.Workspace)/export.plist &&
      /usr/libexec/PlistBuddy -c "Add :signingStyle string manual" $(Pipeline.Workspace)/export.plist &&
      /usr/libexec/PlistBuddy -c "Add :teamID string $(teamId)" $(Pipeline.Workspace)/export.plist &&
      /usr/libexec/PlistBuddy -c "Add :iCloudContainerEnvironment string Production" $(Pipeline.Workspace)/export.plist &&
      /usr/libexec/PlistBuddy -c "Add :stripSwiftSymbols bool true" $(Pipeline.Workspace)/export.plist &&
      /usr/libexec/PlistBuddy -c "Add :compileBitcode bool false" $(Pipeline.Workspace)/export.plist

- task: Xcode@5
  inputs:
    actions: 'clean'
    configuration: '$(configuration)'
    sdk: '$(sdk)'
    scheme: '$(scheme)'
    xcodeVersion: '14'
    signingOption: 'default'
    packageApp: true
    archivePath: '$(Pipeline.Workspace)/build/$(scheme).xcarchive'
    exportPath: '$(Build.ArtifactStagingDirectory)'
    exportOptions: 'plist'
    exportOptionsPlist: '$(Pipeline.Workspace)/export.plist'
    args: '-destination generic/platform=iOS -verbose CODE_SIGNING_REQUIRED=Yes CODE_SIGNING_ALLOWED=No'

1 Like

The above solution worked for us also.

Thanks for your help! This fixed our issue as well. This is our working .yml file in azure devops.

steps:
- task: CmdLine@2
  inputs:
    script: |
      mkdir '$(build.artifactStagingDirectory)/Archive' && cd "$_"

      /usr/libexec/PlistBuddy -c "Clear dict" $(XCODE_EXPORT_OPTIONS_PLIST_FILE_NAME)
      /usr/libexec/PlistBuddy -c "Add method string $(METHOD)" $(XCODE_EXPORT_OPTIONS_PLIST_FILE_NAME)
      /usr/libexec/PlistBuddy -c "Add signingStyle string manual" $(XCODE_EXPORT_OPTIONS_PLIST_FILE_NAME)
      /usr/libexec/PlistBuddy -c "Add signingCertificate string $(CODE_SIGN_IDENTITY)" $(XCODE_EXPORT_OPTIONS_PLIST_FILE_NAME)
      /usr/libexec/PlistBuddy -c "Add provisioningProfiles dict" $(XCODE_EXPORT_OPTIONS_PLIST_FILE_NAME)
      /usr/libexec/PlistBuddy -c "Add provisioningProfiles:$(APP_BUNDLE_ID) string $(APP_PROVISIONING_ID)" $(XCODE_EXPORT_OPTIONS_PLIST_FILE_NAME)
      /usr/libexec/PlistBuddy -c "Add teamID string $(TEAM_ID)" $(XCODE_EXPORT_OPTIONS_PLIST_FILE_NAME)
      /usr/libexec/PlistBuddy -x -c "Print" $(XCODE_EXPORT_OPTIONS_PLIST_FILE_NAME)
  displayName: 'Generate export options'

- task: Xcode@5
  displayName: 'Xcode Clean Archive $(SCHEME)'
  inputs:
    actions: 'clean archive'
    sdk: 'iphoneos'
    configuration: $(CONFIGURATION)
    xcWorkspacePath: 'Product.xcworkspace'
    scheme: $(SCHEME)
    packageApp: true
    archivePath: '$(build.artifactStagingDirectory)/Archive/Product.xcarchive'
    exportOptions: plist
    exportOptionsPlist: '$(build.artifactStagingDirectory)/Archive/$(XCODE_EXPORT_OPTIONS_PLIST_FILE_NAME)'
    xcodeVersion: 'specifyPath'
    xcodeDeveloperDir: '/Applications/Xcode_14.0.app'
    useXcpretty: true
    xcprettyArgs: '--color'

Update: My previous code snippet did work for archiving, signing and exporting the .ipa to TestFlight. However, since our project uses some Apple services .i.e. push notification, associated domains ... etc, the entitlements were not signed when exporting the .ipa. So we received a warning email from Apple stating that the binary was registered for such services but was missing entitlements in the code signature!
The work around I did to fix the entitlements issue, was to archive the project in the same previous way, then sign the app with the required entitlements, and eventually export to an .ipa.
So my final .yml file looks like this:

# install certificate, provisioning profile, and create the export plist
# ...

# Build the archive
- task: Xcode@5
  displayName: 'Xcode archive'
  inputs:
    actions: 'archive'
    configuration: '$(configuration)'
    sdk: '$(sdk)'
    scheme: '$(scheme)'
    xcodeVersion: '14'
    signingOption: 'default'
    packageApp: false
    useXcpretty: false
    args: '-destination generic/platform=iOS -archivePath $(Pipeline.Workspace)/$(scheme).xcarchive -verbose CODE_SIGNING_REQUIRED=Yes CODE_SIGNING_ALLOWED=No'


# Sign the binaries with projects entitlements
- task: Bash@3
  displayName: 'Code signing'
  inputs:
    targetType: 'inline'
    script:
      codesign --entitlements $(Build.Repository.LocalPath)/$(entitlement) -f -s "$(APPLE_CERTIFICATE_SIGNING_IDENTITY)" $(Pipeline.Workspace)/$(scheme).xcarchive/$(app-path)


# Export an ipa from the signed archive
- task: Bash@3
  displayName: 'Xcode export'
  inputs:
    targetType: 'inline'
    script:
      /usr/bin/xcodebuild -exportArchive -archivePath $(Pipeline.Workspace)/$(scheme).xcarchive -exportPath $(Build.ArtifactStagingDirectory) -exportOptionsPlist $(Pipeline.Workspace)/$(export-options)

PS the app-path points to the MyApp.app inside the archive, and entitlement points to the entitlements file in the repo

2 Likes

I was able to fix this issue on fastlane by adding skip_codesigning: true on gym

Adding skip_codesigning: true didn't actually fix the issue.
Entitlments and watch app would not be correctly signed.

What really solved the issue was adding xcargs: "CODE_SIGN_STYLE=Manual DEVELOPMENT_TEAM=#{options[:teamid]}"

1 Like

This issue still alives on Xcode 14.0.1, and seems to be solved on fastlane with adding xcargs "CODE_SIGN_STYLE=Manual" to Gymfile.

1 Like

Thanks! That solved the issues for us.

Have you somehow disabled the archiving in a previous Xcode task, or are you not running any "clean", or "build" tasks? Is the action "archive" enough?

I'm asking, because your current version of the Xcode task looks so different from the previous one.

In the initial xcode Task, I used 'packageApp' that will run the ´archive´ mode. But later I figured that I still needed to sign the .ipa with the entitlements. Hence I only needed to archive with extra arguments.

Ideally, one should have a build pipeline that will run a clean-build and test the code, then such pipeline to deploy the .ipa after it's verified.

We use fastlane match for signing, so the project should be signed manually by default, so CODE_SIGN_STYLE=Manual DEVELOPMENT_TEAM=<TEAM_ID> didn't help.

The project is archived successfully on the local machine, but fails to be archived on GitHub actions....

UPD:
Finally fixed the issue by disabling automatic signing for Pods.xcodeproj targets (it was enabled by cocoapods generation for xcframeworks)
Here you can find my post_install Podfile section

Is this still happening on Xcode 14.2?

1 Like

Confirmed, that this is still happening on Xcode 14.2

2 Likes

+1 still facing the same issue with Xcode 14.2.
issue with fastlane gym with SPM, passing arguments didn't worked for us. :smiling_face_with_tear:
still the same issue.
codesigning_identity: "", xcargs: "CODE_SIGN_STYLE=Manual DEVELOPMENT_TEAM="
Any other workarounds?

1 Like

Xcode 14.1 (14B47b)
Any arguments helps :frowning:
I have an iOS app target that embed 3 frameworks + widget target that is also embed those 3 frameworks.

I also tried to add predefined ExportOptions.plist but it doesn't help in any wait it ends up with following export options

{
"provisioningProfiles": {
   "com.***": "match AppStore com.***",
   "com.***.Widget": "match AppStore "com.***.Widget",
   "com.***.WebAPI": "match AppStore com.***.Widget",
   "com.***.SharedUI": "match AppStore com.***.Widget",
   "com.***.Core": "match AppStore com.***.Widget"
},
"method": "app-store",
"signingStyle": "manual"
}
2 Likes