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

  1. Создать неподписанный .xcarchive
      xcodebuild -workspace Runner.workspace  CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO <more parameters follow>
  1. Подпишите окончательный файл .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 ** при запуске задания.

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

Решение:

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

  2. В 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. Я бы рекомендовал взглянуть на это.

Другие вопросы по тегам