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

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

根据 WWDC 2016关于代码签名的会话 (WWDC 2016-401-Xcode 应用程序签名最新消息),当您选择 Automatic签名时,Xcode 将会:

  • 创建签名证书
  • 创建和更新应用程序 ID
  • 创建和更新供应配置文件

但是根据苹果在那次会议上的说法,Automatic Signing将使用 Development signing,并将仅限于 Xcode 创建的供应配置文件。

当您试图在 CI 环境(如 Travis CI 或 Jenkins)中使用 Automatic Signing时,问题就出现了。我不能找到一种简单的方法来继续使用自动和分发签名(因为 Xcode 强制您使用 Development 和 Xcode 创建的供应配置文件)。

新的“ Xcode 创建的供应配置文件”没有出现在开发者门户中,尽管我可以在我的机器中找到... 我是否应该将这些配置文件移动到 CI 机器,为 Development构建并导出为 Distribution?有没有办法用 xcodebuild覆盖 Automatic Signing

64382 次浏览

我基本上使用 Jenkins CI 和 Xcode 插件遇到了同样的问题。 最后我自己用 xcodebuild做了构建和协同设计。

0. 先决条件

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

1. 构建.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: 您的10位开发人员团队 ID (类似于 A1B2C3D4E5)

2. 出口到. ipa

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

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>
  • developmentapp-storead-hocenterprise之一
  • teamID: 您的10位开发人员团队 ID (类似于 A1B2C3D4E5)

无论如何,这个过程更接近于手动使用 Xcode 所做的工作,而不是像 Jenkins Xcode Plugin 那样。

注:。Xcarchive 文件将始终是开发签名的,但是在第二步中选择“ app-store”作为方法将执行正确的分发签名,并且将分发配置文件包含为“嵌入的. mobile 规定”。

希望这个能帮上忙。

在尝试了一些选项之后,下面是我能够在 CI 服务器上使用的解决方案:

  • 在 CI 环境中包括 Developer 证书和私钥以及自动生成的供应配置文件:

使用 Automatic signing强制您使用 Developer证书和 auto-generated provisioning profiles。一种选择是将您的开发证书和私钥(Application-> Utitility-> Keychain Access)以及自动生成的供应配置文件导出到 CI 机器。定位自动生成的供应配置文件的一种方法是导航到 ~/Library/MobileDevice/Provisioning\ Profiles/,将所有文件移动到备份文件夹,打开 Xcode 并归档项目。Xcode 将创建自动生成的开发配置文件,并将它们复制到 Provisioning Profiles文件夹。

xcodebuild archive ...将为 Development创建一个签名的 .xcarchive。然后 xcodebuild -exportArchive ...可以为 Distribution放弃构建

  • 当构建 CI 环境时,将“自动”替换为“手动”

在调用 xcodebuild之前,一个解决方案是在项目文件中用 ProvisioningStyle = Manual替换所有的 ProvisioningStyle = Automatic实例。sed可以用来在 pbxproj文件中进行简单的查找和替换:

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

@ thelvis 还创建了一个 红宝石脚本来使用 xcodeproj gem 来实现这一点。该脚本使您能够更好地控制所更改的内容。

然后,xcodebuild将使用项目中设置的代码签名标识(CODE_SIGN_IDENTITY)以及供应配置文件(PROVISIONING_PROFILE_SPECIFIER)。这些设置也可以作为参数提供给 xcodebuild,它们将覆盖项目中的代码签名标识和/或配置文件集。

编辑: 在 Xcode 9中,xcodebuild有一个新的构建设置参数 CODE_SIGN_STYLE,可以在 AutomaticManual之间进行选择,所以不需要在项目文件中查找和替换自动与手动的实例,更多信息在 WWDC 2017会议403为 Xcode 和 Xcode Server 签名有什么新鲜事

  • 切换到手动签名

手动签名将提供对所使用的代码签名标识和供应配置文件的完全控制。这可能是最干净的解决方案,但缺点是失去了所有自动签名的好处。

要了解更多关于使用 Xcode 8进行代码签名的信息,我确实推荐使用这个 文章以及 WWDC2016会话 401-Xcode 应用程序签名的新特性

对我来说,什么都没用。我通过更改安装在 Mac Mini (与 Jenkins 共享的 CI 服务器)上的 Xcode 应用程序中的一个文件来解决我的问题,如以下链接所示:
Https://www.jayway.com/2015/05/21/fixing-your-ios-build-scripts/
此外,我关闭了从 Xcode 自动签名。

搞定,终于成功了!

我在考虑另一个我还没见过的选择。设置两个相同的目标,只是它们的签名设置不同。

  • 当添加新设备/开发人员时,Development Target 使用自动签名来获得所有这些好处
  • CI Target 使用手动签名

缺点是你得管理两个相同的目标。优点是可以获得开发自动签名的好处,而不必在构建时间之前维护修改项目的潜在脆弱脚本。

如果您使用 Xcode 8.x 和 Jenkins 作为 CI。然后,您可能会面临“为“ YourProjectName”签名需要一个开发团队的问题。在项目编辑器中选择一个开发团队。

在 SDK‘ iOS 10.1”’中,产品类型‘ Application’需要进行代码签名。

解决办法是什么。

解决办法是:

  1. 将“配置文件”设置为“ Xcode 中无”项目构建设置。

  2. 在 jenkins 中,在 Xcode 设置之前创建一个执行 shell 并编写以下命令

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

    记住: 在 Jenkins 的 Build 部分中,在 Xcode 设置之前保留执行 shell。

这个管用。

我注意到我的 Unity 版本从未在我的 XCode 项目中添加 ProvisioningStyle 键。然后,我找到了一种使用“ PostProcessBuild”构建脚本手动添加 ProvisioningStyle 的方法。例如,在 Unity 构建了 IOS XCode 项目之后调用的一个代码单元。

首先,我看了 project.pbxproj 文件应该是什么样子——当它被设置为 Manual Provisoning 时:

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

然后我创建了我的代码来复制上面看到的文件的“结构”。(使用这里找到的 XCodeEditor 项目: 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 "";
}

修正我的是这个: http://code-dojo.blogspot.jp/2012/09/fix-ios-code-signing-issue-when-using.html

... 将证书从登录密钥链复制到系统密钥链。 您可能还希望将所有开发证书设置为“允许所有应用程序访问此项”(右键单击/获取信息/访问控制)。

有一个叫做 快车道的工具,它使得使用 xcodebuild 变得更加容易,并且它得到了维护,这意味着新的更新将继续为 xcode 的更改提供支持。它使得创建脚本和配置变得更加容易,以便在它支持的许多其他 xcode 自动化工具中构建和协同设计您的应用程序。我建议你看看。

当目标(或项目)中指定的签名失败时,还有一种解决 CI/CD 管道中非功能性签名的方法。

我们使用自动签名为我们的应用程序有一个良好的开发人员的经验,并在 CI/CD 只有签名是在最后一步时完成。Ipa 就是这么产生的。

  1. 生成一个未签名的.xcarchive
xcodebuild -workspace Runner.workspace  CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO <more parameters follow>
  1. 使用 exportOptions.plist 中的配置为最终的. ipa 文件签名
xcodebuild -exportArchive -archivePath <.xcarchive> -exportOptionsPlist <exportOptions.plist> -exportPath <output-path>