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 dedevelopment
,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ónCODE_SIGN_STYLE
para seleccionar entreAutomatic
yManual
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:
-
establezca el perfil de aprovisionamiento en Ninguno en la configuración de compilación del proyecto Xcode.
-
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.