在CI(Travis/Jenkins)环境中使用Xcode构建(Xcode 8)和自动签名

在CI(Travis/Jenkins)环境中使用Xcode构建(Xcode 8)和自动签名,xcode,jenkins,continuous-integration,travis-ci,xcodebuild,Xcode,Jenkins,Continuous Integration,Travis Ci,Xcodebuild,随着Xcode 8的发布,苹果引入了一种管理签名配置的新方法。现在您有两个选项手动和自动 根据2016年WWDC关于代码签名的会议,当您选择自动签名时,Xcode将: 创建签名证书 创建和更新应用程序ID 创建和更新资源调配配置文件 但根据苹果公司在那次会议上的说法,自动签名将使用开发签名,并且将仅限于Xcode创建的配置文件 当您尝试在CI环境(如Travis CI或Jenkins)上使用自动签名时,就会出现问题。我无法找到一种简单的方法来继续使用自动和签名分发(因为Xcode迫使您使用开

随着Xcode 8的发布,苹果引入了一种管理签名配置的新方法。现在您有两个选项
手动
自动

根据2016年WWDC关于代码签名的会议,当您选择自动签名时,Xcode将:

  • 创建签名证书
  • 创建和更新应用程序ID
  • 创建和更新资源调配配置文件
但根据苹果公司在那次会议上的说法,
自动签名
将使用
开发签名
,并且将仅限于Xcode创建的配置文件

当您尝试在CI环境(如Travis CI或Jenkins)上使用
自动签名时,就会出现问题。我无法找到一种简单的方法来继续使用自动和签名分发(因为Xcode迫使您使用开发和Xcode创建的配置文件)


新的“Xcode创建的配置文件”不会显示在开发人员门户中,尽管我可以在我的机器中找到它。。。我是否应该将这些配置文件移动到CI计算机,为
开发
构建,并为
分发
导出?有没有一种方法可以使用
xcodebuild
覆盖
自动签名

我使用Jenkins CI和Xcode插件基本上遇到了相同的问题。 最后我自己用
xcodebuild
完成了构建和代码签名的工作

0先决条件 为了成功完成以下步骤,您需要安装必要的配置文件和证书。这意味着您的代码签名应该已经可以正常工作了

1.构建.xc存档 导出选项的示例。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>

方法
发展
teamID
A1B2C3D4E5
  • 方法
    :是
    开发
    应用商店
    临时
    企业
  • teamID
    :您的10位开发人员团队id(类似于A1B2C3D4E5)
无论如何,这个过程比Jenkins Xcode插件更接近于手动使用Xcode

注意:.xarchive文件将始终进行开发签名,但在第二步中选择“app store”作为方法将进行正确的分发签名,并将分发配置文件包括为“embedded.mobileprovision”。


希望这有帮助。

在尝试了一些选项后,我可以在我的CI服务器上使用以下解决方案:

  • 在CI环境中包括开发人员证书和私钥以及自动生成的配置文件:
使用
自动签名
强制您使用
开发人员
证书和
自动生成的配置文件
。一个选项是将开发证书和私钥(应用程序->实用程序->密钥链访问)以及自动生成的配置文件导出到CI计算机。找到自动生成的配置文件的一种方法是导航到
~/Library/MobileDevice/provisioning\profiles/
,将所有文件移动到备份文件夹,打开Xcode并归档项目。Xcode将创建自动生成的开发资源调配配置文件,并将它们复制到
资源调配配置文件
文件夹中

xcodebuild归档…
将创建一个为
Development
签名的
.xarchive
xcodebuild-exportArchive…
然后可以退出
发行版的构建

  • 在CI环境上构建时,将“自动”替换为“手动”
在调用
xcodebuild
之前,解决方法是将项目文件中
provisionstyle=Automatic
的所有实例替换为
provisionstyle=Manual
sed
可用于在
pbxproj
文件中查找替换:

sed-i''s/provisiongstyle=Automatic/ProvisioningStyle=手动;/'。xcodeproj/project.pbxproj

@thelvis还使用
xcodeproj
gem创建了一个用于执行此操作的工具。脚本使您能够更好地控制更改的内容


xcodebuild
然后将使用项目中设置的代码签名标识(
code\u-SIGN\u-identity
)以及配置文件(
provisioning\u-PROFILE\u-SPECIFIER
)。这些设置也可以作为参数提供给
xcodebuild
,它们将覆盖项目中设置的代码签名标识和/或配置文件

编辑:对于Xcode 9,
Xcode构建
有一个新的构建设置参数
code\u-SIGN\u-STYLE
自动
手动
之间进行选择,因此无需在项目文件中查找并用手动替换自动的实例,更多信息请参见

  • 切换到手动签名
手动签名将提供对正在使用的代码签名身份和配置文件的完全控制。这可能是最干净的解决方案,但其缺点是失去了自动签名的所有好处


要了解更多关于使用Xcode 8进行代码签名的信息,我真的建议使用Xcode 8以及WWDC2016会话,但没有任何效果。我通过更改Mac Mini(带有Jenkins的CI服务器)上安装的Xcode应用程序中的一个文件解决了我的问题,如以下链接所示:

此外,我关闭了Xcode的自动签名功能


全部完成!终于成功了

我正在考虑另一个我还没有看到的选项。设置两个相同的目标,但它们的签名设置不同

  • Development Target在添加新设备/开发人员时,使用自动签名获得所有这些好处
  • CI目标使用手动信号
    xcodebuild -exportArchive -archivePath <path/to/your.xcarchive> -exportOptionsPlist <path/to/exportOptions.plist> -exportPath <output-path>
    
    <!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>
    
    sed -i '' 's/ProvisioningStyle = Automatic;/ProvisioningStyle = Manual;/' ProjectName.xcodeproj/project.pbxproj 
    
    /* Begin PBXDictionary section */
        29B97313FDCFA39411CA2CEA /* Project object */ = {
            isa = PBXProject;
            attributes = {
                TargetAttributes = {
                    1D6058900D05DD3D006BFB54 /* Unity-iPhone */ = {
                        ProvisioningStyle = Manual;
                    };
                    5623C57217FDCB0800090B9E /* Unity-iPhone Tests */ = {
                        TestTargetID = 1D6058900D05DD3D006BFB54 /* Unity-iPhone     */;
                    };
                };
            };
    
    [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 "";
    }