Students Save 30%! Learn & create with unlimited courses & creative assets Students Save 30%! Save Now
Advertisement
  1. Code
  2. Web Development
Code

Configuración de integración continua e implementación continua con Jenkins

by
Difficulty:BeginnerLength:LongLanguages:
Sponsored Content

This sponsored post features a product relevant to our readers while meeting our editorial guidelines for being objective and educational.

Spanish (Español) translation by Elías Nicolás (you can also view the original English article)

La vida diaria de un desarrollador está llena de tareas monótonas y repetitivas. Afortunadamente, vivimos en una edad de inteligencia pre-artificial, lo que significa que las computadoras son excelentes para manejar tareas aburridas y casi nunca se quejan de ello. Así que instalemos algo de automatización para que nuestra rutina diaria sea un poco menos aburrida.

Las pruebas y el despliegue son dos elementos integrales del desarrollo web. Con algo de automatización mezclada, se convierten en soluciones comúnmente llamadas "integración continua" (CI) y "implementación continua" (CD). El aspecto "continuo" de estas soluciones significa que sus proyectos se probarán y desplegarán automáticamente, lo que le permitirá concentrarse más en escribir códigos y menos en agruparlos en servidores.

En este tutorial, configuraremos un popular servidor de integración continua llamado Jenkins y lo sincronizará con GitHub para que ejecute pruebas cada vez que se inserte un nuevo código. Después de eso, crearemos una solución para enviar automáticamente ese código a nuestro servidor de aplicaciones, eliminando la necesidad de implementarlo manualmente.

Utilizaremos DigitalOcean para crear de manera rápida y sencilla servidores virtuales privados (VPS) basados ​​en la nube para alojar nuestra aplicación y Jenkins.

Nota: Este tutorial supone que tiene un conocimiento básico sobre cómo trabajar en la línea de comando, y que su máquina tiene ambos Git y Node.js instalados.

Nuestra aplicación Super Sample

Antes de que podamos probar o implementar algo, necesitamos algo para probar e implementar. Permítanme presentarles nuestra amigable aplicación de prueba tutorial, acertadamente llamada "hello-jenkins".

Escribiremos una aplicación simple de Node.js para nuestros propósitos. No hará mucho más que mostrar una línea de texto en el navegador, pero eso es suficiente funcionalidad para garantizar que hemos configurado correctamente la integración continua y la implementación continua.

Git en GitHub

Como almacenaremos nuestro proyecto en GitHub, comencemos allí. Inicie sesión (o cree) su cuenta de GitHub y cree un nuevo repositorio. Llámalo "hello-jenkins" y dale la siguiente descripción:

Para simplificar, conservemos el repo Public. Siga adelante y marque Inicializar este repositorio con una opción README y seleccione la opción Node en la lista desplegable Agregar .gitignore.

Haga clic en el botón Create repository y nuestro repositorio estará listo.

Ahora clonémos nuestro nuevo repositorio en nuestra máquina local y naveguemos hacia él:

Nuestra aplicación Node

Esta es la estructura final de nuestra aplicación:

Vamos a abordar esto uno por uno. El primer paso para crear cualquier aplicación Node.js es crear un archivo package.json. Aquí está el nuestro:

En las dependencies que agregamos express, que usaremos para ayudar a crear nuestra aplicación Node.js. En devDependencias hemos agregado mocha y supertest, que nos ayudarán a escribir nuestras pruebas.

Ahora que nuestro paquete.json está definido, instale nuestras dependencias de aplicaciones ejecutando:

Es hora de escribir nuestro código de aplicación. Cree un archivo llamado app.js y agregue lo siguiente a él:

Desglosemos nuestra sencilla aplicación Node.js:

  • Primero, importamos la lib express en nuestro package.json.
  • Usamos express para crear una nueva aplicación app..
  • Le decimos a nuestra aplicación app que responda a todas las solicitudes que llegan a la raíz de nuestro sitio (/) con el texto "hello world".
  • A continuación, le indicamos a nuestra aplicación app qué puerto debe escuchar para las solicitudes (process.env.PORT se refiere a la variable de entorno llamada "PORT", y si no existe, en lugar de eso establecemos de manera predeterminada el puerto 5000).
  • Finalmente, hacemos que nuestra aplicación app esté disponible para otros módulos Node.js a través de module.exports (esto será útil más adelante cuando agreguemos pruebas).

¡Eso es! Nuestra aplicación está lista, vamos a ejecutarla:

Abra su navegador favorito y navegue a http://localhost:5000 y verá hello world sentado en toda su gloriosa sencillez.

No es la aplicación de prueba más emocionante, ¡pero funciona! Continúa y cierra nuestra aplicación Node.js con Ctrl-C, y sigamos adelante.

Algunas pruebas están en orden

Es hora de escribir una prueba para nuestra aplicación; después de todo, si no tenemos nada que probar, ¡entonces Jenkins no tendrá nada que hacer!

Cree una carpeta llamada test, y en ella cree un archivo llamado test.js. Agregue el siguiente código para test/test.js:

¿Cómo funciona nuestra prueba? Primero, importamos tanto la supertest lib como nuestra aplicación app. Luego agregamos una prueba única, que describe lo que debería suceder cuando una solicitud GET llega a la raíz de nuestro sitio. Le decimos a nuestra prueba que esperamos que la respuesta sea "hello world", y si lo es, la prueba pasa.

Para ejecutar la prueba, usaremos la biblioteca de Mocha. Instalamos Mocha como parte de nuestras devDependencies, por lo que simplemente ejecutaremos un comando que pase nuestro archivo de prueba a Mocha y Mocha ejecutará nuestras pruebas:

Cuando termine, debería ver un punto verde junto con información que indique que ha pasado una prueba. ¡Eso significa que nuestra prueba fue exitosa! Pero teclear ese comando una y otra vez pronto producirá calambres en los dedos y espasmos en los ojos, así que hagamos un guión de ayuda para hacerlo por nosotros (¡recuerde, las computadoras no se aburren!).

Cree un nuevo directorio llamado script, y en él cree un archivo llamado test (note que no hay extensión). Agregue lo siguiente al script/test:

Ahí, ahora tenemos un script de shell para ejecutar esa línea gnarly para nosotros. Pero antes de que podamos usarlo, debemos otorgarle permisos ejecutables:

¡Probémoslo! Correr:

... y debería ver la misma prueba de aprobación que antes.

Hora de empujar

De acuerdo, tenemos una aplicación que funciona y una prueba de trabajo, así que vamos a enviar nuestro nuevo código a GitHub:

Y eso es todo: ¡nuestra aplicación está lista y en GitHub!

Nuestra aplicación se sirve

Nuestra aplicación se sirveTenemos una aplicación apasionante y cautivadora ("hello world" tiene una especie de poesía, ¿no te parece?), ¡Pero nadie puede verla! Cambiemos eso y haga que nuestra aplicación se ejecute en un servidor.

Para nuestras necesidades de alojamiento, recurriremos a Digital Ocean. DigitalOcean proporciona una manera rápida y sencilla de aumentar las instancias de la nube VPS, convirtiéndolo en el anfitrión perfecto para nuestro patio de recreo CI / CD.

La primera gota

Inicie sesión en (o regístrese) en Digital Ocean y haga clic en el botón Create Droplet. Para el nombre de host, llámalo "hello-jenkins". La instancia de menor tamaño (512MB / 1 / 20GB) satisfará nuestras necesidades y seleccionará la región geográfica más cercana a usted. A continuación, tenemos que elegir la imagen utilizada para crear la gota. DigitalOcean ofrece una amplia selección de sistemas operativos para elegir, pero lo que es realmente agradable es que también proporcionan imágenes adaptadas específicamente para ciertos tipos de aplicaciones.

Haga clic en la pestaña Aplicaciones y seleccione el nodo-v0.10.29 en la opción Ubuntu 14.04 - esto creará un servidor que está muy bien configurado para nuestra aplicación Node.js.

Ahora haga clic en Create Droplet y DigitalOcean comenzará a inicializar nuestro servidor.

Configurar el servidor

En un minuto nuestro nuevo servidor debería estar listo, y debería haber recibido un correo electrónico con las credenciales de raíz de su servidor. Usemos esa información para iniciar sesión:

Se le solicitará la contraseña que se proporciona en el correo electrónico, y luego se le forzará a crear una nueva contraseña (convertirla en algo muy sólido y almacenarla en una ubicación segura, como una base de datos KeePass).

En este momento estamos conectados como root, que es el todopoderoso semidiós de Linux-land. Pero pesada es la cabeza que usa la corona, y operar como raíz root generalmente es una mala idea. Entonces, lo primero que querremos hacer es crear un nuevo usuario, llamémosle "aplicación":

Tendrá que proporcionar una contraseña (una contraseña segura diferente, almacenada de forma segura), y luego le hará una serie de preguntas opcionales.

Queremos cambiar a nuestro usuario de la app, pero antes de cerrar la sesión, debemos otorgarle a nuestro usuario nuevos privilegios de sudo para que pueda realizar acciones administrativas:

Ahora cierre la conexión con la exit y luego conéctese como app:

Se le pedirá la contraseña del usuario de la app, y luego deberá iniciar sesión y listo.

Instala nuestra aplicación

Vamos a poner nuestra aplicación en la máquina. Gracias a las imágenes de la aplicación de DigitalOcean, nuestra máquina viene con Node.js y npm preinstalados, pero aún necesitamos instalar Git:

Se le pedirá su contraseña (ya que está usando sudo), y deberá confirmar la instalación con Y. Una vez que Git esté instalado, podemos usarlo para obtener nuestra aplicación de GitHub.

Copie la URL de clonación HTTPS de la página GitHub del proyecto y luego clone el repositorio en su carpeta de inicio en el servidor:

Ahora nuestra aplicación está en nuestro servidor, en una carpeta llamada "hello-jenkins". Veamos eso:

Lo primero que debemos hacer es instalar las dependencias de la aplicación:

Una vez hecho esto, ¡podemos ejecutar nuestra aplicación! Hazlo girar con:

... y vaya a la dirección IP de su servidor en su navegador.

Pero espera, ¡no funciona! ¿Cual es el trato?

Bueno, recordemos esta línea de código en nuestra app.js:

En este momento, no tenemos una variable de entorno PORT configurada, por lo que nuestra aplicación está configurada de manera predeterminada en el puerto 5000 y debe agregar el puerto a la dirección IP en el navegador (http://YOUR.SERVER.IP.ADDRESS:5000)

Entonces, ¿cómo hacemos para que nuestra aplicación funcione como se espera, sin tener que especificar el puerto? Bueno, cuando un navegador realiza una solicitud HTTP, se establece de manera predeterminada en el puerto 80. Por lo tanto, solo debemos establecer nuestra variable de entorno PORT en 80.

Configuraremos nuestras variables de entorno en el archivo /etc/environment en el servidor: este archivo se carga al iniciar sesión y las variables establecidas estarán disponibles globalmente para todas las aplicaciones. Abra el archivo:

Verás que en este momento el PATH se está configurando en este archivo. Agregue la siguiente línea después de ella:

Luego, escriba Ctrl-X, Y y Enter para guardar y salir. Cierre sesión del servidor (exit) y SSH de nuevo (esto cargará la nueva variable de entorno).

Una última tarea: ejecutar una aplicación en el puerto 80 requiere privilegios de administrador, pero la ejecución del sudo node app.js no conservará las variables de entorno que hemos configurado. Para evitar esto, habilitaremos que el node tenga la capacidad de ejecutarse en el puerto 80 sans sudo:

Deberias hacer eso. Ahora ejecuta:

Navega a http://YOUR.SERVER.IP.ADDRESS, y verás hello world!

Mantenerlo funcionando

En este momento, nuestra aplicación solo se ejecuta mientras estamos ejecutando el proceso. Si lo cerramos, nuestro sitio ya no estará disponible. Lo que necesitamos es una forma de mantener nuestra aplicación Node.js ejecutándose en segundo plano. Para eso, lo usaremos forever. El primer paso es instalarlo globalmente:

Ahora, en lugar de iniciar nuestra aplicación con node app.js, usaremos:

Tenga en cuenta que, en lugar de que el proceso dependa de la ejecución, se cierra inmediatamente y le devuelve el control. Esto se debe a que el servidor Node.js se está ejecutando en segundo plano. Ahora no tenemos que preocuparnos de que nuestro servidor se cierre cuando cerramos la sesión del servidor. ¡forever reiniciará automáticamente nuestra aplicación si se bloquea!

Para detener nuestra aplicación, podemos ejecutar:

Por ahora, sigamos funcionando y pasemos a Jenkins.

El tiempo para probar

Vamos a alojar nuestro servidor Jenkins en una gota de DigitalOcean separada. Vamos a hacer eso ahora.

La segunda gota

Crea un nuevo droplet con el nombre de host "jenkins-box". Elija 512MB / 1 / 20GB nuevamente, junto con la misma ubicación y el mismo tipo de aplicación (node-v0.10.29 en Ubuntu 14.04) como en el droplet anterior.

Haga clic en Create Droplet y una vez que haya terminado, use las credenciales enviadas por correo electrónico para iniciar sesión a través de SSH (tendrá que establecer una nueva contraseña, al igual que antes).

Como antes, deberíamos crear un nuevo usuario antes de hacer cualquier otra cosa. Esta vez vamos a llamarlo admin:

Cierre sesión como root e inicie sesión como administrador admin recién creado.

Dado que el propósito de Jenkins es recuperar nuestro proyecto y ejecutar sus pruebas, nuestra máquina necesita tener todas las dependencias del proyecto instaladas. Hicimos andar esta instancia con la aplicación Node.js de DigitalOcean, por lo que ya no están instalados Node.js y npm. Pero todavía tenemos que instalar Git:

Contrata al mayordomo

El siguiente es Jenkins. Instalar Jenkins es bastante simple: tendremos apt-get para hacer todo el trabajo pesado. La única pega es que tenemos que agregar un nuevo repositorio apt antes de comenzar la instalación:

Ahora podemos instalar Jenkins:

Una vez que esté completo, Jenkins se estará ejecutando y estará disponible en el puerto 8080. Navegue su navegador a la dirección IP de jenkins-box en el puerto 8080 y verá la página de aterrizaje de Jenkins.

Haga clic en el enlace Administrar Jenkins y luego en el enlace Administrar complementos. Cambie a la pestaña Disponible y busque el complemento de GitHub. Haga clic en la casilla Instalar y luego en Descargar ahora e instalar después de reiniciar.

Esto iniciará la secuencia de instalación. El complemento GitHub tiene varias dependencias, por lo que se instalarán varios complementos. En la parte inferior de la página, verifique Reiniciar Jenkins cuando la instalación esté completa y no se estén ejecutando trabajos: esto le indicará a Jenkins que se reinicie una vez que las instalaciones estén completas.

Una vez que Jenkins se haya reiniciado, es hora de agregar nuestro proyecto. Haga clic en el botón Nuevo artículo. Use "hello-jenkins" para el nombre del elemento, seleccione Crear un proyecto de software de estilo libre y haga clic en el botón etiquetado como Aceptar.

Una vez que el proyecto esté configurado, se encontrará en la página de configuración del proyecto. Agregue la URL de GitHub de nuestro proyecto al cuadro del proyecto GitHub:

A continuación, seleccione la opción Git en Gestión de código fuente. En los campos recién aparecidos, agregue la URL a nuestro repositorio del proyecto GitHub al campo URL del repositorio:

Desplácese un poco más hacia abajo y haga clic en el cuadro para habilitar la compilación cuando un cambio se pasa a GitHub. Con esta opción marcada, nuestro proyecto se desarrollará cada vez que presionemos nuestro repositorio de GitHub. Por supuesto, necesitamos que Jenkins sepa qué hacer cuando ejecuta una compilación. Haga clic en el menú desplegable Agregar paso de creación y seleccione Ejecutar shell. Esto hará que un diálogo de Comando esté disponible, y lo que ponemos en este diálogo se ejecutará cuando se inicie una compilación. Agregue lo siguiente a esto:

Nuestra construcción consta de dos pasos. Primero, instala nuestras dependencias de aplicaciones. Luego ejecuta ./script/test para ejecutar nuestras pruebas.

Clic en "Guardar".

Para finalizar la configuración de la integración, diríjase al repositorio de GitHub y haga clic en Configuración. Haga clic en la pestaña Webhooks & Services, y luego en el menú desplegable Agregar servicio. Seleccione el servicio Jenkins (plugin GitHub).

Agregue lo siguiente como la URL del gancho Jenkins:

Haga clic en Agregar servicio. ¡Nuestro proyecto ahora está listo para su primera prueba de integración continua!

Vamos a darle algo para probar. Abra app.js localmente y cambie esta línea:

...a esto:

Guarde el cambio y comprométalo:

Ahora vigila a Jenkins mientras envías tus cambios a GitHub:

Después de uno o dos segundos, debería ver que se ha iniciado un nuevo trabajo para nuestro proyecto hello-jenkins en Jenkins: ¡nuestra integración continua funciona!

El flujo de integración continuo

Pero ... ¡el trabajo falla! ¿Por qué?

Bueno, recuerda que nuestra prueba espera que la llamada raíz devuelva "hello world", pero la hemos cambiado a "hello jenkins". Así que cambiemos las expectativas de nuestra prueba. Cambiar esta línea:

... con esta línea:

Guarde, comprométase y vuelva a subirla:

Mira a Jenkins: una vez más, verás que una compilación se inicia automáticamente, y esta vez, ¡tiene éxito!

Este es el flujo de integración continua. El servidor de prueba está continuamente probando cualquier código nuevo que presione para que se le informe rápidamente sobre cualquier prueba que falle.

Instalarlo

De acuerdo, entonces estamos probando nuestros cambios automáticamente, pero ¿qué hay de implementar esos cambios? ¡No hay problema!

Si has estado observando de cerca, sin duda has notado que falta algo en nuestro proyecto hasta el momento. En la estructura del proyecto al comienzo del tutorial, existe un archivo script/deploy, pero aún no hemos creado dicho archivo. Bueno, ¡ahora lo haremos!

La clave para la autenticación

Pero primero, veamos cómo funcionará la implementación. Nuestro script (ejecutado por el paso de compilación de Jenkin) se registrará en el servidor de la aplicación a través de SSH, navega a nuestra carpeta de aplicaciones, actualiza la aplicación y luego reinicia el servidor. Antes de escribir nuestra secuencia de comandos de implementación, debemos controlar cómo nuestro servidor de Jenkins enviará SSH a nuestro servidor de aplicaciones.

Hasta ahora, hemos accedido a nuestros servidores al ingresar contraseñas manualmente, pero este enfoque no funcionará para las secuencias de comandos automatizadas. En cambio, crearemos una clave SSH que el servidor de Jenkins usará para autenticarse con el servidor de la aplicación.

Cuando Jenkins se instala, crea un nuevo usuario llamado jenkins. Jenkins ejecuta todos los comandos con este usuario, por lo que debemos generar nuestra clave con el usuario de jenkins para que tenga el acceso adecuado.

Mientras inicia sesión como administrador admin en jenkins-box, ejecute lo siguiente:

Proporcione su contraseña del administrador admin y lo cambiará al usuario root. Luego ejecuta:

Ahora estás actuando como el usuario de jenkins. Generar una clave SSH:

Guarde el archivo en la ubicación predeterminada (/var/lib/jenkins/.ssh/id_rsa) y asegúrese de no utilizar una frase de contraseña (de lo contrario, el acceso a SSH requerirá una contraseña y no funcionará cuando se automatice).

A continuación, debemos copiar la clave pública que se creó. Ejecuta esto:

... y copia la salida. Debe ser una cadena larga que comience con "ssh-rsa" y termine con "jenkins@jenkins-box".

Cierre la sesión de jenkins-box y vuelva a iniciar sesión en nuestro servidor de aplicaciones (hello-jenkins) como el usuario de la aplicación app. Necesitamos crear un archivo llamado authorized_keys en nuestra carpeta usuario .ssh de la aplicación app:

Pega la clave pública que copiaste y luego Ctrl-X / Y / Enter para guardar y salir. Para que este archivo funcione correctamente, necesita tener permisos estrictos establecidos en él:

Vuelva a la caja de jenkins, cambie al usuario de jenkins y verifique que puede iniciar sesión en nuestro servidor de aplicaciones sin ingresar una contraseña:

Debe iniciar sesión correctamente en el servidor de la aplicación sin tener que ingresar la contraseña. Con eso establecido, ahora podemos pasar a la implementación.

Enviarlo automáticamente

Cree un archivo en la carpeta de scripts llamada deploy (tenga en cuenta que no hay extensión). Agregue lo siguiente al script/deploy:

Veamos esto:

  • Primero, inicia sesión en el servidor de la aplicación como el usuario de la app.
  • Luego navegaremos en nuestra carpeta de aplicaciones y actualizaremos a la última versión de GitHub.
  • Después de eso, instalamos nuestras dependencias.    
  • Finalmente, una vez que se actualiza nuestro código de la aplicación, reiniciamos nuestro servidor con forever restartall.

Haga que nuestro nuevo archivo de script sea ejecutable:

Agregue este nuevo archivo y confírmelo:

Pero no empujemos todavía. Primero, regrese a la configuración de nuestro proyecto en Jenkins y desplácese hacia abajo hasta el comando de compilación. Agregue esta nueva línea al final:

Guarde el proyecto Jenkins.

Ahora ve y presiona a GitHub, y observa cómo Jenkins construye automáticamente. Una vez que se complete la compilación (debería tener éxito), navegue su navegador a la IP de nuestro servidor de aplicaciones. ¡Presto! Nuestro emocionante "hello world" ha sido reemplazado con un emocionante "hello jenkins"!

¡Nuestra aplicación ahora se está desplegando continuamente!

Todo está bien que automatiza bien

Uf. ¡Eso fue todo el viaje!

Al final, hemos configurado con éxito tanto la integración continua como la implementación continua, lo que proporciona un muy buen nivel de automatización en nuestra vida diaria de desarrollador. Recuerde, las computadoras no se aburren, por lo tanto, mientras se encargan de las pruebas y la implementación, usted es libre de hacer cosas importantes, como hacerse un sándwich. ¡Así que ve a hacer ese sándwich, y cómelo como un campeón de automatización!

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.