Используйте 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?

Ответ 1

После нескольких вариантов, это решения, которые я смог использовать на моем сервере CI:

  • Включите сертификат разработчика и закрытый ключ, а также автогенерированные профили обеспечения в среде CI:

Использование Automatic signing заставляет вас использовать сертификат Developer и auto-generated provisioning profiles. Один из вариантов заключается в том, чтобы экспортировать свой сертификат разработки и закрытый ключ (Application → Utilities → Keychain Access) и автогенерированные профили подготовки к машине 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 script, чтобы сделать это, используя драгоценный камень xcodeproj. script дает вам лучший контроль над тем, что изменилось.

xcodebuild будет использовать идентификатор подписи кода (CODE_SIGN_IDENTITY), заданный в проекте, а также профили подготовки (PROVISIONING_PROFILE_SPECIFIER). Эти параметры также могут предоставляться как параметры xcodebuild, и они переопределяют идентификатор подписи кода и/или профиль подготовки, установленные в проекте.

EDIT: с Xcode 9, xcodebuild имеет новый параметр настроек сборки CODE_SIGN_STYLE для выбора между Automatic и Manual, поэтому нет необходимости находить и заменять экземпляры автоматического с помощью руководства в файле проекта, больше info in WWDC 2017 Сессия 403 Что нового в подписи для Xcode и Xcode Server

  • Переключиться на подписку вручную

Подписание вручную обеспечит полный контроль над идентификаторами подписи кода и используемыми профилями. Это, вероятно, самое чистое решение, но с недостатком потери всех преимуществ автоматической подписи.

Чтобы узнать больше о подписи кода с помощью Xcode 8, я действительно рекомендую эту статью, а также сеанс WWDC2016 401 - Что нового в подписании приложения Xcode

Ответ 2

В основном я сталкиваюсь с той же проблемой, используя 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 Plugin.

Примечание. Файл .xcarchive всегда будет подписан, но выбор "app-store", как метод на втором этапе, сделает правильное подписание рассылки, а также включит профиль распространения как "embedded.mobileprovision".

Надеюсь, что это поможет.

Ответ 3

Я рассматриваю еще один вариант, о котором я еще не упоминал. Установите две идентичные цели, которые отличаются только в настройках их подписания.

  • Цель разработки использует автоматическое подписание для получения всех этих преимуществ при добавлении новых устройств/разработчиков.
  • Цель CI использует ручную подпись

Даунсайд - это то, что вам придется управлять двумя идентичными целями. Потенциал роста заключается в том, что вы получаете преимущества автоматического подписания для разработки и не должны поддерживать потенциально хрупкие сценарии, которые изменяют ваш проект непосредственно перед временем сборки.

Ответ 4

Если вы используете Xcode 8.x и Jenkins для CI. Вероятно, вы столкнулись бы с проблемой "Подписание для" YourProjectName "требует команды разработчиков. Выберите команду разработчика в редакторе проекта.

Подписание кода необходимо для типа продукта "Приложение" в SDK "iOS 10.1". ** BUILD FAILED ** при выполнении задания.

Какое решение?

Решение:

  • установите профиль Provisioning в None в настройках сборки проекта Xcode.

  • В jenkins создайте оболочку выполнения перед настройкой Xcode и напишите следующую команду

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

    Помните: держите эту оболочку перед настройками Xcode в разделе Build jenkins.

Это работает.

Ответ 5

Для меня ничего не получилось. Я решил свою проблему, изменив файл в приложении Xcode, установленном на вашем Mac Mini (CI-сервер с Jenkins), как показано в этой ссылке:
https://www.jayway.com/2015/05/21/fixing-your-ios-build-scripts/
Кроме того, я отключил автоматическое подписание с Xcode.

Все сделано! Наконец работает!

Ответ 6

Я заметил, что моя сборка Unity никогда не добавляла ключ ProvisioningStyle к моему проекту XCode. Затем я нашел способ вручную добавить ProvisioningStyle с помощью сборки PostProcessBuild script. то есть блок кода, который вызывается после того, как проект 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 "";
}

Ответ 7

Для меня это было исправлено: http://code-dojo.blogspot.jp/2012/09/fix-ios-code-signing-issue-when-using.html

... копирование сертификатов из ключевого слова Login в системную цепочку ключей. Вы также можете установить для всех сертификатов разработчика "Разрешить всем приложениям доступ к этому элементу" (щелкните правой кнопкой мыши /Get Info/Access Control).

Ответ 8

Существует инструмент под названием fastlane, который упрощает использование xcodebuild и поддерживается, что означает, что новые обновления будут продолжать поддерживать изменения в xcode. Это упрощает создание сценариев и конфигов для создания и кодовое сопоставление вашего приложения среди многих других инструментов автоматизации xcode, которые он поддерживает. Я бы порекомендовал взглянуть на него.