En el transcurso del desarrollo de una aplicación web para un cliente, nos encontramos con la necesidad de levantar un servidor y poblarlo con el estado actual. Así, puede consultar el avance en el desarrollo y proporcionarnos feedback. Aunque es posible realizarlo manualmente, su automatización nos evita problemas puntuales por errores humanos al desplegar.

Crear un proyecto en React

Comenzaremos creando un proyecto en React haciendo uso de Create React App, un paquete que nos permite crear un proyecto en React con los elementos básicos para comenzar a desarrollar al momento.

Para utilizar este paquete deberemos tener previamente instalado npm y ejecutar las siguientes lineas en nuestro terminal.

#Para instalar el paquete:
npm create-react-app -g
#Para crear proyecto llamado “react-app”:
create-react-app react-app

npx

Si contamos con la versión 5.6 de npm o superior, podremos hacer uso de npx, un comando que se utiliza de forma idéntica a npm con el que podremos descargar y ejecutar paquetes sin tener que instalarlos en el sistema.

Utilizar este comando, en lugar del clásico npm, puede ser muy beneficioso cuando es utilizado sobre paquetes que no son utilizados con cierta asiduidad, para evitar desbordar nuestro ordenador con paquetes que no vayamos a utilizar mas de una vez.

#Para crear nuestro proyecto con npx:
npx create-react-app react-app
#Si queremos actualizar npm para contar con el comando npx:
npm install npm -g

Probar el proyecto

Además de crear nuestro proyecto, Create-react-app también pone a nuestra disposición unos scripts, alojados en nuestro proyecto, que pueden sernos de mucha utilidad durante el desarrollo y el despliegue del mismo.

Los que nos interesan en esta ocasión son dos: start y build.

El primero levanta un servidor en local que nos permitirá probar la web y que, ademas, cuenta con hot-reloading, un sistema que provoca que el servidor por lo que cualquier cambio en el proyecto que se guarde provocará que la página actual se actualice automáticamente mostrando el estado actual de la web.

Con respecto al segundo, build, será el comando que deberemos utilizar para generar un código a partir del nuestro, completamente optimizado y preparado para el despliegue. Nuestro código, no solo no es recomendable que sea utilizado para desplegarlo en el servidor de producción por la cantidad de archivos innecesarios que se subirían al mismo, si no que ni siquiera podrá ser utilizado para ello, puesto que su index no se encuentra en la raíz del proyecto.

Una vez el script haya concluido su trabajo, en la raíz de nuestro proyecto se creará una carpeta “build” con nuestro proyecto y con la cantidad de archivos mínima necesaria para el buen funcionamiento de nuestra web.

Ambos scripts podrán ser ejecutados con npm de la siguiente manera:

npm react-scripts start
npm react-scripts build

Por último, deberemos crear un repositorio en GitHub, donde almacenaremos nuestro código y desde donde se extraerá el código para poblar nuestro servidor de AWS.

Preparar S3 de AWS para hospedar nuestra web

Terminada la preparación de nuestro proyecto, nuestro siguiente paso consistirá en preparar los servidores para hospedar la web.

En este caso concreto haremos uso de dos servidores: uno servirá para hospedar la versión que se encuentre en la rama develop de nuestro repositorio de GitHub. El otro, hospedará la de master, por lo tanto, este ultimo será nuestro servidor de producción.

Dado que la web que vamos a hospedar es estática, utilizaremos el servicio S3 de AWS. Es posible acceder a él desde la pestaña “services” que encontraremos en la cabecera una vez hayamos iniciado sesión en la pagina de AWS.

Una vez en la consola de S3, podemos comenzar a crear nuestro primer servidor haciendo click en Create bucket. Esto nos abrirá un formulario en el que solo rellenaremos el nombre del bucket (que deberá ser único) y la región, donde escogeremos por conveniencia la mas cercana.

En la última página del formulario se nos mostrara un resumen con todas las opciones elegidas, las cuales deberían ser parecidas a las siguientes:

Una vez creado, su nombre nos aparecerá listado y podremos entrar en él haciendo clic sobre su nombre, donde podremos ver sus contenidos y modificar algunos comportamientos.

Por el momento, lo que hemos creado ha sido un servidor que sirve para almacenar y compartir archivos, pero no para hospedar una web. Para ello, debemos introducirnos en el bucket recientemente creado e ir a la pestaña “Properties”. Allí nos encontraremos una card en la que puede leerse Static website posting. Haciendo clic en ella nos aparecerán las siguientes opciones:

Nosotros deberemos marcar la opción que aparece en la imagen así como escribir el nombre del documento que queremos que actúe como indice, index.html en la mayoría de los casos, incluido el nuestro.

A continuación guardamos los cambios, no sin antes copiar el enlace del servidor, que utilizaremos al finalizar el sistema de integración continua para comprobar que los cambios que hagamos se suban al servidor.

Crear usuario IAM en AWS

Antes de meternos en profundidad con Travis, tenemos que llevar a cabo un último paso con nuestra cuenta de AWS.

Cuando, mas adelante, travis quiera llevar todos los cambios realizados sobre nuestro repositorio al servidor correspondiente, este necesitará unos permisos para poder conectarse a nuestra cuenta de AWS automáticamente y haga las operaciones necesarias. Sin embargo, por tema de seguridad, siempre es recomendable hacer uso del llamado usuario IAM.

Un usuario IAM es un usuario que puede ser creado desde tu propia cuenta de AWS, donde puedes establecer los permisos inherentes a dicho usuario (a que servicios puede acceder y que grado de libertad tiene el usuario a la hora de manipular el servicio en cuestión).

Para crear un usuario IAM basta con entrar en el siguiente enlace: https://console.aws.amazon.com/iam/home#/home

Una vez allí haremos clic en Users, donde además se nos indica el numero de usuarios que tenemos creados actualmente, y nos llevará a la siguiente pagina, en la que aparecen listados todos los usuarios creados y en la que contamos con un botón para añadir uno nuevo.

Haciendo clic en dicho botón nos abrirá un formulario que deberemos rellenar: en el apartado de Access type marcaremos la opción Programmatic access. En permisos, la siguiente página, deberemos crear un grupo si no contamos con uno actualmente. Para crear un grupo, haremos clic en Create group y rellenaremos los campos tal y como se aprecia en la imagen con el fin de proporcionar un acceso completo al servicio S3.

Cuando el grupo haya sido creado, este puede ser seleccionado para nuestro usuario y finalizar su creación.

Una vez creado, aparecerán las Access key ID y Secret access key que debemos guardar por ser indispensables para utilizar Travis.

Conectar TravisCI con GitHub y AWS

En este ultimo apartado, configuraremos Travis para que trabaje como mejor se adapte a nuestras necesidades y lo conectaremos con Github y AWS.

Para comenzar con la configuración, iniciaremos sesión en su pagina web con nuestra cuenta de Github. Tras ello, accederemos a un dashboard en la que podremos visualizar tanto nuestros repositorios como aquellos ajenos con los que tengamos alguna clase de permiso.

Haciendo clic en el repositorio creado anteriormente nos aparecerá la opción de dar permisos a travis de gestionar el repositorio en cuestión. Con esto, Travis estaría preparado para recibir nuestras instrucciones desde nuestro repositorio y funcionar automáticamente siguiendo dichas instrucciones. Solo nos faltaría crear un archivo yml, llamado .travis.yml, donde deberán estar escritas las instrucciones antes mencionadas.

Archivo de configuración TravisCI

Comenzaremos indicando que lenguaje deseamos que Travis utilice. Dado que mas adelante necesitaremos que Travis ejecute unos scripts con el gestor de paquetes npm, elegiremos el lenguaje node js. Para ello escribiremos la siguiente linea en nuestro archivo de configuración:

language: node_js

Por defecto, Travis utilizará la ultima versión estable del lenguaje. Si por alguna razón fuese necesario utilizar otra versión, es posible indicar el numero de versión requerida. Para evitar problemas, también podemos solicitarle explícitamente que la versión utilizada sea la última estable, simplemente añadiendo la siguiente linea debajo de la anterior:

node_js:
- "stable"

Una etiqueta, que no es en absoluto necesaria pero que creemos que en este caso podría resultar muy útil, es la etiqueta cache, la cual se utiliza para indicar los directorios y archivos que se desean conservar en caché con el fin de ahorrar tiempo la próxima vez que travis vaya a ejecutarse. Esto es utilizado normalmente con el directorio note_modules, ya que desde una ejecución a otra normalmente no cambian y el evitar descargar todos los archivos cada vez ahorra una inmensa cantidad de tiempo.

Si finalmente se quiere guardar en cache la carpeta de node_modules, bastara con añadir las siguientes lineas al archivo de travis:

cache:
directories
:
- node_modules

Una vez establecido el lenguaje a utilizar los directorios cacheados, podemos indicar a Travis qué operaciones queremos que realice al detectar algún cambio en nuestro repositorio: esto será posible con la etiqueta script, donde podremos ejecutar cualquier numero de scripts presentes en nuestro proyecto.

En nuestro caso, dos de las instrucciones proporcionadas por Create-react-app serán suficientes: la primera, npm test, ejecutara un script para probar la aplicación. Si no detecta ningún problema en la aplicación, Travis continuará con la ejecución de nuestro segundo script, npm run build, que creará una build a partir de nuestro código y lo guardará en el directorio build.

Las lineas que deberemos añadir al yml serán las siguientes:

script:
- npm test
- npm run build

Hasta el momento, hemos indicado a Travis el lenguaje a utilizar, los archivos que debe mantener en cache así como los scripts que debe ejecutar sobre nuestro proyecto y el aspecto del archivo debería ser semejante a lo siguiente:

language: node_js
node_js
:
- "stable"
cache
:
directories
:
- node_modules
script
:
- npm test
- npm run build

Sin embargo, para completar la configuración aun nos falta lo mas importante: indicarle en qué servidor debe desplegar la web y bajo qué condiciones.
Para ello, deberemos tener en cuenta muchos parámetros, como el servidor donde queremos que se despliegue, las claves que le permitirán realizar cualquier modificación en dicho servidor o la rama que se debe haber modificado para que travis comienza a realizar este despliegue.

Como primera medida, añadiremos la etiqueta deploy, sobre la cual se añadirán el resto de las etiquetas faltantes para indicar que aquellas etiquetas presentes en su interior servirán para configurar sobre que proveedor actuará y bajo qué condiciones podrán hacerlo.

Provider será la primera etiqueta que añadiremos, donde se indicara quien sera el proveedor de nuestros servidores. Dependiendo del proveedor y su servicio elegido, la cantidad y nombre de las etiquetas utilizadas puede variar, siendo en nuestro caso s3. Si se desea utilizar otro servicio de AWS, o directamente otro proveedor, en este link se puede consultar los proveedores soportados por Travis así como las etiquetas que deben rellenarse en cada caso: https://docs.travis-ci.com/user/deployment/.

Provider, sin embargo, no nos basta para indicar de forma precisa sobre qué servidor queremos desplegar nuestra web. Es necesario proporcionar un usuario con el que Travis podrá acceder a nuestra cuenta parsonal asi como el nombre del bucket concreto que queremos utilizar. Con este fin utilizaremos las etiquetas access_key_id y secret_access_key para proporcionar el usuario y contraseñas respectivamente, y la etiqueta bucket para indicar el nombre del mismo.
El usuario y contraseña serán los proporcionados por AWS al crear el usuario IAM.

Al añadir estas etiquetas junto a la de provider, la etiqueta deploy deberá tener un aspecto semejante a esto:

deploy:
provider
: s3
access_key_id
: ""
secret_access_key
: ""
bucket
: ""

Con estas adiciones Travis podrá conectarse a nuestro servidor, aunque todavía no le hayamos señalado qué código es el que debe desplegar. Para ello utilizaremos la etiqueta local_dir, donde podremos indicar la carpeta del proyecto en la que se encuentra el código a desplegar. En este caso será build, la carpeta donde se habrá generado el código cuando Travis haya ejecutado el comando con el mismo nombre.

Finalmente, skip_cleanup es una etiqueta que nos permite elegir si saltamos o no la limpieza que Travis hace por defecto de todo aquello que haya generado durante la ejecución de los scripts. Añadir esta etiqueta con el valor true es completamente necesario para evitarlo. Si no, eliminaría la carpeta build que el mismo generó y en el que se encuentra el código que queremos desplegar.

El archivo de configuración, ahora terminado, debería presentar esta forma:

language: node_js
node_js
:
- "stable"
cache
:
directories
:
- node_modules
script
:
- npm test
- npm run build
deploy
:
provider
: s3
access_key_id
: ""
secret_access_key
: ""
bucket
: ""
local_dir
: build
skip_cleanup
: true

Ahora tan solo tendríamos que realizar cualquier cambio en nuestro proyecto. Una vez subido a la rama de master Travis se pondría a trabajar según nuestras directrices y, al cabo de pocos minutos, podríamos apreciar los cambios realizados en nuestro servidor de producción, pudiendo nosotros monitorizar el proceso desde la página de Travis para comprobar de primera mano las operaciones que va realizando a cada paso.

En este punto, contaríamos con un sistema de integración continua completamente funcional, que actualizaría el servidor de producción de forma automática. Sin embargo, no solo vamos a querer un servidor de producción. Normalmente haremos uso de un segundo servidor en el que poder probar bien todos los cambios que hayamos subido a nuestro repositorio, antes de llevar todos los cambios a producción.

Para ello comenzaremos duplicando el contenido de deploy de esta forma, cambiando el nombre del bucket por aquel que hayamos preparado para albergar la web que se encuentra en desarrollo:

deploy:
- provider
: s3
access_key_id
: ""
secret_access_key
: ""
bucket
: ""
local_dir
: build
skip_cleanup
: true
- provider
: s3
access_key_id
: ""
secret_access_key
: ""
bucket
: ""
local_dir
: build
skip_cleanup
: true

Como podéis observar, las claves para acceder al AWS serán las mismas en ambos casos y lo único que deberemos modificar será el nombre del bucket en donde desplegar nuestras distintas versiones de la web, pero ¿como distinguirá Travis que rama corresponde a que bucket?

Para esto necesitaremos la etiqueta on, en donde podemos establecer las condiciones que se deben cumplir para que el despliegue se realice bajo unas condiciones u otras. De este modo, podemos establecer como condición que se realice una cuando la rama modificada sea la master y otra cuando sea develop, como se puede ver a continuación:

deploy:
- provider
: s3
access_key_id
: ""
secret_access_key
: ""
bucket
: ""
local_dir
: build
skip_cleanup
: true
on
:
branch
: master
- provider
: s3
access_key_id
: ""
secret_access_key
: ""
bucket
: ""
local_dir
: build
skip_cleanup
: true
on
:
branch
: develop

Con este último cambio, habremos terminado de configurar nuestro entorno de integración continua: ahora solo nos quedará probarlo.

Pero antes de nada, para asegurarnos que nuestro fichero tiene todos los elementos dispuestos correctamente, podemos comprobar que tenga un aspecto similar al siguiente:

language: node_js
node_js
:
- "stable"
cache
:
directories
:
- node_modules
script
:
- npm test
- npm run build
deploy
:
- provider
: s3
access_key_id
: ""
secret_access_key
: ""
bucket
: ""
local_dir
: build
skip_cleanup
: true
on
:
branch
: master
- provider
: s3
access_key_id
: ""
secret_access_key
: ""
bucket
: ""
local_dir
: build
skip_cleanup
: true
on
:
branch
: develop

Conclusiones

Si has llegado hasta el final de este artículo verás que, aunque en un principio configurar Travis puede resultar un poco engorroso, cuando finalmente conoces el funcionamiento de las etiquetas más comunes y comprendes de forma general el funcionamiento de Travis, todo acaba haciéndose mucho mas fácil. Permitiéndote ser mucho mas rápido la próxima vez que quieras configurarlo, aun cuando la configuración que busques sea muy diferente a la original.

El único que quizás pueda seguir siendo complicado a la hora de querer experimentar puede ser AWS que, debido a su desproporcionada cantidad de opciones, nunca estaremos seguros si la herramienta elegida será la mas idónea para conseguir lo que queremos. Sin embargo, siempre podremos utilizar otros servicios con enfoques mas directos y Travis, además, cuenta con una excelente documentación para enseñarte a configurarlo para dicho servicio.

Con todo, la creación de un entorno de integración continua se convertirá, en mi opinión, en casi una obligación para cualquier equipo de desarrollo, debido a su bajo coste de construcción en relación a los beneficios que este proporciona. Ya sea utilizando Travis, o cualquiera de sus alternativas igualmente viables, como pueden ser Jenkins o CircleCI .