82

With the release of Xcode 8, Apple introduced a new way of managing the signing configuration. Now you have two options Manual and Automatic.

According to the WWDC 2016 Session about Code signing (WWDC 2016 - 401 - What's new in Xcode app signing), when you select Automatic signing, Xcode is going to:

  • Create signing certificates
  • Create and update App IDs
  • Create and update provisioning profiles

But according to what Apple says in that session, the Automatic Signing is going to use Development signing and will be limited to Xcode-created provisioning profiles.

The issue comes when you try to use Automatic Signing on a CI environment (like Travis CI or Jenkins). I'm not able to figure out an easy way to keep using Automatic and sign for Distribution (as Xcode forces you to use Development and Xcode-created provisioning profiles).

The new "Xcode-created provisioning profiles" do not show up in the developer portal, although I can find then in my machine... should I move those profiles to the CI machine, build for Development and export for Distribution? Is there a way to override the Automatic Signing using xcodebuild?

pablobart
  • 2,641
  • 1
  • 24
  • 22
  • 8
    I got the same issue it's driving me wild. – masterial Sep 17 '16 at 21:41
  • 3
    I've created a simple [ruby script](https://gist.github.com/thelvis4/253a2cdea8360da519b2a025c5d8fbac) that allows you to switch between Automatic and Manual signing. You can switch to Manual signing and use the `PROVISIONING_PROFILE_SPECIFIER`, `CODE_SIGN_IDENTITY` combination. Be aware it uses `xcodeproj` gem which you'll have to install first `gem install xcodeproj`. I hope this will help you. – thelvis Sep 20 '16 at 13:20
  • That is awesome, I ended up doing the same. In my case a simple find and replace worked fine. I'll share my findings. – pablobart Sep 20 '16 at 13:45
  • Problem remains, even if you switch to `Manual signing` you have to find a way to share you cert and provisioning profiles (Development or production) to all your CI servers (since the cli xcodebuild command wont manage those as xcode do). That being said you are back to managing some profile manually (using fastlane for exemple) and the Automatic feature looses a bit of its interest. – Nicolas Braun Sep 20 '16 at 16:41
  • The truth is Automatic signing is a great feature as long as you use Xcode. It finally works! The sad part is that it doesn't work if you don't open Xcode (like in CI). So, we ended up using Automatic signing while developing and switch to manual using the script above for Jenkins Builds. It would be great if `xcodebuild` could do the Automatic signing by itself, though. Let's hope signing will be automatized completely in the next version of Xcode. ^^ – thelvis Sep 21 '16 at 17:59

9 Answers9

69

I basically run into the same issue using Jenkins CI and the Xcode Plugin. I ended up doing the build and codesigning stuff myself using xcodebuild.

0. Prerequisites

In order to get the following steps done successfully, you need to have installed the necessary provisioning profiles and certificates. That means your code signing should already be working in general.

1. Building an .xcarchive

xcodebuild -project <path/to/project.xcproj> -scheme <scheme-name> -configuration <config-name> clean archive -archivePath <output-path> DEVELOPMENT_TEAM=<dev-team-id>
  • DEVELOPMENT_TEAM: your 10 digit developer team id (something like A1B2C3D4E5)

2. Exporting to .ipa

xcodebuild -exportArchive -archivePath <path/to/your.xcarchive> -exportOptionsPlist <path/to/exportOptions.plist> -exportPath <output-path>

Example of an exportOptions.plist:

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>method</key>
    <string>development</string>
    <key>teamID</key>
    <string> A1B2C3D4E5 </string>
</dict>
</plist>
  • method: is one of development, app-store, ad-hoc, enterprise
  • teamID: your 10 digit developer team id (something like A1B2C3D4E5)

This process is anyway closer to what you would do with Xcode manually, than what for example the Jenkins Xcode Plugin does.

Note: The .xcarchive file will always be develpment signed, but selecting "app-store" as method in the 2nd step will do the correct distribution signing and also include the distribution profile as "embedded.mobileprovision".

Hope this helps.

Community
  • 1
  • 1
d4Rk
  • 6,622
  • 5
  • 46
  • 60
  • 2
    when the signing is set to `Automatic` Xcode is still using `iPhone Developer`, even after setting the `DEVELOPMENT_TEAM` and `CODE_SIGNING_IDENTITY='Phone Distribution'`. If you check the log of `xcodebuild` you can see that the codesign is using `Signing Identity: "iPhone Developer: XXXX (XXXXX)"`, so your CI environment needs the developer certificate and auto generated provisioning profiles, are you using `Manual` or `Automatic`? – pablobart Sep 19 '16 at 14:51
  • 4
    Basically, if you try to force the `CODE_SIGNING_IDENTIY` but you have `Automatic` signing enabled, you will get this error: ` has conflicting provisioning settings. is automatically signed, but code signing identity iPhone Distribution: ... has been manually specified. Set the code signing identity value to "iPhone Developer" in the build settings editor, or switch to manual signing in the project editor. ` – pablobart Sep 19 '16 at 16:02
  • Actually I'm using Unity3D to create the Xcode project, but when I open the project, I can see that "Automatically manage signing" is ticked. I just gave it a try using `iPhone Distribution` (until now I just used Developer). But it just works for me. Command line output: `Build settings from command line: CODE_SIGNING_IDENTITY = iPhone Distribution DEVELOPMENT_TEAM = MY_TEAM_ID` Could you paste the command you actually used (of course you can obfuscate the team id, or any other private stuff). – d4Rk Sep 19 '16 at 17:45
  • If I try `CODE_SIGNING_IDENTITY= 'iPhone Distribution'`, I can see the same output that you are seeing, but if you check the full output of the build log and check for the `CodeSign` phase you will see that is actually using `Signing Identity: "iPhone Developer:....` (try to save the xcodebuild terminal output with `> build.log`). So if you don't exactly match the code signing identity name, it is still using development. If you match your code signing identity name (`CODE_SIGNING_IDENTITY= 'iPhone Distribution: My Company Name'`) then you will see the other error – pablobart Sep 19 '16 at 18:31
  • 2
    And I'm afraid you cannot currently switch between Automatic and Manual signing using a tool. I suppose it could work out if you find a way to edit `project.pbxproj` file and add `ProvisioningStyle = Manual;` in `TargetAttributes` for your target. But that seems to be tricky and Manual management of the certificates and provisioning profiles seems to be a more direct approach for now if you want to build on CI environment. – thelvis Sep 19 '16 at 21:25
  • Thanks for the answer but the use of Jenkins is to automate builds if you're making builds every night manually, that would not be cool. But I tried the xcodebuild tool in the command line too. It works but how to integrate it with Jenkins is the question – C0D3 Sep 20 '16 at 15:29
  • @pablobart You're right according the first step, it really seems that xcodebuild always signs the xcarchive file as "development". BUT after exporting the xcarchive to an ipa file (see 2nd step), it will do the correcet distribution signing, when "app-store" was selected as "method". I'll update my answer accordingly. – d4Rk Sep 21 '16 at 21:52
  • Thanks, worked for me. Also would be good to mention that you MUST have installed ad-hoc,production/enterprise provisioning profiles otherwise second step will not work. Can I ask you from where did you learn this ? I can't find good info about xcodebuild and all it's settings. – hsafarya Sep 26 '16 at 17:58
  • @hsafarya Thanks for the advice, I put it in my answer. Yea.. the docs on xcodebuild are not that great, really :-(. Before, I used the jenkins xcode plugin, to get all this stuff done. But that plugin seems not to be updated frequently, and using Xcode 8 it was just not working for me anymore. So I had to find another solution. After some research and a lot of try and error, I came up with this. ;-) – d4Rk Sep 26 '16 at 18:15
  • one up vote! It works on my local machine. However for some reason on Jenkins it is still saying "Code signing is required for product type 'Framework' in SDK 'iOS 10.0' ** ARCHIVE FAILED **. Anybody has any ideas why? – fangmobile Sep 30 '16 at 20:36
  • sounds like: http://stackoverflow.com/questions/37806538/code-signing-is-required-for-product-type-application-in-sdk-ios-10-0-stic – d4Rk Oct 01 '16 at 08:52
  • As your suggest, I run Jenkins build with those command line and already set Xcode8 as manual build, I get the error: requires a provisioning profile. Select a provisioning profile for the "Jenkins" build configuration in the project editor. – biolinh Oct 10 '16 at 04:25
  • @d4Rk, I tried your solution and work fine in personal project but in project at work is giving me this error "Provisioning profile "iOS Team Provisioning Profile: com.me.MyApp" doesn't include the currently selected device "iPhone".". Do you have any idea why? – user2924482 Jul 27 '17 at 21:15
  • Just check in Developer Portal -> Certificates... -> Devices, if your device is listed there, if not you can add it manually there – d4Rk Jul 31 '17 at 07:16
  • I am getting below error in jenkins, I am using automatic signing. Currently I am on Jenkins user. ** ARCHIVE FAILED ** The following build commands failed: CopySwiftLibs /Users/Shared/Jenkins/Library/Developer/Xcode/DerivedData/BusinessApp-cwllsbfxsykowsembsmsodaflirs/Build/Intermediates.noindex/ArchiveIntermediates/BusinessApp/InstallationBuildProductsLocation/Applications/BusinessApp.app (1 failure) Build step 'Execute shell' marked build as failure Finished: FAILURE – iKushal Mar 19 '18 at 06:08
39

After trying a few options, these are the solutions that I was able to use on my CI server:

  • Include the Developer certificate and private key as well as the auto generated provisioning profiles in the CI environment:

Using Automatic signing forces you to use a Developer certificate and auto-generated provisioning profiles. One option is to export your development certificate and private key (Application -> Utilities -> Keychain Access) and the auto-generated provisioning profiles to the CI machine. A way to locate the auto-generated provisioning profiles is to navigate to ~/Library/MobileDevice/Provisioning\ Profiles/, move all files to a backup folder, open Xcode and archive the project. Xcode will create auto-generated development provisioning profiles and will copy them to the Provisioning Profiles folder.

xcodebuild archive ... will create a .xcarchive signed for Development. xcodebuild -exportArchive ... can then resign the build for Distribution

  • Replace 'Automatic' with 'Manual' when building on a CI environment

Before calling xcodebuild a workaround is to replace all instances of ProvisioningStyle = Automatic with ProvisioningStyle = Manual in the project file. sed can be used for a simple find an replace in the pbxproj file:

sed -i '' 's/ProvisioningStyle = Automatic;/ProvisioningStyle = Manual;/' <ProjectName>.xcodeproj/project.pbxproj

@thelvis also created a Ruby script to do this using the xcodeproj gem. The script gives you a better control over what is changed.

xcodebuild will then use the code signing identity (CODE_SIGN_IDENTITY) set in the project, as well as the provisioning profiles (PROVISIONING_PROFILE_SPECIFIER). Those settings can also be provided as parameters to xcodebuild and they will override the code signing identity and/or provisioning profile set in the project.

EDIT: with Xcode 9, xcodebuild has a new build settings parameter CODE_SIGN_STYLE to select between Automatic and Manual so there's no need to find and replace instances of automatic with manual in the project file, more info in WWDC 2017 Session 403 What's New in Signing for Xcode and Xcode Server

  • Switch to manual signing

Manual signing will provide total control over the code signing identities and provisioning profiles being used. It's probably the cleanest solution, but with the downside of losing all the benefits of Automatic signing.

To learn more about code signing with Xcode 8 I really recommend this article as well as the WWDC2016 session 401 - What's new in Xcode app signing

pablobart
  • 2,641
  • 1
  • 24
  • 22
  • I'm still having issues after turning off manual signing for all my targets, Error in Jenkins console output is: ### Codesigning '' with 'iPhone Distribution' + /usr/bin/codesign --force --preserve-metadata=identifier,entitlements,resource-rules --sign iPhone Distribution. --resource-rules=/var/folders/9v/.../Payload/YourApp.app/ResourceRules.plist --entitlements /var/folders/9v/.../entitlements_plistHBx8AyjS /var/folders/9v/.../Payload/YourApp.app Program /usr/bin/codesign returned 1 : [Warning: usage of --preserve-metadata with option "resource-rules" (deprecated in Mac OS X >= 10.10)! – C0D3 Sep 20 '16 at 15:50
  • If you are using `Automatic` you can't use `iPhone Distribution` to build, you will need to do one of the options above, sign with Development and then export with distribution or 'force' manual signing – pablobart Sep 20 '16 at 16:12
  • Sorry I wrote that wrong, I meant after turning off automatic signing – C0D3 Sep 20 '16 at 16:59
  • Your issue doesn't seem to be related with the new signing, a quick Google search linked to this website that can maybe help you https://www.jayway.com/2015/05/21/fixing-your-ios-build-scripts/ Also, since Xcode 7, using `xcrun PackageApplication` is deprecated, and you should use `xcodebuild -exportArchive` instead – pablobart Sep 20 '16 at 17:39
  • Switch to manual singing, I got error: requires a provisioning profile. Select a provisioning profile for the "Jenkins" build configuration in the project editor. – biolinh Oct 10 '16 at 04:26
  • What a hero. Your first point did the trick for me (emptying the `Provisioning Profiles` folder). Thanks mate! – pommefrite Dec 13 '16 at 11:46
  • 1
    `PROVISIONING_PROFILE_SPECIFIER` can't be used if you switch to Manual Provisioning... – wolffan Mar 02 '17 at 10:00
  • Anyone know why xcodebuild doesn't find the prov. profiles when run in a Jenkins pipeline, but in a bash it works? – BadmintonCat Apr 20 '17 at 09:38
  • when I try to manually sign with `xcodebuild -project "MyApp.xcodeproj" -scheme "MyApp" -sdk "iphoneos" -configuration Release DEVELOPMENT_TEAM="ABC8GH76FG" PROVISIONING_PROFILE="xxxx-xxxx"`. **It complains as** `Provisioning profile "iOS Team Provisioning Profile *" doesnt include signing certificate "iPhone Distribution: MyCompany (ABC8GH76FG)"` . How can I get around this ? – TheWaterProgrammer Jul 12 '17 at 18:31
  • I am getting below error in jenkins, I am using automatic signing. Currently I am on Jenkins user. ** ARCHIVE FAILED ** The following build commands failed: CopySwiftLibs /Users/Shared/Jenkins/Library/Developer/Xcode/DerivedData/BusinessApp-cwllsbfxsykowsembsmsodaflirs/Build/Intermediates.noindex/ArchiveIntermediates/BusinessApp/InstallationBuildProductsLocation/Applications/BusinessApp.app (1 failure) Build step 'Execute shell' marked build as failure Finished: FAILURE – iKushal Mar 19 '18 at 06:09
3

I'm considering another option I've not seen mentioned here yet. Setup two identical targets, that only differ in their signing settings.

  • Development Target uses automatic signing to get all of those benefits when new devices / developers are added
  • CI Target uses manual signing

Downside is that you would have to manage two identical targets. Upside is that get the benefits of automatic signing for development, and don't have to maintain potentially brittle scripts that modify your project just before build time.

2

If you are using Xcode 8.x and Jenkins for CI. Then probably you would face issue with "Signing for “YourProjectName" requires a development team. Select a development team in the project editor.

Code signing is required for product type 'Application' in SDK 'iOS 10.1’”.** BUILD FAILED ** when running the job.

What is the solution?.

Solution is:

  1. set Provisioning profile to None in Xcode project build settings.

  2. In jenkins, Create a execute shell before the Xcode setting and write the below command

    sed -i '' 's/ProvisioningStyle = Automatic;/ProvisioningStyle = Manual;/' ProjectName.xcodeproj/project.pbxproj 
    

    Remember: keep that execute shell before Xcode settings in Build section of jenkins.

This works.

DanielBarbarian
  • 5,093
  • 12
  • 35
  • 44
Ajeet Sharma
  • 214
  • 2
  • 9
2

There is one more way to workaround nonfunctional signing in CI/CD pipeline when the signing specified in the target (or project) fails.

We use automatic signing for our apps to have a good developer experience, and in CI/CD only signing is done in the last step when .ipa is produced.

  1. Produce an unsigned .xcarchive
xcodebuild -workspace Runner.workspace  CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO <more parameters follow>
  1. Sign the final .ipa file with configuration in exportOptions.plist
xcodebuild -exportArchive -archivePath <.xcarchive> -exportOptionsPlist <exportOptions.plist> -exportPath <output-path>
1

For me, nothing worked. I solved my problem by changing a file in Xcode app installed on your Mac Mini (CI server with Jenkins), as shown in this link:
https://www.jayway.com/2015/05/21/fixing-your-ios-build-scripts/
Additionally I turned off automatic signing from Xcode.

All done! Finally works!

0

I noticed my Unity build was never adding a ProvisioningStyle key to my XCode project. I then found a way to manually add the ProvisioningStyle by using a "PostProcessBuild" build script. i.e. a unit of code that is called after the IOS XCode project has been built by Unity.

First I had a look at what the project.pbxproj file should look like - when it is set to Manual Provisioning:

/* Begin PBXDictionary section */
    29B97313FDCFA39411CA2CEA /* Project object */ = {
        isa = PBXProject;
        attributes = {
            TargetAttributes = {
                1D6058900D05DD3D006BFB54 /* Unity-iPhone */ = {
                    ProvisioningStyle = Manual;
                };
                5623C57217FDCB0800090B9E /* Unity-iPhone Tests */ = {
                    TestTargetID = 1D6058900D05DD3D006BFB54 /* Unity-iPhone     */;
                };
            };
        };

Then I created my code to replicate the "structure" of the file seen above. (using the XCodeEditor project found here: XCodeEditor)

[PostProcessBuild]
public static void OnPostProcessBuild(BuildTarget target, string path)
{
    // Create a new project object from build target
    XCProject project = new XCProject(path);

    if (target == BuildTarget.iOS)
    {
        //Add Manual ProvisioningStyle - this is to force manual signing of the XCode project
        bool provisioningSuccess = AddProvisioningStyle(project, "Manual");

        if (provisioningSuccess)
            project.Save();
    }
}

private static bool AddProvisioningStyle(XCProject project, string style)
{
    var pbxProject = project.project;

    var attr = pbxProject.data["attributes"] as PBXDictionary;
    var targetAttributes = attr["TargetAttributes"] as PBXDictionary;

    var testTargetIDGuid = FindValue(targetAttributes, "TestTargetID");

    if (!string.IsNullOrEmpty(testTargetIDGuid))
    {
        var settings = new PBXDictionary();
        //here we set the ProvisioningStyle value
        settings.Add("ProvisioningStyle", style);

        targetAttributes.Add(testTargetIDGuid, settings);

        var masterTest = FindValue(targetAttributes, "ProvisioningStyle");

        if (masterTest == style)
        {
            return true;
        }
    }

    return false;
}

private static string FindValue(PBXDictionary targetAttributes, string key)
{
    foreach (var item in targetAttributes)
    {
        var ma = item.Value as PBXDictionary;

        foreach (var di in ma)
        {
            var lookKey = di.Key;

            if (lookKey == key)
            {
                return di.Value.ToString();
            }
        }
    }

    return "";
}
UberGeoff
  • 192
  • 6
0

What fixed it for me was this: http://code-dojo.blogspot.jp/2012/09/fix-ios-code-signing-issue-when-using.html

... copying certificates from Login keychain to System keychain. You might also want to set all dev certificates to 'Allow all applications to access this item' (Right-click/Get Info/Access Control).

BadmintonCat
  • 9,416
  • 14
  • 78
  • 129
-1

There is a tool called fastlane which makes using xcodebuild much easier and it is maintained meaning new updates will continue to provide support for changes to xcode. It makes it much easier to create scripts and config for building and codesigning your app among many other xcode automation tools it supports. I'd recommend giving it a look into.

lastlink
  • 1,505
  • 2
  • 19
  • 29
  • 6
    `fastlane` and any other tool which claims to automate away all of this complexity leave you with a black box you don't understand. they work OK until they break then you need to figure out how both the code signing and Fastlane processes work. – alfwatt Oct 02 '18 at 01:39
  • Anyone who searches for two seconds knows about fastlane and match and gym, these are hugely complicated solutions that bring plenty of their own problems. My experience with fastlane and match is that your project needs to be set to manual signing locally, which is unacceptable in many cases. – dcrow Jun 07 '20 at 22:03