Índice de Contenidos
- Entorno
- Introducción
- Workflow. Partes y sintaxis.
- Configuración y ejecución de un workflow
- Construir la imagen con Docker
- Secretos
- Conclusiones
1. Entorno
Este tutorial ha sido escrito utilizando el siguiente entorno:
- MacBook Pro Retina 15”
- 2,2Ghz Intel Core i7
- 16GB RAM
- macOS Catalina 10.15.7
2. Introducción a Github Actions
Previamente ya se había visto GitHub Actions en algunos tutoriales. Mi intención en este artículo es profundizar un poco en esta tecnología de CI/CD, explicando en qué consiste, para qué surgió y cómo se está utilizando.
Como bien sabemos, la Integración Continua es una práctica que nos requiere añadir frecuentemente nuevo código a un repositorio compartido para detectar errores a la mayor brevedad posible. Para ello Github propuso en 2018 no solo alojar nuestro código en sus repositorios como hemos hecho siempre, sino que además la posibilidad de automatizar los distintos pasos de compilación y test de nuestros proyectos (al igual que ya tenía implementado Gitlab).
Para ello Github Actions ha creado el concepto de workflow el cual es el encargado principal de todo nuestro proceso o Pipeline. Se puede configurar de manera que Github reaccione a ciertos eventos (por ejemplo cuando se hace un nuevo push a una rama), automáticamente de forma periódica o por eventos externos. Especificando en dicho workflow que se analicen los componentes del proyecto, una vez terminados se mostrarán los resultados de los mismos y se podrá comprobar si el cambio en dicha rama ha producido algún error o ha ido todo bien. Este mismo es ejecutado en un runner o instancia en un servidor y Github te da la posibilidad de utilizar un runner hosteado por Github o añadir un host propio.
3. Workflow. Partes y sintaxis.
Para entender bien en qué consiste un workflow, el siguiente esquema muestra las partes que lo componen.
- Workflow: como ya hemos comentado anteriormente, es un procedimiento automatizado el cual se añade a un repositorio. Con él se puede hacer el build, test, package, release o deploy de un proyecto dentro de Github.
- Job: es un conjunto de steps que se ejecutan en runner de nuestro proceso.
- Step: es una tarea individual que puede ejecutar comandos dentro de un job. Un job está formado por uno o más steps y éstos están ejecutados sobre el mismo runner a la hora de ejecutarse el workflow.
- Action: Son los comandos de ejecución del proceso, ejecutados en un step para crear un job. Son el bloque de construcción más pequeño que hay. Puedes crear tus propios actions o utilizar algunos de ellos que ya están creados por la comunidad de Github. Obligatoriamente para utilizar un action en un workflow, éste debe ir incluido en un step.
Para ver un ejemplo más claro de esto se puede tomar un ejemplo de un proyecto Java con Maven muy simple de este enlace o podéis utilizar cualquier proyecto que ya tengáis subido.
Lo primero de todo es crear la propia carpeta en la cual añadiremos el fichero de configuración del workflow. Esta carpeta tiene por norma que llamarse .github/workflows/ . Aquí vamos a crear el fichero workflow.yml (Github Actions utiliza la sintaxis de YAML para especificar la configuración de todo el workflow).
El contenido inicial de nuestro workflow.yml (se le puede poner cualquier otro nombre) es el siguiente:
name: Build and test of Java Project on: [push] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Set up JDK 1.8 uses: actions/setup-java@v1 with: java-version: 1.8 - name: Build with Maven run: mvn -B package --file pom.xml
Entendiendo el fichero por partes:
- “name: Build and test of Java Project”: El nombre opcional que le das al workflow
- “on”: Especifica el evento que automáticamente comienza a ejecutar el fichero de workflow. El ejemplo lo ejecuta gracias al comando push de git sobre nuestro repositorio. Para especificar además la rama o ramas sobre las que nos gustaría que iniciase, sería añadiendo:
on: [push] Branches: [master]
- «jobs»: Sección donde se pueden especificar uno o más jobs.
- «build»: Es el nombre que le hemos dado a nuestro primer y único job. En este caso el nombre sí es obligatorio.
- «runs on: ubuntu-latest»: Configura el workflow para que se ejecute en una instancia de la última versión de ubuntu. Se puede cambiar por otro sistema operativo si quisiéramos: windows-latest, macos-11.0, etc. Aquí se pueden ver los disponibles.
- «steps»: Sección donde se especifican uno o más steps de un único job.
- «uses: actions/checkout@v2»: La palabra clave uses le dice al job de obtener v2 (versión 2, antiguamente se usaba la v1) de la acción de la comunidad de Github llamada actions/checkout. Éste es un action que comprueba nuestro repositorio y lo descarga en nuestro runner o instancia, permitiendo que sobre el código podamos ejecutar el resto de acciones. Es obligatorio añadir este action de checkout las veces que nuestro workflow ejecute sobre nuestro código o se haga uso de un action que hemos definido en otro fichero del repositorio.
- «name: Set up JDK 1.8»: Un nombre opcional que se le ha dado al action.
- «uses: actions/setup-java@v1»: Este action se encarga de descargar e instalar una versión específica de java (java-version: 1.8 como podemos ver) que la comunidad de Github ya ha preparado para poder utilizarse. Aquí se pueden consultar además todas las versiones disponibles y sintaxis adicional.
- «run: mvn -B package — file pom.xml»: La palabra run le dice al job de ejecutar un comando en el runner. En este caso estamos utilizando maven para compilar y empaquetar nuestro proyecto.
4. Configuración y ejecución de un workflow
Ahora para lanzar el workflow y ver los resultados, hacemos push de nuestro proyecto a la rama en la que lo tengamos (no importa la rama pues como no hemos especificado cuál, lo va a lanzar para todas) tras haber creado la carpeta y añadido el fichero de workflow.yml.
git add . git commit -m "Added workflow file to the repository" git push
Justo después, nos dirigimos a la sección de Actions de nuestra página principal del repositorio en Github.
Como vemos, automáticamente se nos ha creado un proceso de workflow llamado «Added workflow file to the repository» y que se está ejecutando. El icono amarillo indica que aún no ha acabado.
Una vez termina satisfactoriamente, tiene que aparecer de la siguiente manera:
Y además se pueden consultar los logs de cada uno de los jobs que lo forman pulsando sobre él y luego seleccionando el job que queremos para ver si se ha ejecutado cada paso que hemos especificado.
Además si en nuestro proyecto hemos añadido Tests, éstos se ejecutarán y se mostrarán sus resultados también:
Si alguno de los tests fallan, el workflow nos aparecería con error y tendríamos que arreglar el test y volverlo a lanzar para que nos aparezcan todos los jobs completados con éxito.
5. Construir la imagen con Docker
Github Actions nos da la posibilidad de correr nuestro entorno en una imagen Docker, con todas las ventajas que ello tiene. Para ello vamos a añadir el siguiente fichero de Dockerfile a la raíz del proyecto el cual nos compila de la misma manera que hacíamos anteriormente:
FROM maven:3.6.0-jdk-8-slim AS build COPY src /usr/src/app/src COPY pom.xml /usr/src//app RUN mvn -B package --file /usr/src/app/pom.xml FROM java:8 EXPOSE 8080 COPY --from=build /usr/src/app/target/project-test-github-1.0-SNAPSHOT.jar /usr/app/project-test-github-1.0-SNAPSHOT.jar ENTRYPOINT ["java","-jar","/usr/app/project-test-github-1.0-SNAPSHOT.jar"]
Una vez añadido el fichero, tenemos que modificar nuestro workflow.yml para indicar que queremos utilizar Docker a través de un Dockerfile, quedando de la siguiente manera:
name: Build and test of Java Project on: [push] jobs: build: name: Build with Docker runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Building the image from the Dockerfile uses: ./.github/action-docker
Como se puede ver ha disminuido bastante el tamaño del fichero manteniendo el sistema operativo de ubuntu-latest que Github nos proporciona ya que cuenta con Docker instalado. Aparte del action de checkout únicamente añadimos otro nuevo action que hace referencia a una nueva carpeta que hemos creado llamada action-docker. En esta carpeta vamos a añadir otro YAML con el action que especifica que queremos hacer uso del Dockerfile.
Es muy importante saber que el YAML tiene que llamarse action.yml o action.yaml sino no nos funcionará. En este enlace se puede consultar la sintaxis de Github Actions para los ficheros YAML.
El action.yml para que nos ejecute nuestra imagen Docker bastaría con añadirlo como:
name: "Using Docker" runs: using: "docker" image: "../../Dockerfile"
Indicando en «image» donde tenemos nuestro Dockerfile nos lo utilizará para crear la imagen. Si ahora hacemos push de todo esto y no nos hemos equivocado en nada, en los logs de nuestro wokflow del apartado de Actions nos muestra cómo compila igual que antes en una imagen Docker.
6. Secretos
Los secretos de Github Action nos permiten almacenar información sensible en nuestro repositorio para luego poder usarlo en nuestros procesos de workflow. Son variables de entorno encriptadas por Github, haciendo uso de libsodium sealed box para asegurar que la información de los secretos se aseguran antes de siquiera ser parte de los repositorios de Github y por supuesto mientras se utilizan en cualquiera de los workflows.
Para añadir un secreto a nuestro repositorio:
- Navegamos al menú principal del repositorio.
- Debajo del nombre del repositorio, seleccionamos Settings.
- En el menú de la izquierda seleccionamos Secrets y a continuación nos sale el botón New secret para añadir un nuevo secreto.
4. Añadimos nombre y valor y pulsamos sobre Add secret. Ahora ya nos aparece creado y listo para poder añadirlo a nuestros pipelines.
7. Conclusión
Github nos ofrece una herramienta muy interesante para la integración continua de nuestros proyectos en sus repositorios de una manera muy similar como ya nos trajo Gitlab hace unos años. Ambos funcionan muy parecido y consiguen el mismo resultado de una manera muy clara y sin salirnos de la misma página principal de nuestro repositorio. En este tutorial hemos visto cómo podemos crear nuestro workflow con las actions fácilmente para integrar continuamente los cambios en nuestros proyectos y cómo éste viene perfectamente integrado en el repositorio para comprobar que los cambios son aceptables.
Cualquier duda o aportación no se dude en añadirla a los comentarios.