Introducción
La ingeniería de software es un campo competitivo y de ritmo rápido. Lanzar sus productos a los usuarios más rápido le dará una ventaja sobre sus competidores. Por el lado positivo, existen mejores prácticas de la industria para ayudar a las empresas a competir en igualdad de condiciones.
La integración continua y el desarrollo continuo (CICD) es un ejemplo de una estrategia que aprovecha las mejores prácticas de la industria para dar a las empresas una ventaja en este campo competitivo.
GitHub, un repositorio basado en la web con Git, una herramienta de control de versiones, permite a los desarrolladores, ingenieros y arquitectos de software implementar CI/CD. El desarrollo continuo (CD) es la práctica de automatizar compilaciones, pruebas y despliegues. La integración continua (CI) permite que muchas personas colaboren en el mismo proyecto y verifiquen que el código funciona sin preocuparse por los conflictos de fusión.
GitHub Actions nos permite escribir pasos que automatizan las compilaciones, pruebas y despliegues.
En este tutorial, aprenderá cómo configurar la integración continua con GitHub Actions. Comenzaremos configurando un repositorio Git para alojar nuestro código. Luego, configuraremos un proceso de CI de GitHub para monitorear los cambios en nuestro código, iniciar un runner de CI para realizar pruebas, compilar y desplegar nuestra aplicación en un servidor Ubuntu 22.04 que ejecuta Nginx.
Requisitos previos
Para seguir este tutorial, necesitará lo siguiente:
-
Un servidor que ejecute Ubuntu 22.04. Puede seguir este tutorial para la configuración inicial del servidor Ubuntu, agregar un usuario no raíz, y habilitar el cortafuegos UFW de Ubuntu.
-
Necesitará tener instalado Node.js en su servidor, preferiblemente la versión 14 o superior. Tenemos un tutorial sobre cómo instalar Node.js en Ubuntu.
-
Necesitará tener instalado el software de servidor Nginx. Tenemos una guía sobre Cómo instalar Nginx en un servidor que ejecuta Ubuntu.
-
Necesitará Docker y Docker Compose instalado en su máquina local para ejecutar un entorno de desarrollo aislado. Siga nuestro tutorial para aprender Cómo instalar y operar Docker en la nube.
Ahora que tenemos todo lo que necesitamos, comencemos.
Paso 1. Clonar el repositorio del proyecto.
Vamos a basar este tutorial en Reactjs, una biblioteca declarativa de JavaScript para crear interfaces de usuario. Si desea configurar un nuevo proyecto desde cero, puede utilizar este recurso sobre cómo configurar una aplicación React. Para abreviar, utilizaremos un clon de este repositorio de React.js que ya configuramos en GitHub.
La aplicación que estamos clonando es una aplicación React simple con react-router 6 y una prueba realizada con React Testing Library, que nos proporciona métodos para acceder al DOM.
Para clonar el repositorio, haga clic en el botón verde y copie la URL.

Abra la terminal en su espacio de trabajo y ejecute el siguiente comando para clonar la aplicación:
|
1 |
git clone git@github.com:EspiraMarvin/cicd-tut.git |
Una vez que haya clonado el repositorio, navegue al directorio del proyecto:
|
1 |
cd cicd-tut |
Ejecute el comando docker-compose up para compilar y ejecutar la aplicación:
|
1 |
docker-compose up --build --force-recreate |
Cuando se complete el proceso, visite http://localhost:3000
Debería ver algo similar a esto:

Paso 2. Comprender el archivo Node.js.yml.
En este paso, definiremos las directivas en el archivo YAML de GitHub para ayudarnos a comprender qué está sucediendo. En el repositorio, hay un directorio .github/workflows que contiene un node.js.yml que tiene pasos de flujo de trabajo que los runners de GitHub siguen después de que usted envíe los cambios a su repositorio de código en GitHub. YAML se utiliza para escribir flujos de trabajo para GitHub Actions. Los archivos YAML terminan con una extensión yaml o yml.
Abra el node.js.yml archivo, debería verse así:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
name: cicd-tut on: push: branches: [ "main" ] pull_request: branches: [ "main" ] jobs: build: # El tipo de runner en el que se ejecutará el trabajo runs-on: self-hosted strategy: matrix: node-version: [16.x] # Los pasos representan una secuencia de tareas que se ejecutarán como parte del trabajo steps: - name: 'checkout' uses: actions/checkout@v3 - name: 'configurar acciones de node' uses: actions/setup-node@v3 with: node-version: "16" cache: 'npm' - run: npm i - run: npm test - run: npm run build # - run: cp -r ~/actions-runner/cicd-react/react-tut-test/react-tut-test/build /var/www/react-cicd |
Al momento de escribir este tutorial, estábamos usando la versión 16 de Node.js 16. Ahora, comprendamos el flujo de trabajo de GitHub Actions:
-
name
name: cicd-tut
El nombre de su flujo de trabajo, este nombre se mostrará en su repositorio Actions pestaña.
-
on
|
1 2 3 4 5 |
on: push: branches: [ "main" ] pull_request: branches: [ "main" ] |
on se utiliza para definir eventos. Los eventos pueden activar automáticamente un flujo de trabajo o programarse para más adelante. Los eventos pueden ser únicos o múltiples, también puede especificar ejecuciones de flujo de trabajo para ramas, etiquetas o archivos específicos. Esto funciona como un filtro.
En nuestro archivo YAML estamos definiendo múltiples eventos automáticos, estos son:
-
Un push evento se activa cuando se realiza un commit de código en un repositorio
-
Un pull_request evento se activa cuando se crea una pull request en la rama main.
Estamos especificando un nombre de rama main para restringir la ejecución del flujo de trabajo únicamente a esa rama. También podemos especificar ramas que se ignorarán utilizando la bandera ! seguida del nombre de la rama.
-
jobs
Un flujo de trabajo se compone esencialmente de uno o varios trabajos. Estos trabajos se ejecutan en sucesión desde el primero hasta el último.
|
1 2 3 4 |
jobs: build: # El tipo de runner en el que se ejecutará el trabajo runs-on: self-hosted |
Cada trabajo se ejecuta en un entorno de runner especificado por runs-on. Puede elegir ejecutar trabajos ya sea en runners de GitHub indicados por ubuntu-latest o en un runner self-hosted indicado por self-hosted. Su elección dependerá de la cantidad de trabajos que necesite. Con los runners autohospedados (self-hosted), tiene más flexibilidad y control de los recursos.
En nuestro siguiente paso, primero ejecutaremos nuestros trabajos en runners de GitHub, luego, más adelante, configuraremos un runner autohospedado de GitHub en nuestro propio servidor.
-
strategy
Strategy nos permite usar variables en una sola definición de trabajo para crear automáticamente múltiples ejecuciones de trabajo que se basan en las combinaciones de variables.
En nuestro archivo YAML, tenemos una variable para nuestra node-version, pero si agregamos otra para la versión 18 de node, así: node-version: [16.x, 18.x], entonces la estrategia matrix creará 2 ejecuciones de trabajo para nuestra aplicación react tanto para las versiones de node 16 como 18.
|
1 2 3 |
strategy: matrix: node-version: [16.x] |
-
steps
Los pasos (steps) son una secuencia de tareas que componen un trabajo. Los pasos pueden ejecutar comandos, configurar tareas, ejecutar acciones en su repositorio público o acciones publicadas en un registro de docker.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
steps: - name: 'checkout' uses: actions/checkout@v3 - name: 'configurar acciones de node' uses: actions/setup-node@v3 with: node-version: "16" cache: 'npm' - run: npm i - run: npm test - run: npm run build |
Un paso tiene un nombre. Aunque es opcional, puedes usarlo para especificar una forma fácil de identificar el nombre de tu paso que se mostrará en GitHub.
En un paso, puedes seleccionar una acción para ejecutar en tu trabajo; las acciones son reutilizables. Las versiones de la acción se especifican al definir una acción, esto es importante ya que evita que tu flujo de trabajo se rompa cuando el propietario de la acción publica una actualización.
En el fragmento de código anterior, checkout@v3 es un ejemplo de una acción con una versión especificada 3. Esta acción hace checkout de tu repositorio para que tu flujo de trabajo pueda acceder a él.
Algunas acciones como actions/setup-node@v3 anteriores tienen entradas indicadas mediante la palabra clave with, las acciones de configuración de node requieren la versión 16 de node y que npm esté en caché.
-
run
Esta acción ejecuta programas de línea de comandos utilizando el shell del sistema operativo.
En el archivo YAML anterior, tenemos tres comandos, todos se ejecutarán utilizando el mismo shell en el entorno del runner.
-
El primer comando npm i instala todas las dependencias necesarias para nuestra aplicación de React.
-
El segundo npm test, ejecuta la prueba que hemos escrito. La prueba espera que el texto learn react se renderice en la página de inicio (Home).
-
Por último, npm run build crea un directorio de compilación (build) con una versión de producción de nuestra aplicación. Más adelante, utilizaremos este directorio de compilación en nuestro bloque de servidor Nginx.
Paso 3. Probar GitHub CI con GitHub Runners.
En este paso, probaremos el proceso de Integración Continua con los runners de GitHub. Comienza abriendo el archivo node.js.yml. Modifica el tipo de runner en el que se ejecutarán las acciones a ubuntu-latest. El propósito de esto es probar si el flujo de trabajo de GitHub funciona perfectamente en los runners de GitHub antes de configurar nuestros propios runners autohospedados (self-hosted).
|
1 2 3 |
jobs: build: runs-on: ubuntu-latest |
Crea un nuevo repositorio en tu cuenta de GitHub. Antes de continuar, regresa al directorio de tu espacio de trabajo y elimina el directorio .git, si no puedes verlo, revisa tus archivos ocultos. Puedes usar el siguiente comando en tu terminal para eliminar el directorio:
|
1 |
rm -rf .git |
Ahora puedes hacer git add de todos los archivos de tu proyecto, commit y push a tu repositorio. Si te quedas atascado, usa esta guía sobre cómo conectar la carpeta de tu proyecto al repositorio de GitHub que creaste anteriormente.
Cuando hayas terminado, haz clic en la pestaña Code, y verás un pequeño punto naranja al lado del recuento total de commits. Al hacer clic en él, verás un modal similar al de abajo, que indica que tu flujo de trabajo se ha puesto en cola:

Ahora haz clic en el enlace Details en el modal o ve a la pestaña Actions, verás cada paso del flujo de trabajo node.js.yml siendo ejecutado por los runners de GitHub:

Si tiene éxito, haz clic en la pestaña Actions, debería verse así:

Y eso es todo, el pequeño punto naranja en nuestra pestaña Code ahora debería ser una marca de verificación verde. El runner de GitHub ha compilado nuestra aplicación con éxito.
Ahora, vayamos un paso más allá y cambiemos el entorno de compilación para usar runners autohospedados (self-hosted) de GitHub en nuestra propia infraestructura de servidor Ubuntu.
Paso 4. Configurar el flujo de trabajo de GitHub para usar un runner autohospedado.
Antes de instalar el runner autohospedado en nuestro servidor, regresemos a nuestro espacio de trabajo y editemos el archivo de flujo de trabajo node.js.yml para que se ejecute en runners autohospedados de GitHub.
|
1 2 3 |
jobs: build: runs-on: self-hosted |
En esta etapa, cuando confirmes los cambios, el trabajo se pondrá en cola ya que no se ha definido un runner autohospedado.
En tu repositorio, haz clic en la pestaña
Settings, en la barra lateral izquierda haz clic en
Actions, luego haz clic en
Runners:

Haz clic en New self-hosted runner, y selecciona Linux como sistema operativo.
Verás instrucciones que te muestran cómo descargar el runner e instalarlo en tu servidor.
Paso 5. Instalar y configurar un runner autohospedado de GitHub en nuestro servidor.
En este paso, configuraremos un runner autohospedado de GitHub. Un runner autohospedado es un sistema que puede implementar y administrar la ejecución de trabajos de GitHub Actions en el sitio web de GitHub. Una ventaja que tiene el runner autohospedado sobre el runner hospedado por GitHub es la flexibilidad. Ofrece más control sobre el sistema operativo, el hardware y otras herramientas que se pueden personalizar para satisfacer las necesidades de su aplicación.
Los runners autohospedados se pueden agregar en varios niveles, tales como:
-
Runners a nivel de repositorio, estos están dedicados a un solo repositorio.
-
Runners a nivel de organización, estos pueden procesar trabajos para múltiples repositorios en una organización.
-
A nivel de empresa, que se pueden asignar a múltiples organizaciones.
Para continuar, inicie sesión en su servidor a través de ssh:
|
1 |
ssh username@server_ip |
Cambie a su directorio de inicio con el comando:
|
1 |
cd ~ |
Luego, cree un directorio llamado action-runners y navegue dentro de él:
|
1 |
mkdir actions-runner && cd actions-runner |
A continuación, descargue la última versión del paquete del runner:
|
1 |
curl -o actions-runner-linux-x64-2.298.2.tar.gz -L https://github.com/actions/runner/releases/download/v2.298.2/actions-runner-linux-x64-2.298.2.tar.gz |
Luego extraiga el paquete descargado con el comando:
|
1 |
tar xzf ./actions-runner-linux-x64-2.298.2.tar.gz |
De vuelta en su repositorio, en la pestaña Settings , en el panel lateral izquierdo haga clic en Actions, luego en Runners, tal como lo hicimos en el Step 4.
Verá un comando en la lista que incluye un token que vincula su runner autohospedado a su repositorio de GitHub. Mientras esté dentro del directorio en el que extrajo el código del runner de GitHub, use el comando de la lista para vincular su runner, por ejemplo:
|
1 |
./config.sh --url https://github.com/EspiraMarvin/react-tut-test --token XXXXXXXXXXXXXXXXXXXXXXXXXXX |
Debería autenticarse con éxito:

Presione enter para el grupo de runner predeterminado (Default).
Luego ingrese un nombre para su runner, por ejemplo, my-runner, y presione enter.
Presione Enter para omitir la adición de etiquetas adicionales, debería ver el mensaje de éxito en la captura de pantalla a continuación:

Ingrese el nombre de su directorio de trabajo, por ejemplo, react-cicd, debería completarse con éxito con el texto settings saved.
Finalmente, ejecute ./run.sh, esto debería mostrar Connected to Github:

Pero esto no se ejecuta en segundo plano, si escribimos ctrl+c en nuestra terminal, el runner se detendrá, necesitamos reemplazarlo con el servicio .svc.sh para mantener el runner ejecutándose como un servicio y así poder continuar interactuando con él.
Detenga el runner con ctrl+c. Puede instalar el servicio .svc.sh ejecutando el comando:
|
1 |
sudo ./svc.sh install |
Una vez instalado, inicie el servicio con el comando:
|
1 |
sudo ./svc.sh start |
Esto debería completarse con éxito, mostrando active (running).
Para confirmar que el servicio svc.sh está activo y funcionando, ejecute el comando:
|
1 |
sudo ./svc/sh status |

En este punto, cualquier flujo de trabajo que haya estado en cola esperando un runner autohospedado debería ejecutarse con éxito. También puede editar un archivo y probar cosas. Por ejemplo, modifique el archivo Acerca de.tsx, confirme (commit) y envíe (push) los cambios, el runner autohospedado completará el trabajo con éxito.
Paso 6. Configuración del bloque de servidor de Nginx
En este paso, configuraremos un bloque de servidor en Nginx para ver la versión de compilación de nuestra aplicación React. Tenemos un tutorial sobre Configuración de bloques de servidor de Nginx que puede resultarle útil.
A continuación se muestra un ejemplo de un bloque de servidor utilizado en este tutorial:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
server { listen 80; listen [::]:80; server_name react.test; root /var/www/react-cicd/build; index index.html index.htm index.nginx-debian.html; add_header X-Frame-Options "SAMEORIGIN"; add_header X-XSS-Protection "1; mode=block"; add_header X-Content-Type-Options "nosniff"; charset utf-8; location / { try_files $uri $uri/ =404; } } |
Creará un archivo de configuración de bloque de servidor Nginx dentro del /etc/nginx/sites-available directorio.
Abra un archivo para la configuración del bloque de servidor de su sitio con el editor nano usando el comando:
|
1 |
sudo nano /etc/nginx/sites-available/react-cicd |
Copie el bloque de servidor compartido anteriormente, modifíquelo de acuerdo con las rutas de sus directorios y péguelo en el archivo abierto. Cuando haya terminado de editar, presione ctrl+x luego presione y y enter para guardar y salir.
Una vez guardado, cree un enlace simbólico para la configuración del bloque de servidor react-cicd desde /etc/nginx/sites-available a /etc/nginx/sites-enabled ejecutando el comando:
|
1 |
sudo ln -s /etc/nginx/sites-available/react-cicd /etc/nginx/sites-enabled/ |
Para que los cambios surtan efecto, debe reiniciar Nginx. Sin embargo, antes de poder reiniciar el servicio Nginx, pruebe si las configuraciones de Nginx son válidas ejecutando el comando:
|
1 |
sudo nginx -t |
Si la configuración es correcta, la prueba debería ser exitosa.
Observe el valor de la directiva server_name “ react.test ” en el bloque de servidor? Agregará este valor en su archivo hosts en su máquina local. Esto le permitirá abrir la aplicación en su navegador. Este paso solo es necesario para dominios virtuales utilizados en entornos de desarrollo local. Si tiene un nombre de dominio registrado vinculado a una IP pública de su servidor, entonces el nombre de dominio ya debería estar accesible en su navegador.
En su máquina local, abra el archivo hosts con el comando:
|
1 |
sudo nano /etc/hosts |
Dentro del archivo hosts, agregue la dirección IP de su servidor, por ejemplo, 127.0.0.1, seguido de su nombre de dominio virtual.
A continuación se muestra un ejemplo. Luego cierre el archivo y guarde:
|
1 |
192.168.3.123 react.test |
De vuelta en su servidor, dentro del directorio /var/www , cree un nuevo directorio, puede llamarlo react-cicd ejecutando:
|
1 |
mkdir react-cicd |
En esta etapa, descomentaremos el último comando en el archivo node.js.yml .
Este comando copia la carpeta build de nuestra aplicación react desde donde especificamos nuestra carpeta de trabajo dentro del directorio actions-runner en el paso 5.
Y coloca la carpeta public en el directorio /var/www/react-cicd .
El bloque de servidor ahora puede acceder a nuestra aplicación y mostrarla en un navegador.
Por último, reinicie el servicio Nginx con el comando:
|
1 |
sudo service nginx restart |
Ahora, puede realizar un cambio en el archivo Acerca de.tsx , luego confirme y envíe sus cambios a su repositorio. Después de una compilación exitosa, verá la versión compilada de su aplicación react en http://react.test o en el nombre de dominio que especificó. Evite editar el elemento href en el archivo Home.tsx ya que puede hacer que la prueba ya escrita falle. La pestaña Actions en su repositorio también debería mostrar la compilación del trabajo completada.

Conclusión
La integración continua con Github Actions tiene muchas ventajas, incluyendo una buena experiencia de desarrollo, ayuda con las pruebas continuas, permite colaboraciones más sencillas en equipos más grandes, acorta el tiempo de desarrollo, lanzamientos rápidos de nuevas funciones, comentarios en tiempo real y satisfacción del cliente, dándole una ventaja sobre sus competidores. Para ampliar este conocimiento, es posible que también desee aprender sobre Configuración de pipelines de integración continua (CI) de GitLab en Ubuntu. y a utilizar una instancia de GitLab autogestionada para alojar sus imágenes de Docker y ejecutar compilaciones privadas.
¡Feliz computación!
Comentarios
Aún no hay comentarios. Sea el primero.