Requisitos
- Proceso automatizado
- 5 plataformas principales ahora (iOS, Android, Windows, Linux, WebGL)
- Posibilidad de compilar para otras plataformas en un futuro próximo (Nintendo, PlayStation, XBox, Stadia, etc.)
- Flexibilidad para integrarse con otros servicios
- Menor costo posible
Después de evaluar la infraestructura actual de la empresa y las ventajas y desventajas de utilizar servicios como Unity Builder, decidimos desarrollar los procesos de automatización en Jenkins. Al adoptar este enfoque, logramos todos los requisitos de la tarea, ya que Jenkins nos permitirá:
- Automatizar los pasos necesarios para generar los ejecutables.
- Generar ejecutables para todos las plataformas deseadas (5 plataformas principales y otras plataformas), actualmente en Unity Builder no es posible trabajar con las plataformas adicionales.
- Lograr una mayor rentabilidad mediante el uso de nodos dinámicos que serán destruidos después de que finalice el proceso de ejecución. Unity Builds usa una estrategia similar, pero el costo total es un poco mayor.
Ahora que tenemos nuestro plan definido, pongámonos manos a la obra y preparemos nuestro archivo de Jenkins. En esta publicación hacemos las siguientes suposiciones:
- Tienes una instancia de Jenkins y conocimientos básicos de algunos conceptos de Jenkins.
- El sistema operativo del nodo donde se ejecutaran los trabajo es Windows.
- Su máquina de trabajo tiene Android Studio instalado.
- Su máquina trabajadora tiene Unity Hub instalado.
- Tiene una licencia de Unity, pro o plus.
Plataforma Android
Configuración de Android Studio
- Abrir la configuración de Android Studio
- Agregue las versiones de API (Niveles) que necesita que su aplicación soporte
Configuración de Unity Hub
- Vaya a la sección de instalación en el panel izquierdo
- Haga clic en ADD y seleccione la versión recomendada
- Una vez instalada la versión de Unity, haga clic en los 3 puntos sobre la versión y seleccione Add Modules
- Instale Android Build Support y haga clic en Done
Crear el Jenkinsfile
- Primero necesitamos crear el archivo Jenkins que contendrá los pasos necesarios para generar nuestra compilación.
pipeline { // Definición de variables de entorno que se pueden usar a lo largo del trabajo environment { } // Opciones: agregar marca de tiempo a los logs de trabajos y limitar la cantidad de compilaciones que se deben mantener. options { } // Variables que modifican el comportamiento del trabajo parameters { } // Selector del agente que ejecutará el trabajo agent { } // Los pasos necesarios para generar la aplicación deseada stages { } // Cualquier acción que queramos realizar después de que todos los pasos hayan tenido éxito o hayan fallado post { } }
- A continuación, definamos nuestras variables ambientales, opciones de configuración, parámetros de compilación, agente de compilación y acciones post trabajo.
pipeline { // Definición de variables de entorno que se pueden usar a lo largo del trabajo environment { // Github data String gitUrl = "[email protected]:GekoCloud/unity_build_demo.git" String gitCredentials = "jenkins-private-key" // configura una credencial (PrivateKey) si tu repo es privado. // Unity UNITY_EXECUTABLE = "C:\\Path\\A\\TU\\Version\\Unity\\2020.3.16f1\\Editor\\Unity.exe" // Unity data UNITY_ID_EMAIL = credentials('jenkins-id-for-unity-email') UNITY_ID_PASSWORD = credentials('jenkins-id-for-unity-password') UNITY_ID_LICENSE = credentials('jenkins-id-for-unity-license') // Unity parametros BUILD_NAME = "Android-${currentBuild.number}" String buildTarget = "Android" String outputFolder = "CurrentBuild" // PARAMETERS DATA IS_DEVELOPMENT_BUILD = "${params.developmentBuild}" // Agregar mas variables de entorno } // Opciones: agregar marca de tiempo a los logs de trabajos y limitar la cantidad de compilaciones que se deben mantener. options { timestamps() buildDiscarder(logRotator(numToKeepStr: "10")) } // Variables que modifican el comportamiento del trabajo parameters { string(name: 'gitBranch', defaultValue: 'development', description: 'Set the branch.') booleanParam(name: 'developmentBuild', defaultValue: true, description: 'Choose the buildType.') } // Selector del agente que ejecutará el trabajo agent { node { // El nodo de Jenkins que se utilizará debe tener la etiqueta android label "android" } } // Los pasos necesarios para generar la aplicación deseada stages { } // Cualquier acción que queramos realizar después de que todos los pasos hayan tenido éxito o hayan fallado post { success { echo "Funcionó :)" } failure { echo "NO Funcionó :(" } } }
- Ahora que tenemos una estructura general básica, definamos las diferentes etapas/pasos que nos permitirán crear la aplicación deseada.
- Descargar el código de nuestra aplicación de nuestro repositorio de código.
stage('Git Pull') { steps { echo "Git pull repo" script { try { git url: "${gitUrl}", branch: "${gitBranch}", credentialsId: "${gitCredentials}" } catch (e) { currentBuild.result = "FAILED" echo "JOB FAILED: The selected branch does not exists." } } } }
-
- Activar nuestra licencia de Unity en la máquina.
stage('Activate License') { steps { script { echo "Activate License..." bat '%UNITY_EXECUTABLE% -nographics -projectPath %CD% -quit -batchmode -username %UNITY_ID_EMAIL% -password %UNITY_ID_PASSWORD% -serial %UNITY_ID_LICENSE%' } } }
-
- Ejecutar el comando de compilación.
stage('Build Application') { steps { script { echo "create Application output folder..." bat 'mkdir %outputFolder%' echo "Buld App..." bat '%UNITY_EXECUTABLE% -projectPath %CD% -quit -batchmode -nographics -buildTarget %buildTarget% -customBuildPath %CD%\\%outputFolder%\\ -customBuildName %BUILD_NAME% -executeMethod BuildCommand.PerformBuilds' } } }
El argumento -executeMethod BuildCommand.PerformBuilds, nos permite ejecutar funciones definidas en un script de C# (El archivo BuildCommand.cs debe estar ubicado en la carpeta Assets/Scripts/Editor de tu proyecto y puedes ver un ejemplo BuildCommand, que realizará las diferentes configuraciones que generalmente se realizan manualmente en la IDE de Unity. Para obtener más información sobre las opciones que se pueden configurar, visite la documentación de la api de unity.
-
- Desactivar nuestra licencia de Unity en la máquina donde se ejecuta el trabajo de Jenkins.
post { always { script { echo "Return License..." bat '%UNITY_EXECUTABLE% -nographics -quit -batchmode -returnlicense -username %UNITY_ID_EMAIL% -password %UNITY_ID_PASSWORD%' } } }
Esto solo es necesario si ejecuta sus cargas de trabajo en máquinas efímeras, ya que la licencia de unity no se libera automáticamente cuando se termina la máquina que ejecuta el trabajo. Además, esto no se ejecuta como una etapa porque necesitamos liberar la licencia si el trabajo falla o tiene éxito.
Una vez que haya terminado su Jenkinsfile (puede ver el archivo completo aqui: Jenkinsfile) y su script BuildCommand se haya agregado a su proyecto, puede crear un trabajo de pipeline en su instancia de Jenkins y apúntarlo a su Jenkinsfile. Nota: Dado que está publicación fue pensada como guía y no como una demo, es posible que deban realizarse algunos cambios para su proyecto específico.
Para resumir, Unity permite a los desarrolladores definir configuraciones de compilación al proporcionar una API de configuración muy extensa, mientras que Jenkins permite a los equipos de devops ejecutar estas compilaciones automatizadas en procesos de CI/CD, que adicionalmente pueden incluir todo tipo de pasos adicionales: subir a buckets S3, monitorear logs de compilación generados, etc. Si tiene problemas para configurar la infraestructura para ejecutar sus pipelines de compilación, contáctenos y podríamos ayudarte con eso 😁.