Используйте xcodebuild (Xcode 8) и автоматическую подпись в средах CI (Travis/Jenkins)
С выпуском Xcode 8 Apple представила новый способ управления конфигурацией подписи. Теперь у вас есть два варианта Manual
а также Automatic
,
Согласно Сессии WWDC 2016 о подписании кода (WWDC 2016 - 401 - Что нового в подписи приложения Xcode), когда вы выбираете Automatic
подписывая, Xcode собирается:
- Создать сертификаты подписи
- Создать и обновить идентификаторы приложений
- Создание и обновление профилей обеспечения
Но согласно тому, что Apple говорит на этой сессии, Automatic Signing
собирается использовать Development signing
и будет ограничен созданными Xcode профилями обеспечения.
Проблема возникает, когда вы пытаетесь использовать Automatic Signing
в среде CI (например, Travis CI или Jenkins). Я не могу найти простой способ продолжать использовать Автоматически и подписывать для распространения (поскольку XCode заставляет вас использовать профили обеспечения и разработки, созданные XCode).
Новые "профили инициализации, созданные XCode" не отображаются на портале для разработчиков, хотя я могу найти их на своем компьютере... если я перенесу эти профили на компьютер CI, создайте для Development
и экспорт для Distribution
? Есть ли способ переопределить Automatic Signing
с помощью xcodebuild
?
9 ответов
Попробовав несколько вариантов, вот решения, которые я смог использовать на своем CI-сервере:
Включите сертификат разработчика и закрытый ключ, а также автоматически созданные профили обеспечения в среде CI:
С помощью Automatic signing
заставляет вас использовать Developer
сертификат и auto-generated provisioning profiles
, Один из вариантов - экспортировать сертификат разработки и закрытый ключ (Приложение -> Утилиты -> Доступ к цепочке для ключей) и автоматически сгенерированные профили обеспечения на компьютер CI. Чтобы найти автоматически сгенерированные профили предоставления доступа, перейдите к ~/Library/MobileDevice/Provisioning\ Profiles/
, переместите все файлы в резервную папку, откройте Xcode и заархивируйте проект. Xcode создаст автоматически сгенерированные профили обеспечения разработки и скопирует их в Provisioning Profiles
папка.
xcodebuild archive ...
создаст .xcarchive
подписано для Development
, xcodebuild -exportArchive ...
может затем отказаться от сборки для Distribution
Замените "Автоматический" на "Ручной" при построении в среде CI
Перед звонком xcodebuild
Обходной путь должен заменить все экземпляры ProvisioningStyle = Automatic
с ProvisioningStyle = Manual
в файле проекта. sed
можно использовать для простого поиска замены в pbxproj
файл:
sed -i '' 's/ProvisioningStyle = Automatic;/ProvisioningStyle = Manual;/' <ProjectName>.xcodeproj/project.pbxproj
@thelvis также создал скрипт Ruby для этого, используя xcodeproj
драгоценный камень. Сценарий дает вам лучший контроль над тем, что изменяется.
xcodebuild
будет использовать код подписи (CODE_SIGN_IDENTITY
), заданный в проекте, а также профили обеспечения (PROVISIONING_PROFILE_SPECIFIER
). Эти настройки также могут быть предоставлены в качестве параметров для xcodebuild
и они будут переопределять идентификатор подписи кода и / или профиль обеспечения, установленный в проекте.
РЕДАКТИРОВАТЬ: с Xcode 9,
xcodebuild
имеет новый параметр настройки сборкиCODE_SIGN_STYLE
выбирать междуAutomatic
а такжеManual
так что нет необходимости искать и заменять автоматические экземпляры с ручными в файле проекта, больше информации в WWDC 2017 Сессия 403 Что нового в подписи для Xcode и Xcode Server
Переключиться на ручную подпись
Подписание вручную обеспечит полный контроль над идентификаторами подписи кода и используемыми профилями. Это, вероятно, самое чистое решение, но с обратной стороной потери всех преимуществ автоматической подписи.
Чтобы узнать больше о подписывании кода с помощью Xcode 8, я очень рекомендую эту статью, а также сессию 401 WWDC2016 - Что нового в подписи приложений Xcode
Я в основном сталкиваюсь с той же проблемой, используя Jenkins CI и Xcode Plugin. В итоге я сам делал сборку и кодирование 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-значный идентификатор команды разработчиков (что-то вроде 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>
method
: один изdevelopment
,app-store
,ad-hoc
,enterprise
teamID
: ваш 10-значный идентификатор команды разработчиков (что-то вроде A1B2C3D4E5)
Этот процесс в любом случае ближе к тому, что вы будете делать с XCode вручную, чем то, что делает, например, плагин Jenkins XCode.
Примечание. Файл.xcarchive всегда будет подписан на уровне разработки, но при выборе "app-store" в качестве метода на 2-м шаге будет выполнено правильное подписание дистрибутива, а также будет включен профиль дистрибутива как "embedded.mobileprovision".
Надеюсь это поможет.
Я рассматриваю другой вариант, о котором я еще не упоминал. Установите две идентичные цели, которые отличаются только настройками подписи.
- Development Target использует автоматическую подпись, чтобы получить все эти преимущества при добавлении новых устройств / разработчиков
- CI Target использует ручную подпись
Недостатком является то, что вам придется управлять двумя одинаковыми целями. Плюсом является то, что вы получаете преимущества автоматической подписи для разработки, и вам не нужно поддерживать потенциально хрупкие скрипты, которые изменяют ваш проект непосредственно перед сборкой.
Существует еще один способ обойти нефункциональную подпись в конвейере CI/CD, когда подпись, указанная в цели (или проекте), не работает.
Мы используем автоматическую подпись для наших приложений, чтобы сделать их удобными для разработчиков, а в CI/CD подпись выполняется только на последнем этапе при создании .ipa.
- Создать неподписанный .xcarchive
xcodebuild -workspace Runner.workspace CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO <more parameters follow>
- Подпишите окончательный файл .ipa с конфигурацией в файле exportOptions.plist.
xcodebuild -exportArchive -archivePath <.xcarchive> -exportOptionsPlist <exportOptions.plist> -exportPath <output-path>
Если вы используете Xcode 8.x и Jenkins для CI. Тогда, вероятно, вы столкнетесь с проблемой: "Для подписи" YourProjectName "требуется команда разработчиков. Выберите команду разработчиков в редакторе проекта.
Подписание кода требуется для типа продукта "Приложение" в SDK "iOS 10.1" ".** BUILD FAILED ** при запуске задания.
Каково решение?.
Решение:
установите профиль обеспечения в None в настройках сборки проекта Xcode.
В jenkins создайте исполняемую оболочку перед настройкой Xcode и напишите приведенную ниже команду
sed -i '' 's/ProvisioningStyle = Automatic;/ProvisioningStyle = Manual;/' ProjectName.xcodeproj/project.pbxproj
Помните: сохраните оболочку execute перед настройками Xcode в разделе Build of jenkins.
Это работает.
Для меня ничего не сработало. Я решил свою проблему, изменив файл в приложении Xcode, установленном на вашем Mac Mini (CI-сервер с Jenkins), как показано в этой ссылке:
https://www.jayway.com/2015/05/21/fixing-your-ios-build-scripts/
Дополнительно я отключил автоматическую подпись из Xcode.
Все сделано! Наконец работает!
Для меня это было исправлено: http://code-dojo.blogspot.jp/2012/09/fix-ios-code-signing-issue-when-using.html
... копирование сертификатов из цепочки для ключей входа в систему. Вы также можете установить для всех сертификатов разработчика значение "Разрешить всем приложениям доступ к этому элементу" (щелкните правой кнопкой мыши / Получить информацию / Контроль доступа).
Я заметил, что моя сборка Unity никогда не добавляла ключ ProvisioningStyle в мой проект XCode. Затем я нашел способ вручную добавить ProvisioningStyle с помощью сценария сборки PostProcessBuild. то есть блок кода, который вызывается после того, как проект IOS XCode был построен Unity.
Сначала я посмотрел на то, как должен выглядеть файл 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 */;
};
};
};
Затем я создал свой код, чтобы повторить "структуру" файла, показанного выше. (используя проект 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 "";
}
Существует инструмент, называемый fastlane, который значительно упрощает использование xcodebuild, и он поддерживается, что означает, что новые обновления будут продолжать обеспечивать поддержку изменений в xcode. Это значительно упрощает создание сценариев и конфигураций для построения и кодирования вашего приложения среди многих других поддерживаемых им средств автоматизации xcode. Я бы рекомендовал взглянуть на это.