在CI(Travis/Jenkins)环境中使用Xcode构建(Xcode 8)和自动签名
随着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迫使您使用开
手动
和自动
根据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
:是方法
,开发
,应用商店
,临时
企业
:您的10位开发人员团队id(类似于A1B2C3D4E5)teamID
希望这有帮助。在尝试了一些选项后,我可以在我的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 "";
}