web-dev-qa-db-fra.com

Utiliser xcodebuild (Xcode 8) et la signature automatique dans les environnements CI (Travis/Jenkins)

Avec la sortie de Xcode 8, Apple a introduit une nouvelle façon de gérer la configuration de la signature. Vous avez maintenant deux options Manual et Automatic.

Selon la session WWDC 2016 sur la signature de code (WWDC 2016 - 401 - Nouveautés de la signature d'application Xcode) , lorsque vous sélectionnez la signature Automatic, Xcode va:

  • Créer des certificats de signature
  • Créer et mettre à jour les identifiants d'applications
  • Créer et mettre à jour des profils d'approvisionnement

Mais selon ce que Apple a dit lors de cette session, le Automatic Signing va utiliser Development signing et sera limité aux profils de provisioning créés par Xcode.

Le problème survient lorsque vous essayez d'utiliser Automatic Signing dans un environnement de CI (comme Travis CI ou Jenkins). Je ne suis pas en mesure de trouver un moyen simple de continuer à utiliser Automatique et à signer pour la distribution (car Xcode vous oblige à utiliser les profils de provisioning développés et développés par Xcode).

Les nouveaux "profils d'approvisionnement créés par Xcode" n'apparaissent pas dans le portail des développeurs, bien que je puisse les trouver ensuite dans ma machine ... dois-je déplacer ces profils vers la machine CI, générer pour Development et exporter pour Distribution? Existe-t-il un moyen de remplacer le Automatic Signing en utilisant xcodebuild?

71
pablobart

Après avoir essayé quelques options, voici les solutions que j'ai pu utiliser sur mon serveur CI:

  • Incluez le certificat de développeur et la clé privée, ainsi que les profils de provisionnement générés automatiquement dans l'environnement CI:

L'utilisation de Automatic signing vous oblige à utiliser un certificat Developer et auto-generated provisioning profiles. Une option consiste à exporter votre certificat de développement et votre clé privée (Application -> Utilitaires -> Accès au trousseau) et les profils de provisionnement générés automatiquement vers la machine CI. Un moyen de localiser les profils de provisioning générés automatiquement consiste à accéder à ~/Library/MobileDevice/Provisioning\ Profiles/, à déplacer tous les fichiers dans un dossier de sauvegarde, à ouvrir Xcode et à archiver le projet. Xcode créera des profils de provisionnement de développement générés automatiquement et les copiera dans le dossier Provisioning Profiles.

xcodebuild archive ... créera un .xcarchive signé pour Development. xcodebuild -exportArchive ... peut alors renoncer à la construction pour Distribution 

  • Remplacez 'Automatique' par 'Manuel' lors de la création d'un environnement CI

Avant d'appeler xcodebuild, une solution de contournement consiste à remplacer toutes les instances de ProvisioningStyle = Automatic par ProvisioningStyle = Manual dans le fichier de projet. sed peut être utilisé pour une simple recherche et remplacement dans le fichier pbxproj:

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

@thelvis a également créé un script Ruby pour ce faire, à l'aide de la gemme xcodeproj. Le script vous permet de mieux contrôler ce qui change.

xcodebuild utilisera alors l'identité de signature de code (CODE_SIGN_IDENTITY) définie dans le projet, ainsi que les profils d'approvisionnement (PROVISIONING_PROFILE_SPECIFIER). Ces paramètres peuvent également être fournis en tant que paramètres à xcodebuild et ils remplaceront l'identité de signature de code et/ou le profil de provisioning défini dans le projet.

EDIT: avec Xcode 9, xcodebuild a un nouveau paramètre de construction CODE_SIGN_STYLE pour choisir entre Automatic et Manual, il n’est donc pas nécessaire de rechercher et de remplacer des instances de automatic avec manual dans le fichier de projet, plus d’informations dans WWDC 2017 Session 403 Nouveautés de la signature pour Xcode et Xcode Server } _

  • Passer à la signature manuelle

La signature manuelle fournira un contrôle total sur les identités de signature de code et les profils d'approvisionnement utilisés. C'est probablement la solution la plus propre, mais avec l'inconvénient de perdre tous les avantages de la signature automatique.

Pour en savoir plus sur la signature de code avec Xcode 8, je vous recommande vivement cet article ainsi que la session WWDC2016 401 - Nouveautés de la signature d'application Xcode

34
pablobart

En gros, je rencontre le même problème avec Jenkins CI et le plug-in Xcode . J'ai fini par créer moi-même la construction et la codification en utilisant xcodebuild.

0. Prérequis

Pour réussir les étapes suivantes, vous devez avoir installé les profils d'approvisionnement et les certificats nécessaires. Cela signifie que votre signature de code devrait déjà fonctionner en général.

1. Construire une .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: l'identifiant de votre équipe de développeurs à 10 chiffres (quelque chose comme A1B2C3D4E5)

2. Exporter au format .ipa

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

Exemple de 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: est l'un de development, app-store, ad-hoc, enterprise
  • teamID: l'identifiant de votre équipe de développeurs à 10 chiffres (quelque chose comme A1B2C3D4E5)

Ce processus est de toute façon plus proche de ce que vous feriez manuellement avec Xcode, contrairement à ce que fait par exemple le plugin Jenkins Xcode.

Remarque: le fichier .xcarchive sera toujours signé de développement, mais la sélection de "app-store" en tant que méthode à la 2e étape permet de signer correctement la distribution et d'inclure le profil de distribution en tant que "embedded.mobileprovision".

J'espère que cela t'aides.

58
d4Rk

J'envisage une autre option que je n'ai pas encore vue mentionnée ici. Configurez deux cibles identiques, qui ne diffèrent que par leurs paramètres de signature. 

  • Cible de développement utilise la signature automatique pour obtenir tous ces avantages lorsque de nouveaux périphériques/développeurs sont ajoutés
  • CI Target utilise la signature manuelle

L'inconvénient est que vous devez gérer deux objectifs identiques. Vous pouvez tirer parti des avantages de la signature automatique pour le développement, sans avoir à gérer des scripts potentiellement fragiles qui modifient votre projet juste avant la génération.

2
Paul Buchanan

Si vous utilisez Xcode 8.x et Jenkins pour CI. Ensuite, vous rencontrerez probablement un problème avec "La signature de" Votre nom de projet "nécessite une équipe de développement. Sélectionnez une équipe de développement dans l'éditeur de projet.

La signature de code est requise pour le type de produit 'Application' dans le SDK 'iOS 10.1' ”. ** BUILD FAILED ** lors de l'exécution du travail.

Quelle est la solution?.

La solution est:

  1. définissez le profil d'approvisionnement sur Aucun dans les paramètres de construction du projet Xcode.

  2. Dans Jenkins, créez un shell exécutable avant le paramètre Xcode et écrivez la commande ci-dessous.

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

    Rappelez-vous: conservez cette exécution Shell avant les paramètres Xcode dans la section Construction de Jenkins.

Cela marche.

2
Ajeet Sharma

Pour moi, rien n'a fonctionné. J'ai résolu mon problème en modifiant un fichier dans l'application Xcode installée sur votre Mac Mini (serveur CI avec Jenkins), comme indiqué dans ce lien:
https://www.jayway.com/2015/05/21/fixing-your-ios-build-scripts/
De plus, j'ai désactivé la signature automatique à partir de Xcode.

Terminé! Enfin fonctionne!

1
Marcelo dos Santos

J'ai remarqué que ma version Unity n'a jamais ajouté de clé ProvisioningStyle à mon projet XCode. J'ai ensuite trouvé un moyen d'ajouter manuellement le ProvisioningStyle à l'aide d'un script de génération "PostProcessBuild". c'est-à-dire une unité de code appelée après la construction du projet XCode IOS par Unity. 

J'ai tout d'abord regardé à quoi devrait ressembler le fichier project.pbxproj - lorsqu'il est défini sur Approvisionnement manuel:

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

Ensuite, j'ai créé mon code pour répliquer la "structure" du fichier vu ci-dessus. (en utilisant le projet XCodeEditor trouvé ici: 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 "";
}
0
UberGeoff

Il existe un outil appelé fastlane qui facilite beaucoup l’utilisation de xcodebuild et qui est maintenu: les nouvelles mises à jour continueront de prendre en charge les modifications apportées à xcode. Cela facilite beaucoup la création de scripts et la configuration pour la construction et la signature de codes de votre application parmi de nombreux autres outils d'automatisation xcode pris en charge. Je recommanderais d'y jeter un coup d'oeil.

0
lastlink

Ce qui a résolu le problème pour moi, c'est ceci: http://code-dojo.blogspot.jp/2012/09/fix-ios-code-signing-issue-when-using.html

... copie des certificats du trousseau de connexion au trousseau système . Vous pouvez également définir tous les certificats de développement sur "Autoriser toutes les applications à accéder à cet élément" (clic droit/Obtenir des informations/Contrôle d'accès).

0
BadmintonCat