xcode jenkins continuous-integration travis-ci xcodebuild

Utilice xcodebuild(Xcode 8) y la firma automática en entornos CI(Travis/Jenkins)



continuous-integration travis-ci (8)

Con el lanzamiento de Xcode 8, Apple introdujo una nueva forma de administrar la configuración de firma. Ahora tiene dos opciones Manual y Automatic .

De acuerdo con la sesión WWDC 2016 sobre la firma de código (WWDC 2016 - 401 - Novedades de la firma de la aplicación Xcode) , cuando selecciona Firma Automatic , Xcode va a:

  • Crear certificados de firma
  • Crear y actualizar ID de aplicaciones
  • Crear y actualizar perfiles de aprovisionamiento

Pero de acuerdo con lo que Apple dice en esa sesión, la Automatic Signing utilizará Development signing y se limitará a los perfiles de aprovisionamiento creados por Xcode.

El problema surge cuando intenta utilizar la Automatic Signing en un entorno de CI (como Travis CI o Jenkins). No puedo encontrar una manera fácil de seguir usando Automático y firmar para Distribución (ya que Xcode lo obliga a usar Desarrollo y perfiles de aprovisionamiento creados por Xcode).

Los nuevos "perfiles de aprovisionamiento creados por Xcode" no aparecen en el portal del desarrollador, aunque puedo encontrarlos en mi máquina ... ¿Debería mover esos perfiles a la máquina CI, compilar para Development y exportar para Distribution ? ¿Hay alguna forma de anular la Automatic Signing usando xcodebuild ?


Básicamente me encuentro con el mismo problema usando Jenkins CI y el Xcode Plugin. Terminé haciendo la compilación y xcodebuild yo mismo usando xcodebuild .

0. Prerrequisitos

Para que los siguientes pasos se realicen correctamente, debe haber instalado los perfiles y certificados de aprovisionamiento necesarios. Eso significa que su firma de código ya debería estar funcionando en general.

1. Construyendo un .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 : su ID de equipo de desarrollador de 10 dígitos (algo así como A1B2C3D4E5)

2. Exportando a .ipa

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

Ejemplo 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 : es uno de development , app-store , ad-hoc , enterprise
  • teamID : su ID de equipo de desarrollador de 10 dígitos (algo así como A1B2C3D4E5)

Este proceso está más cerca de lo que haría con Xcode manualmente, que lo que hace, por ejemplo, el Jenkins Xcode Plugin.

Nota: El archivo .xcarchive siempre estará firmado por el desarrollo, pero al seleccionar "app-store" como método en el segundo paso, se realizará la firma de distribución correcta y también se incluirá el perfil de distribución como "embedded.mobileprovision".

Espero que esto ayude.


Después de probar algunas opciones, estas son las soluciones que pude usar en mi servidor CI:

  • Incluya el certificado de desarrollador y la clave privada, así como los perfiles de aprovisionamiento generados automáticamente en el entorno de CI:

El uso de la Automatic signing obliga a usar un certificado de Developer y auto-generated provisioning profiles . Una opción es exportar su certificado de desarrollo y clave privada (Aplicación -> Utilidades -> Acceso a llavero) y los perfiles de aprovisionamiento generados automáticamente a la máquina CI. Una forma de localizar los perfiles de aprovisionamiento generados automáticamente es navegar a ~/Library/MobileDevice/Provisioning/ Profiles/ , mover todos los archivos a una carpeta de respaldo, abrir Xcode y archivar el proyecto. Xcode creará perfiles de aprovisionamiento de desarrollo generados automáticamente y los copiará en la carpeta Provisioning Profiles .

xcodebuild archive ... creará un .xcarchive firmado para Development . xcodebuild -exportArchive ... puede renunciar a la compilación para Distribution

  • Reemplace ''Automático'' con ''Manual'' cuando construya en un entorno CI

Antes de llamar a xcodebuild una solución es reemplazar todas las instancias de ProvisioningStyle = Automatic con ProvisioningStyle = Manual en el archivo del proyecto. sed se puede usar para buscar y reemplazar de manera simple en el archivo pbxproj :

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

@thelvis también creó un script Ruby para hacer esto usando la gema xcodeproj . El script te da un mejor control sobre lo que se cambia.

xcodebuild usará la identidad de firma de código ( CODE_SIGN_IDENTITY ) establecida en el proyecto, así como los perfiles de aprovisionamiento ( PROVISIONING_PROFILE_SPECIFIER ). Esas configuraciones también se pueden proporcionar como parámetros para xcodebuild y xcodebuild la identidad de firma de código y / o el perfil de aprovisionamiento establecido en el proyecto.

EDITAR: con Xcode 9, xcodebuild tiene un nuevo parámetro de configuración de compilación CODE_SIGN_STYLE para seleccionar entre Automatic y Manual por lo que no hay necesidad de encontrar y reemplazar instancias de automático con manual en el archivo del proyecto, más información en WWDC 2017 Sesión 403 Novedades para firmar Servidor Xcode y Xcode

  • Cambiar a firma manual

La firma manual proporcionará un control total sobre las identidades de firma de código y los perfiles de aprovisionamiento que se utilizan. Es probablemente la solución más limpia, pero con la desventaja de perder todos los beneficios de la firma automática.

Para obtener más información sobre la firma de código con Xcode 8, realmente recomiendo este article , así como la sesión 401 de WWDC2016 : Novedades de la firma de aplicaciones de Xcode


Estoy considerando otra opción que no he visto mencionada aquí todavía. Configure dos objetivos idénticos, que solo difieren en su configuración de firma.

  • Development Target utiliza la firma automática para obtener todos esos beneficios cuando se agregan nuevos dispositivos / desarrolladores
  • CI Target utiliza la firma manual

Lo malo es que tendrías que gestionar dos objetivos idénticos. Lo positivo es que obtiene los beneficios de la firma automática para el desarrollo y no tiene que mantener scripts potencialmente frágiles que modifiquen su proyecto justo antes del tiempo de construcción.


Existe una herramienta llamada fastlane que hace que usar xcodebuild sea mucho más fácil y se mantiene, lo que significa que las nuevas actualizaciones continuarán brindando soporte para cambios en xcode. Hace que sea mucho más fácil crear scripts y configuraciones para construir y codificar su aplicación entre muchas otras herramientas de automatización de xcode que admite. Recomiendo echarle un vistazo.


Lo que me solucionó fue esto: http://code-dojo.blogspot.jp/2012/09/fix-ios-code-signing-issue-when-using.html

... copiando certificados del llavero de inicio de sesión al llavero del sistema. Es posible que también desee configurar todos los certificados de desarrollo para ''Permitir que todas las aplicaciones accedan a este elemento'' (haga clic con el botón derecho / Obtener información / Control de acceso).


Noté que mi versión de Unity nunca agregaba una clave ProvisioningStyle a mi proyecto XCode. Luego encontré una manera de agregar manualmente el ProvisioningStyle usando un script de compilación "PostProcessBuild". es decir, una unidad de código que se llama después de que Unity haya creado el proyecto IOS XCode.

Primero eché un vistazo a cómo debería verse el archivo project.pbxproj, cuando está configurado en Aprovisionamiento manual:

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

Luego creé mi código para replicar la "estructura" del archivo visto anteriormente. (utilizando el proyecto XCodeEditor que se encuentra aquí: 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 ""; }


Para mí, nada funcionó. Resolví mi problema cambiando un archivo en la aplicación Xcode instalada en su Mac Mini (servidor CI con Jenkins), como se muestra en este enlace:
jayway.com/2015/05/21/fixing-your-ios-build-scripts
Además, apagué la firma automática de Xcode.

¡Todo listo! Finalmente funciona!


Si está utilizando Xcode 8.xy Jenkins para CI. Entonces, probablemente enfrentaría un problema con "Firmar para" YourProjectName "requiere un equipo de desarrollo. Seleccione un equipo de desarrollo en el editor del proyecto.

Se requiere la firma de código para el tipo de producto ''Aplicación'' en el SDK ''iOS 10.1'' ”. ** FALLO DE CONSTRUCCIÓN ** al ejecutar el trabajo.

¿Cuál es la solución?.

La solución es:

  1. establezca el perfil de aprovisionamiento en Ninguno en la configuración de compilación del proyecto Xcode.

  2. En jenkins, cree un shell de ejecución antes de la configuración de Xcode y escriba el siguiente comando

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

    Recuerde: mantenga ese shell de ejecución antes de la configuración de Xcode en la sección Build de jenkins.

Esto funciona.