Use xcodebuild (Xcode 8) and automatic signing in

2019-01-07 02:42发布

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?

8条回答
Emotional °昔
2楼-- · 2019-01-07 03:04

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).

查看更多
\"骚年 ilove
3楼-- · 2019-01-07 03:08

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 "";
}
查看更多
混吃等死
4楼-- · 2019-01-07 03:08

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.

查看更多
相关推荐>>
5楼-- · 2019-01-07 03:10

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.

查看更多
Viruses.
6楼-- · 2019-01-07 03:15

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.

查看更多
够拽才男人
7楼-- · 2019-01-07 03:17

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

查看更多
登录 后发表回答