This graph shows how many times the word ______ has been mentioned throughout the history of the program.
Vamos a aprender Github Actions.
¿Y Github Actions por qué lo vamos a aprender?
Bueno, porque es un sistema de Continuous Integration.
¿Qué es lo que nos va a permitir el Continuous Integration?
Bueno, pues integrar nuestra aplicación siempre, constantemente.
¿Pero qué es esto de integrar? ¿Qué quiere decir?
Bueno, básicamente, la integración continua lo que quiere decir
es un sistema de automatización para verificar la integridad,
hablando de integridad, como la calidad o que esté bien formado nuestro código.
Y que además se pueda añadir en producción.
O sea, que la integración digamos que es un poquito todo.
Esta despedida del BotCamp duele más que las despedidas de Messi. Sad.
Una lágrima, una lágrima, Luigi. Gracias por el comentario, hombre.
Entonces, ¿qué es lo que buscamos?
Pues automatizar la verificación e integración de los cambios de código
de varios contribuidores, no solo de uno, de todos los que trabajan en ese repositorio
en un único proyecto de software. ¿Por qué?
Porque tenemos un montón de desarrolladores y desarrolladoras
que trabajan sobre un código y al final lo que queremos es integrarlo todo.
Pues esa integración continua, ¿qué quiere decir?
Pues cada vez que se haga un cambio en cada una de las copias que tienen estos desarrolladores,
lo que vamos a querer es integrarlo en la pieza de software que queda
y verificar que todo ha ido correctamente o evitar que no se integre, ¿no?
Porque si tiene algún error no vamos a querer que se integre.
Pues esto es lo que se hace.
Ahora, ¿por qué se llama continua?
Porque es un proceso que no deja de pasar.
Cada vez que se sube un cambio, vuelve a ejecutarse este proceso.
Este proceso en el que va del desarrollador al source control, al repositorio,
que puede ser Gija, puede ser Gitla, puede ser cualquiera.
A partir de ahà se hace la build para construir nuestra aplicación,
se hacen los tests para asegurarnos que está correctamente,
se pueden reportar, enviar notificaciones y lo que sea,
y luego hacer la release, que es un despliegue que puede ser a producción,
que hoy lo vamos a hacer.
Hoy vamos a hacer toda la continuous integration.
Vamos a hacerlo con GitHub Actions y vamos a hacer todos y cada uno de estos pasos
que he comentado.
Incluso el despliegue lo vamos a hacer en Heroku,
porque es que en Vercell es tan sencillo que no tiene sentido explicarlo.
Pero bueno, vamos a explicar Heroku para que podáis hacerlo con cualquier otro hosting,
el que prefiráis y que sepáis que se puede hacer.
Asà que esto es lo que vamos a hacer.
Ahora, ¿qué pasos son los que hacen el continuous integration?
Pues lo vamos a ver, ¿vale?
Pasar el link, revisar que los commits funcionen correctamente,
que tengan una normativa de nombres, construir o empaquetar la aplicación,
bueno, un montón de cosas.
¿Y cómo lo vamos a hacer?
Bueno, pues yo tengo este proyecto de aquÃ,
que se llama Midudev Pokedex for Continuous Integration, ¿vale?
Está pensado justamente para hacer continuous integration.
Os lo dejo por el chat, por si lo queréis, ¿vale?
Esto acabo de empezar, asà que nada, que una cosa que podéis hacer si queréis
es hacer todo lo que voy a hacer yo a la vez.
O sea, que podéis hacer un fork y todo lo que voy a hacer lo vais a poder hacer vosotros mismos,
de la misma forma que lo estoy haciendo yo.
Asà que si queréis, ya sabéis, os vais a este repositorio, le dais a fork
y a partir de ahà podéis hacer todo lo que voy a hacer yo.
Todo, todo, todo, sin ningún tipo de nada, nada.
O sea, igualito, igualito.
Obviamente necesitaréis cuentas de rock y tal, pero eso lo iréis viendo.
Asà que vamos a empezar con el Continuous Integration, con las GitHub Actions.
¿Por qué las GitHub Actions?
A ver, hay un montón de sistemas de Continuous Integration.
Tenemos Jenkins, ¿vale?
Jenkins es uno de los más famosos.
Seguramente es uno de los que más se utilizan.
También tenemos, por supuesto, Travis.
A ver si no me equivoco, porque Travis, Continuous Integration,
Travis C, voy a poner.
Travis también, que está bastante bien integrado con GitHub.
Y el otro son las GitHub Actions.
¿Por qué vamos a utilizar GitHub Actions?
Bueno, aparte de porque es totalmente gratuito y es muy fácil de utilizar,
pues está muy bien integrado con GitHub, como lo vamos a ver.
Pero lo que vamos a aprender hoy, aunque no es exactamente igual para Jenkins o para Travis,
es muy similar.
Lo que está detrás al final se escribe de otra forma,
pero lo que vamos a hacer es muy similar en todos estos sistemas de integración continua, ¿vale?
Al final los sistemas de integración continua tenéis que pensar que son máquinas virtuales, ¿ok?
Lo que son, son servidores que tienen máquinas con su memoria RAM, con su procesador,
porque básicamente lo que hacemos es que en lugar de hacerlo de forma local,
todos estos procesos lo hacemos en una máquina que está en la nube,
y asà nos aseguramos que siempre sea la misma máquina con la misma configuración
y que tenga siempre una instalación limpia y todo esto, ¿vale?
Pero bueno, que sepáis que tenéis Jenkins, tenéis Travis CI y tenemos GitHub Actions.
GitHub Actions, como he dicho, es totalmente gratis.
Entonces, es verdad que tiene un lÃmite y el lÃmite es el número de minutos.
De la forma de gratuita, si tenéis la cuenta gratuita, tenéis 2.000 minutos al mes.
A partir de ahà tendrÃais que pagar.
2.000 minutos al mes está bastante bien.
Ya veréis cuánto tarda nuestro, el que vamos a crear hoy, vais a ver cuánto tarda
y veréis que a lo mejor dos o tres minutos.
Lo que harÃa que podrÃamos pasar casi, pues, mil veces.
Al mes podrÃamos pasar nuestro Continuous Integration.
El Pro tiene 1.000 minutos más y si no, a partir de ahÃ, pues, ya habrÃa que empezar a pagar.
Luego, si necesitas otro tipo de configuración, por ejemplo, que tenga más potencia,
que sea un Mac OS en lugar de un Linux, por defecto es un Linux.
Ya veréis que nosotros utilizamos Ubuntu porque es el que se suele utilizar para este tipo de herramientas.
Pero podéis contratar un Mac OS y entonces tenéis que pagar aparte, ¿vale?
Que lo tengáis en cuenta.
Y también incluso lo podéis hospedar si tenéis un hosting vuestro, lo podéis hospedar.
Pero bueno, eso se sale un poquito de lo que queremos hacer.
Lo importante, vamos a empezar con nuestro proyecto, con el Pokédex for Continuous Integration.
Y lo primero que voy a hacer es clonarlo.
Y vamos a ver cómo podemos hacer justamente esto, ¿vale?
Nos vamos a la terminal, voy a hacer un git clone de este proyecto, el de Pokédex for Continuous Integration.
Me voy al proyecto, Pokédex for Continuous Integration.
Y ahora que tenemos esto, pues como siempre, cuando se empieza un proyecto, pues nada, un MPM install para instalar las dependencias.
No deberÃa tener muchas, asà que vamos a esperar que no tenga muchas.
Y ahora le echaremos un vistazo al proyecto para explicar qué es, qué hace.
Le haremos una build, le pasaremos los tests y veremos unas cuantas cosas y te explico lo que tiene, ¿vale?
En principio, con el MPM install, se me ha estado toda la dependencia que necesitamos.
Ya veremos si luego necesitamos alguna más.
Tampoco le he hecho un vistazo muy en detalle.
Pero bueno, vamos a ver.
MPM run, para ver qué scripts tenemos.
Tenemos un start, tenemos el test, tenemos un start prot, es linked y un build.
Vale.
Vamos a hacer un MPM start.
No, vamos a empezar con la build.
Vamos a hacer un MPM run build, porque seguramente el start...
Bueno, el start, sÃ, vamos a hacer el start.
El start es el del modo desarrollo y esto va a hacer la compilación por defecto.
Y ya está.
Aquà se deberÃa...
Vale, este es nuestro proyecto.
Podemos ver que hay un montón de pokémones aquÃ.
Le podemos dar, yo que sé, al Widdle y aquà nos sale la información.
Podemos ir al siguiente, podemos ir al anterior, ¿vale?
Bueno, pues esto serÃa nuestro proyecto.
Vamos a ver qué más scripts tenemos.
TendrÃamos también el test.
Vamos a ejecutar el test, a ver qué pasa.
Vale, MPM run test.
Vale, falla un test.
No te preocupes, lo arreglaremos después.
Esto es normal, por ahora vamos a dejar asÃ.
Lo importante es que los tests se ejecutan.
Falla uno, pero bueno, ya veremos cómo lo arreglamos.
MPM run slint, para ver el linter.
También tiene errores, no pasa nada.
También lo arreglaremos después.
¿Qué más?
Vamos a hacer un MPM run build, para hacer la build de la aplicación.
A ver si falla o no.
No falla.
Perfecto, ya nos habrá hecho la build.
Y bueno, vamos a abrir el proyecto, para echarle un vistazo a este...
A esta aplicación.
Ya vemos que tenemos Babel RC.
Es un proyecto que tiene una configuración de Webpack.
No está hecha de abrir acá.
O sea, tiene su propia configuración desde cero.
Babel loader, HTML loader.
Esto no hemos visto en FullStat Bootcamp.
Pero bueno, no es importante.
Si no lo has visto, no pasa nada.
Lo único que tienes que saber es que utiliza Webpack.
Aquà tenemos todas las dependencias con todos los scripts.
Vale, todas las dependencias que necesitamos.
Tenemos dependencia de desarrollo y de producción.
Y mirando un poquito el código, pues podemos ver que son componentes de React.
Es un proyecto de React.
El que vamos a desplegar, con el que vamos a hacer Continuous Integration, es un proyecto de React.
Perfecto.
Tenemos aquà en el source todo lo que es el código, que seguramente tenemos que tocar alguna pequeña cosa.
Hoy no vamos a codificar mucho, sino que vamos a probar el Continuous Integration.
Pero ya hemos visto que tanto los test como el linter falla.
Asà que vamos a tener que revisarlo.
Tenemos que hacer algo para arreglarlo.
¿Cómo podemos crear un workflow para GitHub Actions?
¿Y cómo funciona GitHub Actions?
Las GitHub Actions, si volvemos a nuestro repositorio, ya las tenéis aquà disponibles.
¿Veis que pone Actions?
Pues si tú le das aquà a Actions, ahora no aparece nada.
Y te dice, bueno, para empezar con GitHub Actions.
Y la verdad es que aquà ya te da algunas sugerencias que están bastante bien.
Una que te dice, mira, para proyectos con Webpack, pues ha detectado qué es lo que tiene tu repositorio y dice,
utiliza Webpack.
Node.js, Gulp.
No, pues Gulp no tengo.
Pero bueno, no es perfecto esto.
Son sugerencias.
Entonces, la de Webpack o Node.js no tendrÃa mala cuenta.
Le podrÃamos dar a Setup this workflow.
Y esto te crea aquà un editor que está bastante bien.
Lo que pasa es que, claro, ya te viene con un montón de cosas aquà configuradas.
Y a lo mejor no es exactamente lo que queremos.
Pero ya vemos un poco que me está creando dentro de la carpeta .github barra workflows barra y el nombre de este fichero es webpack.yaml.
Asà que va a utilizar un formato YAML, que para el que no conozca el formato YAML es similar a JSON, pero no utiliza llaves.
En lugar de utilizar llaves, utiliza espacios.
Luego lo verás claramente.
Y te daré un consejo, una recomendación súper importante que tienes que hacer sà o sà para no volverte tarumba.
Asà que, bueno, no lo vamos a hacer asà con el editor.
Lo vamos a hacer nosotros desde cero en Visual Studio Code.
Asà que esto es solo para que sepas, si tienes otro proyecto, que sepas que puedes hacer esto y esto te puede dar alguna idea.
Nosotros lo vamos a hacer desde cero.
Vamos a crear el primer workflow.
Porque GitHub Actions, lo que tienes que crear son workflows.
Y puedes tener más de uno.
Asà que vamos a hacer un new file.
Vamos a hacer punto github barra workflows.
Barra.
Vamos a poner por ahora hello.yaml.
¿Vale?
Hemos dicho que es un formato YAML.
Primera cosa súper importante del workflow.
Bueno, los workflows tienen que tener un nombre.
Asà que vamos a ponerle un nombre y le vamos a llamar sayhello.
¿Vale?
Hasta para empezar.
Ahora, segunda cosa que tienen que tener los workflows de GitHub Actions.
Lo que tienen que tener es un evento.
¿Cuándo se tiene que activar un workflow?
Un workflow al final es una serie de procesos.
Pues ¿cuándo se tiene que activar este archivo?
Pues este archivo le tengo que decir.
Vale, este archivo va a escuchar el evento de push en las ramas.
Y le puedes decir las ramas.
En este caso vamos a decir que sea master.
Vamos a ver, vamos a asegurarnos cuál es la rama que tenemos aquÃ.
¿Ves?
Esta es main.
¿Vale?
Pues entonces en lugar de master vamos a poner main.
Cada vez que hagamos un push en la rama main lo que vamos a hacer es que se va a ejecutar todo este workflow.
¿Y qué es lo que va a hacer un workflow?
Vale, pues un workflow para trabajar lo que necesita.
Mira, de hecho fÃjate que pone missing property jobs.
O sea, es una maravilla esta extensión.
Y ahora te diré cuál es, no te preocupes.
Lo que tiene que hacer es tener trabajo.
Porque la gente que no trabaja pues no hace nada.
No hace nada.
Bueno, puede estar estudiando.
Pero en este caso la GitHub Actions necesita trabajo.
Asà que le decimos jobs.
Y le vamos a indicar cuáles son los trabajos que tiene que hacer este workflow.
Vamos a ponerle un nombre.
Vamos a poner hello world, por ejemplo.
Y le tenemos que decir primero en qué sistema operativo va a funcionar este trabajo.
Asà que le decimos este trabajo funciona en Ubuntu Latest.
Ubuntu Latest serÃa la última versión de Ubuntu.
Pero puedes utilizar, si lo prefieres, y de hecho puede ser una buena idea,
que utilices una versión en concreto.
De hecho está muy bien que tiene hasta autocompletado.
¿Ves?
Aquà te pone 16.04, 18.04, 20.04.
Bueno, pues le podemos poner la versión especÃfica.
Si le pones Latest, el problema que puede haber es que cuando salga la 22,
automáticamente utilizará esa y se puede romper todo y no queremos que se rompan las cosas.
Ahora que tenemos un trabajo con el nombre hello world,
que decimos que tiene que funcionar en Ubuntu,
le tenemos que decir todos los pasos que tiene que dar.
Asà que le vamos a indicar los pasos.
A los pasos tú le puedes dar un nombre.
Por ejemplo, le podemos decir, vamos a hacer un eco del mensaje.
Le podemos poner un nombre o lo que tú quieras.
Si quieres no le pones un nombre.
Y aquà le vamos a poner run y le decimos lo que tiene que ejecutar.
Lo podemos hacer asÃ, en la misma lÃnea.
Vamos a poner hola midu.
Lo puedes hacer en la misma lÃnea.
Otra cosa que puedes hacer es poner esta barra asà y luego ya escribir todo lo que quieras.
Ahora, antes de continuar y de probar nuestro primer workflow,
una cosa súper, súper importante, porque si no, YAML es una locura.
FÃjate con una cosa, ¿no?
Yo, YAML funciona a través de las tabulaciones.
Todo lo que son tabulaciones entiende que es información que está contenida.
No es como JSON, que el JSON funciona con las llaves.
Lo que significa que las llaves pueden estar mal tabuladas y funcionar igualmente.
Pero YAML no.
YAML es muy, muy, muy, muy jodido.
Necesita que funcione con las tabulaciones correctamente.
Si yo hago mal esta tabulación, ¿vale?
Pues ya la estoy liando.
Ya no funcionarÃa exactamente igual.
FÃjate que a veces, si aquà hago mal una tabulación, ¿ves?
Me dice, bad indentation of a mapping entry.
O sea, ya me empieza a decir, oye, esto está mal.
¿Cómo puedes hacer?
¿Ves?
AquÃ, bueno, aquà veo que no.
Depende un poco de dónde lo pongas.
Que algunas veces sà que te lo chiva y otras no.
Pero, bueno, está bastante interesante que por poco que te lo diga,
yo creo que si pones un espacio y cosas asÃ, depende de dónde lo pongas y que te lo dicen.
Es súper importante, ¿vale?
Tienes que tener la extensión de YAML instalada.
Hay una extensión que es bastante oficial porque es de Red Hat.
Tiene 6 millones de descargas.
Esta extensión para trabajar con archivos YAML es súper, súper, súper necesaria.
Por dos motivos.
Uno, porque te va a indicar los errores.
Y si no te das cuenta de estos errores y los subimos aquÃ, Cap Actions,
vamos a volver locos perdidos, ¿vale?
Porque te va a decir, el YAML está mal formateado, no vas a encontrar el error, un rollo.
Asà que instálate esta extensión cada vez que trabajes con un YAML.
Y luego, porque a lo mejor no hace lo que tú esperas, ¿vale?
Porque si, fÃjate, que si el Steps lo pones aquÃ, a lo mejor, aquà sà que se ha dado cuenta que está mal intentado,
pero a lo mejor lo que simplemente hace es ignorarlo y nunca lo ejecuta.
A lo mejor funciona, pero no hace lo que tú esperas.
Asà que, bueno, es buena idea tenerlo instalado.
Además, también tienes el autocompletado.
FÃjate que aquà me está haciendo el autocompletado de todos los eventos que puedo escuchar.
Y esto es una cosa que te lo está haciendo también la extensión.
Asà que lo tengas en cuenta, que lo utilices, que es muy buena idea.
Ya tenemos nuestro primer workflow.
Vamos a verlo en funcionamiento, si os parece.
Vamos a add our first workflow of GitHub Actions.
Venga.
No hay, vale.
Lo comitamos todo y lo subimos.
Voy a poner aquà la terminal.
Pusheamos.
¿Vale?
Y voy a volver a mi repositorio y voy a refrescar.
A ver, capachao.
Mira, fÃjate aquà que hay ya un circulito amarillo.
Esto lo que quiere decir es que se está procesando el workflow de GitHub Actions.
De hecho, si le das un clic, ya te dice, hay algunos checks que todavÃa no se han completado.
Y ves que pone aquÃ, say hello barra hello world.
Esto es el nombre que le hemos puesto al workflow.
Y el hello world es el nombre del trabajo que le hemos puesto.
Le podemos dar a detalles y esto nos lleva directamente a la ejecución de nuestro workflow.
Nos va diciendo todos los pasos.
En este caso, solo ha tardado 19 segundos.
Y hace un segundo que se ha ejecutado.
Todo ha ido bien porque aquà vemos que tiene un check.
¿Ves?
Check.
Perfecto.
Si hubiera fallado, nos hubiera puesto un fail.
Entonces, aquà nos pone los diferentes pasos.
Setup job.
Nos dice toda la información del sistema operativo.
El entorno.
Los tokens de los permisos que tenemos.
Esto lo veremos un poquito más adelante.
Hacemos el eco del mensaje.
Y ya ha terminado el trabajo.
Bueno, este es el job.
Seguramente uno de los más piratas, más aburridos del mundo.
Ahora lo complicamos un poco.
Si no, también le podéis dar a Actions.
AquÃ, si le dais a Actions, ya podéis ver todos los workflows que hemos ido ejecutando.
Hace un minuto, ha tardado 11 segundos.
Y este es el primero.
A través del commit add or first workflow GitHub Actions, ha empezado este en la rama main.
Y aquà podemos ver, además, los diferentes workflows.
Porque, como he dicho, podemos tener más de uno.
De hecho, luego tendremos más de uno.
Asà que veremos cómo funciona.
Vamos a hacer más cositas.
Ahora ya tenemos aquà Steps.
Tengo el eco del message.
Vamos a poner más Steps.
Para que veas las posibilidades que tienes aquÃ.
Importante de los Steps que estén alineados.
Cuando ponemos aquà en YAML, ponemos este guión, lo que quiere decir es que Steps es como un array.
Y cada guión lo que está haciendo es ser un elemento del array de Steps.
En este caso, solo habÃa puesto uno.
HabÃa puesto el name.
HabÃa puesto este.
Pero si yo quito este name y lo ponemos aquà en el run, aquà es exactamente lo mismo.
El nombre es totalmente opcional.
Lo importante es que vayamos separando con el guión cada uno de los pasos que queremos que tenga.
Asà que lo tengas en cuenta.
Asà que tiene que estar también alineado.
Tiene que estar al mismo nivel.
¿Qué más podemos hacer?
Al final, como esto es una máquina, podemos ponerle dime la fecha.
Y le ponemos aquà en run.
Vamos a poner date.
Este lo vamos a poner aquÃ, en la misma lÃnea, para que lo veas.
Y aquà vamos a poner directamente un run del LSL.
Vamos a hacer esto para que veas un poco como es una máquina realmente y que podemos enviarle cualquier comando que nos interese.
Add new commands for workflow.
Vale.
Puseamos.
Y vámonos otra vez aquÃ.
Normalmente hay que refrescar manualmente.
Hay veces que, mira, eso te iba a decir, hay veces que hace esto, que automáticamente lo detecta y te aparece.
Pero hay veces que a lo mejor si ves que no te lo detecta, pues lo refrescas manualmente y ya está.
Vale.
Está muy bien porque ya hemos visto cómo estaba en amarillo, se ha puesto en verde.
Volvemos a entrar.
Aquà nos pone todos los pasos, todos los trabajos.
Ahora solo tenemos uno, pero más adelante verás cómo van apareciendo todos los que vayamos haciendo en el siguiente workflow.
Y aquà tendrÃamos el echo de message.
Dime la fecha.
Ahora ves, aquà tienes el nombre porque le he puesto un nombre a este paso.
Pero el siguiente ves que pone ejecutar es lsl porque no le he puesto ningún nombre.
Aquà he ejecutado el comando date, me ha dicho la fecha, lsl y bueno, no tiene ningún archivo.
Y aquà es uno de los primeros, no problemas, pero uno de los primeros retos que vamos a tener.
Y es el hecho de que nuestra máquina de GitHub Actions está vacÃa.
O sea, no tiene ficheros.
He hecho un lsl y fÃjate, no tiene nada.
Total, cero.
O sea, estoy ejecutando esto ahora mismo en una máquina vacÃa.
No me está aportando absolutamente nada.
Vamos a arreglar esto porque, claro, no tiene sentido que intente hacer comandos en algo que no tiene nada.
Está vacÃo.
¿Cómo vamos a hacer esto?
Bueno, vámonos a crear otro workflow.
Nos vamos aquÃ, en workflows, vamos a crear ahora el pipeline.
Le voy a llamar pipeline, que básicamente un pipeline, digamos que es una tuberÃa en la que pasan todos los procesos por los que fluye nuestra aplicación.
Le podéis llamar como quieras.
Pero yo le voy a llamar deployment pipeline.
¿Por qué?
Porque al final lo que vamos a hacer es el despliegue de nuestra aplicación a producción.
Vamos a decir que trabaja cuando se hace un push en la rama de master.
Aquà esto hay otra forma de escribirlo, luego lo veremos.
Pero por ahora quédate con esta.
He puesto master, pero deberÃa ser main.
Importante que sea tu rama master, de verdad.
Aquà al final lo puedes hacer con cualquier tipo de rama.
En este caso, nuestra es la main.
Vamos a decir los trabajos que tenemos.
Por ahora voy a hacerlo todo en uno.
Entonces le voy a llamar deploy, pero luego lo separaremos en diferentes jobs.
Y ahora en el deploy le vamos a decir que se va a ejecutar el sistema operativo 1804 de Ubuntu.
Y vamos con los pasos que tenemos que dar para conseguir esto.
¿Qué pasa con esto de los pasos?
Como hemos dicho, yo lo que quiero es conseguir el código, ¿no?
Porque es que ahora mismo aquà lo tengo vacÃo.
Lo que quiero conseguir seguro es tener el código de mi propia aplicación.
Asà que ahora lo que vamos a ver es el concepto del marketplace de la GitHub Actions.
Porque si hay una cosa que es brutal de GitHub Actions es el hecho de que las acciones se pueden componer de otras acciones a su vez.
Una locura.
¿Qué quiere decir esto?
Lo que quiere decir es que yo lo que necesito serÃa hacer un checkout de mi proyecto, ¿verdad?
Pues voy a buscar checkout en el marketplace de GitHub.
Si yo busco checkout, podremos ver aquà que hay aplicaciones y aquà tenemos acciones.
Y hay un montón de acciones.
Hay una acción que justamente hace lo que necesito.
Checkout a Git Repositorio at a Particular Version.
Esto es lo que quiero yo.
Quiero hacer un checkout.
O sea, quiero traerme el repositorio a mi máquina.
Pero ves que hay un montón.
Hay un montón.
Submodule Checkout, Spark Checkout.
Aquà te puedes volver tarumba.
Hay aquà para enviar notificaciones, hacer testing de mobile, para hacer localización.
Hay de todo.
Hay de todo.
Esto no te lo terminas.
En este caso el que nos interesa es este que además, fÃjate, los que están verificados suelen ser bastante chulos.
Asà que vamos a utilizar este que es oficial además de GitKab.
En este lo único que tenemos que hacer es decirle quiero utilizar esta acción
y con With tú puedes pasarle la configuración de esta acción en concreto.
Y de hecho, en este caso no vamos a necesitar ninguna configuración, pero es bastante interesante porque le puedes decir el repositorio,
que por defecto es tu propio repositorio, pero podrÃa ser otro.
PodrÃas hacer un checkout de otro repositorio que fuese tuyo o incluso que estuviese abierto.
Luego, el token que vas a utilizar, que todo esto te lo resuelve de forma totalmente automática.
Piensa que tú aquà realmente podrÃas hacer, igual que hemos hecho aquÃ, que hemos hecho el run y hemos hecho esto,
aquà podrÃamos empezar a hacer git, clone, no sé qué.
Pero claro, tendrÃas que configurarlo, tendrÃas que pasarle el token, tendrÃas que hacer un montón de cosas.
Pues con esta acción, esto lo está haciendo totalmente gratis para ti, sin que tú te tengas que preocupar de absolutamente nada.
De hecho, aquà podemos ver algunos de los ejemplos.
Dice, usando esta acción con un fetch depth cero.
Esto lo que hace es que solo se trae el último commit para hacer el git checkout mucho más rápido.
Bueno, pues podrÃamos hacer esto.
Este users lo tenemos que poner en los steps, ¿vale?
En los steps le vamos a decir que tenemos una step que es utilizar el actions checkout y le decimos con la opción del fetch depth que sea cero,
para que eso solo se traiga el último commit, asà lo hará lo más rápido posible.
Ahora bien, ¿qué es lo que me gustarÃa hacer aquÃ?
Bueno, lo que quiero hacer en la Github Action, en este workflow, es instalar las dependencias y lintar el código.
Asà que, ¿cómo puedo conseguir eso?
Bueno, lo que necesito es Node.
Asà que podrÃa, de la misma forma que hemos visto antes, podrÃa hacer un run, instalar MVM y con MVM instalar Node y todo esto.
Pero, obviamente, hay muchos proyectos que necesitan Node, no es el único.
Asà que buscando en nuestro Marketplace, vámonos a nuestro Marketplace.
Entonces, si yo aquà busco Node, pues vamos a ver que tenemos un action que es Setup Node.js Environment, que es justamente lo que necesitamos.
Asà empezamos a componer con acciones que no tenemos que nosotros escribirlo todo.
Esta también es oficial de GitHub.
Y con esto, mira, es que además aquÃ, esto es lo más tÃpico en cualquier proyecto de Frontend, que, o, sÃ, de Frontend o de Backend que esté hecho con Node.js.
Entonces, lo que vas a ver muchas veces repetido son estos steps.
Uno, hacer el checkout.
Dos, hacer el setup de Node con la versión que quieres.
Luego, hacer la instalación y tal.
Bueno, pues vamos a copiarnos esto para decirle que queremos utilizar esta versión.
Y lo intentamos correctamente.
ImportantÃsimo.
ImportantÃsimo.
Luego, fÃjate, esto es una recomendación, aunque si tienes la extensión no te va a pasar nada.
Pero, ¿ves que yo tengo los simbolitos, estos puntos?
Estos puntos son espacios.
Y yo tengo que estos sÃmbolos que normalmente son transparentes, ¿no?
Que no los ves, son invisibles.
Yo lo que tengo es que cuando selecciono los veo.
¿Por qué?
Porque hay veces que se te puede colar una tabulación con espacios y entonces el YAML no te funciona correctamente.
Y yo estas cosas, para no volverme loco, ya lo tengo bastante controlado.
Vale, pues ya utilizamos estas dos acciones.
Ya tenemos el checkout, tenemos el setup Node.
Ahora le vamos a decir, pues vamos a crear aquà otra.
Y vamos a tener, instalar las dependencias, ¿no?
Queremos instalar las dependencias.
¿Cómo lo hacemos?
Pues ejecutamos en PMInstall.
Ahora también vamos a tener otra.
Y aquÃ, ¿qué le vamos a hacer?
Vamos a empezar con el linter.
El linter es súper tÃpico que se ejecute en Continuous Integration.
Ya sea Travis, GitHub Actions, CircleCI, GitLabCI, lo que sea.
¿Por qué?
Porque, hombre, el linter es lo que te asegura que el código que estás integrando en la rama master o en la rama que sea es correcto.
Asà que vas a querer evitar que se integre si no está bien.
O que al menos te notifique que estás intentando integrar algo que no está bien.
Asà que vamos a hacer un run de npm run slint.
Creo que era, si miro, voy a mirar por aquÃ.
Vale, esto no lo cerramos.
Pero creo que en el package.json habÃamos puesto el script era slint.
¿Vale?
Muy bien, pues por ahora vamos a dejarlo asÃ.
Vamos a probar que esto funciona, que todo ha ido correctamente.
Vamos a añadir Add New Pipeline Workflow.
¿Vale?
Y lo hacemos un push para nuestro proyecto.
Volvemos por aquÃ.
Aquà deberÃamos ver la bolita.
Súper interesante.
Esta bolita está muy bien porque cuando está amarillo es que se está pasando y visualmente lo ves.
Pero también luego se pone en verde o se pone en rojo.
Y al darle, pues directamente puedes ver.
Aquà podemos ver que se están ejecutando los dos workflows.
Por un lado el de decir hola, que habÃamos puesto, lo he dejado ya porque total no pasa nada.
Y por otro lado tenemos el deployment pipeline que acabo de crear.
Yo podrÃa ir a Actions y verlo de otra forma.
Aquà podemos ver que tenemos los dos workflows.
Deployment pipeline y say hello.
Te puedes enfocar en uno u otro.
PodrÃas ir al say hello o el deployment pipeline.
Este es el más interesante.
Asà que vamos a ver este.
Además este todavÃa se está ejecutando porque tiene que hacer bastantes más cosas.
Vámonos por aquÃ.
Vámonos al deploy.
Y fÃjate que está instalando las dependencias y ha tardado 33 segundos.
Lo interesante, que ya ha pasado el linter y aquà hay mucho rojo.
Pero ha pasado el linter, me está diciendo todos los errores.
Lo cual está muy bien.
Y además lo que ha detectado es que el proceso que estaba haciendo ha salido con un código que no es cero.
Los comandos, los procesos pueden salir con un montón de códigos.
Pero básicamente si es cero es que ha ido bien.
Si no es cero es que ha ido mal.
Normalmente se sale con el código 1 para decir que no ha salido correctamente.
De hecho ves, exit status 1.
De esta forma es como el continuous integration detecta que el comando que estabas utilizando ha apretado.
Lo hace con esto, con el exit status 1.
Y una vez que sale, ya podemos ver aquà que nos sale bien grande.
Como te he dicho, si volvemos al repositorio, ves, aquà tienes ahora esto.
Esto es muy genial porque lo ves.
Pero también podrÃas incluso, si vamos aquà a las actions, veremos que en un sitio aquÃ,
Deployment Pipeline, aquÃ, en estos tres puntitos, ves que pone aquà create status batch.
Este lo puedes dar y lo que te hace es poder crearte este batch que tú puedes añadir en el README.
De esta forma, pues nada, te lo copias, te puedes ir al README, te lo, vamos a poner aquÃ, lo pegas ahÃ.
Y luego cuando haga un commit, pues vamos a tener, al menos en el README, ver cómo ha quedado la última vez,
que es todavÃa más grande y mucho más potente.
Bueno, ya sabÃamos que iba a fallar el linter, pero era una forma de ver justamente, ¿no?
También otra cosa que te quiero enseñar es que si vas aquà a las actions y le das al workflow que ha fallado,
vas a ver que sin necesidad de entrar al detalle, como lo hemos hecho, aquà ya te indica las anotaciones.
Y en las anotaciones te está diciendo todos los errores que ha detectado.
Y fÃjate que los errores que ha detectado son los errores que te da el linter.
Los strings tienen que ser asÃ, aquà hay un semicolon de más, o sea, aquà tienes ya anotaciones.
No hace falta siempre que entres al detalle del log, sino que desde fuera ya lo puedes ver.
Obviamente el detalle del log es mucho más interesante porque tiene mucha información,
pero desde fuera ya podrÃas incluso ver cada uno de estos errores.
AquÃ, pues además te dice la lÃnea, el archivo y tal.
Bueno, vamos a echar un vistazo y nos pone que este error ha pasado en app.js.
Vámonos a nuestro proyecto.
Vamos a app.js.
Aquà puedo ver que también el editor me está diciendo que tengo todos estos errores.
Voy a formatear directamente el archivo y me los va a solucionar porque me va a hacer un fix del sling directamente.
Me ha solucionado los que ha podido, los que no ha podido me los ha dejado, me ha dicho, estos te encargas tú.
Este process is not defined.
Bien, vale, esto es porque seguramente el linter, si vamos a la configuración del linter,
en environment no tiene el environment de node a true.
Y por lo tanto, la variable global de process no la encontraba.
Ahora sÃ, ¿ves?
Y la detecta como que es un proceso de node.js.
Perfecto.
Y luego tenemos este unexpected console statement.
PodrÃamos hacer dos cosas.
Uno, hacer un sling disable line del no console.
Y esto, pues ya lo tendrÃamos.
O, bueno, para currarnos en salud, podrÃamos venir aquà al no console y decir que nos diga que es un warning.
Porque no es raro que tengamos console logs en la parte del servidor.
Y que ahà pongamos este tipo de información.
Puede no ser un error.
¿Vale?
Asà que vamos a dejarlo asÃ.
Y por si acaso, aquà en la terminal, voy a ejecutar aquà en la terminal, npm run sling, a ver si todo está bien.
¿Vale?
Ahora me dice los warnings del console.
¿Vale?
Perfecto.
Pues vamos a fix lint.
Vamos a hacerlo bien.
Fix lint errors.
¿Vale?
Y aquà vamos a hacer add t-cap action batch status.
¿Vale?
Hacemos un push de todo esto y vamos a ver cómo queda.
Vámonos por aquà a ver cómo queda el batch.
¿Vale?
¿Ves?
Este batch lo que te enseña es el estado de la última vez, de la última ejecución.
Asà que hasta que no dé verde, esto no va a volver a pasar a ser verde.
¿Ves?
TodavÃa está failing porque no sabes si va a ser verde o failing el siguiente.
Vamos a darle aquÃ.
Vamos al deployment pipeline.
Vamos a ver si ahora sà que se está ejecutando correctamente el linter.
Voy a mirar una cosa con la instalación para hacerla más rápido.
¿Ves que tengo aquà un package lock?
Pues vamos a poder hacer las instalaciones un poco más rápido y ahora te explicaré un poco cómo y te revisamos esto.
Vale, ahora ha funcionado todo correctamente.
El linter me muestra los warnings.
Ha instalado las dependencias.
Son 18 segundos.
Tampoco mucho.
Mira, aquà se podrÃan hacer dos cosas.
Y esto es muy tÃpico de hacerlo en continuous integration.
Uno.
Como puedes ver aquà el npm install, cuando los instala, tenemos aquà que además está haciendo lo del funding y además está haciendo lo de la audición.
O sea, audición de la seguridad de los paquetes.
Y te dice, oye, he encontrado 5.277 vulnerabilidades.
Aparte de que esto añade bastante ruido, además de eso, no se lo ve nadie y tiene un impacto en el tiempo que tarda.
A lo mejor es una cuestión de segundos.
Pero bueno, cuando estamos hablando de 18 segundos, pero que los ejecuta mil veces, todo suma.
Asà que, una cosa que puedes hacer serÃa, aquà en la instalación que estábamos haciendo anteriormente, en el pipeline, podrÃamos hacer esto.
No audit y no fund.
Incluso podrÃamos decirle no optional, ¿vale?
Para que no instale las dependencias opcionales.
Por ahora voy a hacer esto, pero seguramente después lo voy a cambiar por otra cosa que es todavÃa más rápida.
Pero bueno, solo para ver cómo va evolucionando el tema de la rapidez.
Porque el optimizar la integración continua para que tarde lo menor posible, lo menor tiempo posible, vas a ver que también es una cosa súper importante.
Bueno, ya tenemos esto, ¿no?
El linter.
Perfecto.
¿Qué queremos hacer ahora?
Pues aparte del linter, vamos a querer hacer la build de nuestro proyecto.
Asà que le voy a poner build.
Vamos a decir run, npm run build.
Vamos a hacer la build, ahora que lo tenemos bien.
Y, por supuesto, después vamos a ejecutar los tests.
Asà que hacemos un npm test y con esto ya tendrÃamos la build y los tests.
Vamos a comprobar.
A ver, ya hemos visto antes en local si yo hacÃa un npm test que fallaba, ¿eh?
Pero bueno, veremos el fallo en Condition Integration y lo arreglaremos y tal.
Y luego veremos dónde sale este error.
Vamos por ahora a añadir la build y el test con estas nuevas opciones, parámetros del npm install.
Yo, si me preguntas, ¿eh?
Si me preguntas, estas opciones del no audit y el no fund, yo los tengo también en local.
Porque para mà también suelen ser bastante molestos.
GitHub, ya por sÃ, te suele avisar cuando tiene vulnerabilidades en las dependencias de tu aplicación.
Por lo tanto, que cada vez que haces un npm install te avise y además te llene el log.
Yo es que los ignoro.
Entonces, lo que te recomiendo es que hagas un npm config get audit y aquà verás, ¿ves?
Yo tengo un false.
Igual a ti te será la true.
Pues puedes hacer un npm config set audit y le pones el valor que quieras, pues false.
Y lo mismo lo puedes hacer para el fund, ¿vale?
Yo con el fund, que es para saber qué proyectos son los que aceptan funding, yo también los tengo a false.
De esta forma, cuando yo hago localmente un npm install, no me hace esas comprobaciones y araño unos segundos.
Pero yo todo lo que sea ganar segundos, a tope con eso.
Asà que, bueno, vamos a build and test app in deployment pipeline, ¿vale?
Vamos a pushear los cambios.
Estos son aliases que tengo yo, ¿eh?
El gcmsg, ggpush, estos son aliases que tengo.
Nos vamos a actions y, bueno, aquà tenemos otra vez el say hello, que si queréis lo puedo quitar, porque si no va a estar ahà todo el rato.
Y el deployment pipeline, que es el que nos interesa.
Pues nada, entramos aquÃ.
Luego esto lo vais a ver tan bonito cuando...
Vamos a ir poco a poco, pero el final es muy bonito.
Vamos a ver si mejora un poco la instalación.
Igual no se nota.
Igual hay veces que la instalación fluctúa y además, como tarda relativamente poco, igual no vemos una mejora realmente.
Creo que sà que veremos más mejora que lo que haremos después en la instalación.
Vamos a ver.
De hecho, mira, ahora está tardando 18 y aquà ha tardado 22.
Ha tardado un poco más incluso, poniéndole los...
No es que tarde más, ¿sabes?
Porque alguien ahora puede decir, hostia, has hecho que tarde 4 segundos más.
No, lo que pasa es que hay veces que puede tardar 18, como puede tardar 30 y el hecho de que añada estos parámetros, lo que puedes hacer es que normalmente tarde menos.
Pero no se fija, siempre tarde menos.
No tiene un impacto tan grande y tarda muy poquito como para que tenga un impacto real.
Pero al menos el lock, que también es importante en Continuous Integration, tener el lock, lo que te muestra, limpio, pues ves, ahora no aparece nada aquÃ.
En cambio aquÃ, cuando habÃa hecho la instalación, no sé, nos aparecÃa esto.
¿Vale?
Bueno, lo importante.
¿Qué nos ha fallado?
Aquà tenemos el jest, nos sale un montón de fail.
Bueno, esto es console.log, console.logs y nos ha fallado aquà y por lo tanto no ha continuado ejecutando, nos ha salido la x y tal.
Bueno, vamos a arreglarlo en un momento.
Ahora que hemos visto más o menos dónde está el error, tenÃa algo del next y el previous, ¿no?
Que el previous, ese enlace sà que va bien, pero el next no tiene la información correcta.
Vamos a buscar en el source, me imagino, Pokémon Page.
Vamos a ver aquà el next.
Next.
Next.
Next.
Vale.
Vale, ya veo el error.
Pokémon PreviousName.
Claro, este funciona correctamente, pero aquà en lugar de utilizar el next, está utilizando el previous otra vez.
Asà que le ponemos aquà el next y ahora si ejecutamos los tests, pues ahora deberÃan funcionar correctamente.
Vale, vamos a verlo.
Vale, ahora sà que pasan los tests.
No sé si se ha visto porque eso está muy abajo, pero que ahora funciona correctamente.
Vale.
Por ahora voy a hacer esto.
Vamos a hacer el fix next link with correct info.
Vale.
Pusheamos y bueno, vamos a dejar que eso se vaya haciendo por ahÃ.
Mientras, luego lo veremos que está en verde.
¿Qué vamos a hacer ahora?
Bueno, los tests que tenemos están muy bien, pero unos tests que son muy tÃpicos, que se suelen utilizar en este tipo de aplicaciones, son los de end to end.
Y lo vamos a ver.
Vamos a ver cómo los podemos hacer.
Y además te voy a decir una buena práctica que puedes hacer para evitar que tarde de más el Continuous Integration.
Ya te digo que es súper importante optimizar el tiempo del Continuous Integration.
Entonces, lo vamos a hacer con Cypress.
Lo vamos a hacer bastante rápido.
Si no sabes de Cypress, pues te recomiendo un montón que vayas a mi web.
A mi web, no, a mi canal de YouTube.
Y te busques el...
Hay un vÃdeo este.
Aprende testing con Cypress como lo hace un senior o algo asÃ, me parece que es.
Mira, un chico feliz con unos rulos fantásticos.
Dos chicos o dos personas que no les gusta hacer testing.
Pero en esta clase te explico cómo hacer Cypress, por qué es importante, tal, tal, tal.
Si no sabes qué es Cypress, ahà lo tienes.
Pero es para hacer testing en tu end.
Entonces, lo más tÃpico, lo que harÃamos normalmente, ¿no?
SerÃa hacer, bueno, pues tienes que instalar Cypress, ¿no?
Y te dirÃa, haz un npm install de Cypress y save dev.
¿Cuál es el problema de hacer esto?
Bueno, no es un problema.
Pero lo que estarÃamos haciendo con esto, Cypress es una dependencia muy grande.
Muy, muy, muy grande.
Piensa que se instala un navegador.
Entonces, ya no solo la dependencia al paquete de notes es grande, sino que tener que instalar el navegador es bastante importante.
Entonces, vamos a evitar este paso.
Y vamos a hacer que se instale, o sea, que se ejecute y se descargue solo cuando sea necesario.
Lo que vamos a hacer para ello, nos vamos a ir aquà al Package.json.
Y lo primero que vamos a hacer aquà en scripts, además esto es una cosa que podéis utilizar para un montón de cosas, asà que es muy interesante.
Igual que tenemos aquà un start prod, voy a añadir un start test, que va a ser lo mismo, pero lo vamos a poner en modo test.
Con la variable del node environment lo vamos a poner en test.
Y ahora que tenemos esto, pues voy a crear mis test end to end.
Vamos a poner un script que sea test end to end.
Y para esto, lo que vamos a hacer es ejecutar npx cypress run.
npx lo que va a hacer es ejecutar al vuelo el paquete de cypress, de forma que hasta que no lo necesite, no lo va a instalar.
Tú podrás tener tu aplicación y cuando ejecutes este script, entonces será que instalará en la carpeta temporal la dependencia de cypress y lo ejecutará de forma global.
Asà que de esta forma nos evitamos el npm install y hasta que no lo necesites, no se instalará.
Para que lo veas, yo ahora mismo podrÃa hacer un npm install, no instalarÃa cypress, pero en cuanto haga un npm run test end to end, ahora sÃ, voy a hacer esto un poquito más grande, ahora dirá, me va a preguntar y todo.
Oye, ¿quieres que instale realmente cypress? Porque claro, tengo que instalarlo si quieres que ejecute este comando.
Vamos a ver si funciona.
Vale.
Ah, bueno, será que ya lo ha detectado por algo, no sé por qué, pero ya lo tenÃa instalado.
Claro, puede ser que haya hecho un npx antes de cypress y ya esté la dependencia en el directorio temporal.
Si no lo tienes, aquà te preguntará y te dirá, oye, ¿quieres que instale cypress? Le dices que sà y ya está.
Aquà ahora me está fallando porque me dice que no encuentra la configuración de cypress y todo esto.
Vale, no pasa nada, pues la configuración de cypress, se le pueden pasar opciones para que no te pida la configuración.
Pero bueno, le vamos a dar la configuración que sea vacÃa para que se deje quejar y lo que vamos a hacer es crear aquà nuestros test de integración.
Va a ser un test de integración bastante sencillo.
En cypress barra integration barra app.js, aquÃ, ¿ves? En este directorio vamos a crear nuestros test de integración.
Aquà hay un tema importante. No pongas .spec ni .test porque como está utilizando jest el proyecto, se liarÃa y entonces podrÃa intentar ejecutar los test de cypress.
Este es el directorio por defecto que utiliza cypress, pero si no te gusta puedes configurar justamente aquà en cypress, le puedes poner la configuración que quieras.
No me acuerdo ahora cuál era la configuración, pero creo que eran integration folder o algo asÃ.
Bueno, como no te he dado autocomplete, pero bueno, que lo puedes configurar si no te gusta justo esta carpeta.
Vamos a poner un test que sea bastante fácil. Voy a ejecutar otra vez npm start.
Vamos a ver un poco lo que podrÃamos testear.
A ver qué tenemos por aquÃ.
Vale. Mira, aquà al fondo no se ve, pero vamos a hacer dos cosas.
Uno, ¿ves que aquà hay este string? Pues este string lo vamos a... vamos a ver si contiene este string y vamos a buscar un Pokémon aquà random, ¿vale?
Eso es lo que vamos a hacer para asegurarnos que funciona correctamente nuestra aplicación.
Asà que hacemos un describe, le llamamos Pokédex y aquà pues tenemos una función y en la función vamos a hacer que la página de frontal pues can be open, ¿vale?
Al menos vamos a asegurarnos que se pueda abrir.
Vale, esto lo hacemos por aquà y aquà pues vamos a hacer que... ¿Cuál es la página que tiene que visitar?
La página que tiene que visitar serÃa http localhost 5000.
Lo que tengo que hacer es ver si hay alguno que contiene al Pikachu, por ejemplo.
Bueno, espérate, espero que esté Pikachu.
Pikachu, vale. Pikachu.
Y luego el ccontains que tenga la frase esta que he dicho que salÃa al fondo.
Vale, esto por un lado. Bueno, ahora se me queja por el tema del linter. FÃjate que me dice CI is not defined.
Aquà tienes diferentes opciones. Una, instalarte el plugin de Cypress, que serÃa lo correcto seguramente,
o hacer lo que voy a hacer yo para ir por faena, que es poner aquà una global de CI.
O sea, esto lo que hace es indicarle al linter que hay una variable global que es esta de aquà que la vas a utilizar en tu fichero.
Bueno, de esta forma deja de preguntarte. Pero lo mejor serÃa utilizar el plugin porque de esta forma tendrÃas autocompletado de esta variable global y todo esto.
Pero bueno, como esto va a ser todo lo que vamos a hacer de Cypress, ya está bien.
Muy bien. Vamos a quitar esto. Entonces, hacemos la build para que nos pille todos los últimos cambios que hemos hecho arreglando los tests.
Hacemos el npm run start test.
¿Vale? Ahora lo tenemos en el puerto 5000. Vamos al puerto 5000.
Parece que funciona. Por lo tanto, voy a abrir otra pestaña y vamos a ejecutar los tests en tuen para ver si pasan.
A ver si todo funciona correctamente.
Y esto es lo mismo que haremos en Continuous Integration.
Pero bueno, está bien que justamente te asegures primero si en local todo funciona bien, porque si no es un poco rollo.
¿Vale?
¿Ves? Esto es lo que comentaba antes. Antes alguien me preguntaba, ¿cuál es la diferencia si con Cypress puedes hacer todos los cambios?
Porque no nos haces todos los cambios en Cypress, o sea, todos los tests en Cypress, en lugar de hacer los unitarios.
Y este es el tema, ¿no? Es que los tests, los end to end, son más lentos que los unitarios o incluso los de integración.
Aquà podemos ver cómo ha tardado 8 segundos, o sea, hacer un test que es bastante sencillo.
No escala muy bien. Tienes que hacer test de end to end para funnels que sean muy importantes y crÃticos para tu aplicación.
Porque el problema es que le lleva demasiado tiempo.
Si tú te pones a hacer todos los tests aquÃ, pues no va a tardar demasiado tiempo.
No va a tardar muy poco tiempo, sino que se va a tomar su tiempo.
Lo bueno, pues que puedes hacer que guarde vÃdeos. Por ejemplo, mira, aquà me ha guardado un vÃdeo.
Vamos a ver si me lo pone. ¿Ves? Me guarda un vÃdeo y aquà te deberÃa enseñar un poco la aplicación.
¿Qué es lo que ha hecho, no? Bueno, no sé, a ver si ve.
¿Vale? Visitar la página. Ahora deberÃan ser aquà los pokémons.
Entonces ahora mirar cada paso es súper potente, la verdad.
Pero el problema, ¿ves? Ahora ha encontrado el Pikachu y ha encontrado el Pokémon a un Pokémon carácter.
Pero el problema es que es bastante lento. Pero bueno, si hay un error, pues tienes el vÃdeo y es bastante genial.
Ahora que ya tenemos esto en local, ya tenemos el test end to end, perfecto.
Pero justamente fÃjate cómo se llaman los tests de Cypress.
Integration. Esto no es casualidad. Esto no es casualidad.
Y es que los tests end to end, claro, tenemos tests de integración.
Pero cuando hablamos de Cypress, de integration y tal, es porque justamente la gracia que tienen estos tests end to end
es que acaben en continuous integration.
Porque son los que se van a asegurar que gran parte del funnel, de la experiencia del usuario, funciona correctamente.
Asà que vamos a añadirlos a nuestro pipeline. No iban a ser menos.
Para añadirlos, pues nada, lo mismo. Vamos a crear aquà un name.
Luego esto lo vamos a refactorizar y vas a ver lo bonito que queda.
Vamos a poner los tests.
Y aquà vamos a utilizar otra GitHub Action.
Asà que vámonos a nuestro marketplace.
Que por cierto, las actions antes le hemos dejado...
Vale, estaba en verde cuando he hecho el fix.
Digo, a ver si lo hemos dejado en rojo y yo me he puesto aquà a ver a hacer otras cosillas.
Vale, vámonos al GitHub Marketplace.
Este de aquÃ.
Y vamos a volver a buscar aquà a ver si tienen algo con Cypress.
Y obviamente deberÃa...
Pensaba que iba a salir mucho más fácil.
Porque Cypress tiene su propia...
Cypress.io.
A ver.
By Cypress.io.
Creo que es este.
Este sÃ.
Este es de los propios creadores de Cypress que tienen una GitHub Action.
Pues aquà lo tenemos.
Vale.
Pues tiene su propia acción.
Y como podemos ver, es súper sencillo de utilizarlo.
Y es el que vamos a utilizar para no tener que nosotros configurar Cypress.
Cypress normalmente en Continuous Integration, tanto Travis, GitHub Actions, Jenkins y tal, suele ser un rollazo.
Suele ser bastante complejo.
¿Por qué suele ser bastante complejo?
Porque necesita instalar Chrome o Firefox o lo que sea.
Y para compilar Chrome y este tipo de navegadores en Ubuntu, pues necesitas librerÃas, dependencias...
Es un rollo.
Asà que mi recomendación es que utilices esta acción y te vas a olvidar totalmente de configuraciones.
Y suele funcionar bastante bien.
Asà que vamos a usarla.
Vamos a poner aquà en el Uses.
Vamos a utilizar esta acción, GitHub Action, la versión 2.
Hay una cosa que no he comentado antes y es bastante importante con el tema de las acciones.
Que como puedes ver, las acciones están versionadas.
Y la versión es bastante importante, más de lo que parece.
Porque claro, piensa que hay una versión 1, una versión 2 y cada versión puede tener sus opciones y configuraciones distintas.
Y puede tener breaking changes.
O sea, lo que antes funcionaba, mejor no funciona en la nueva versión.
De hecho, igual que esto, evitad siempre utilizar las acciones asÃ.
Se puede utilizar, pero el problema es que esto lo que va a hacer es utilizar siempre la latest.
Si esto pasa, cuando salga la versión 3, pues la puede liar parda y dejar de funcionar el Continuous Integration.
Y no hay nada peor que el Continuous Integration deje de funcionarte de golpe.
Eso lo que va a hacer es bloquear al equipo de trabajo.
Asà que asegúrate de al menos, al menos como mÃnimo, porque también puedes llegar a utilizar el hash del commit,
pero al menos de indicar la versión major.
Por si cambian la versión major, pues que no se rompa.
Asà que aquÃ, igual, ves que pongo arroba versión 2.
Y asà nos aseguramos que está utilizando justamente la versión que queremos de Cypress.
Esta GitHub Action, de la misma forma que hemos hecho esta acción aquà con este width y este width,
esta action también se puede configurar.
Asà que le podemos poner aquà un width y le vamos a indicar diferenciación de configuración.
Primero, le podemos decir cuál es el comando que tiene que ejecutar para inicializar los tests end-to-end.
Pues le decimos comando. ¿Cuál es el comando que quiero que ejecutes?
npm run test end-to-end.
Porque si vamos a nuestro package.json, este es el comando justamente que ejecuta los tests end-to-end.
¿Qué más le podemos decir?
Vale, los tests end-to-end, como has podido ver, que he tenido que hacer yo aquÃ,
he tenido en la terminal esta, he tenido que levantar la aplicación para pasar los tests end-to-end.
Por lo tanto, antes de pasar los tests end-to-end, tenemos que levantar la aplicación.
¿Cómo hacemos esto? npm run start test.
Este run start test es justamente el que he añadido aquà y también creo que es el que he utilizado antes aquÃ,
si no me equivoco.
No sé si he utilizado... sÃ, aquÃ.
npm run start test, he levantado la aplicación y luego he ejecutado los tests end-to-end.
¿Qué más le podemos decir?
Vale, le podemos decir que es...
¿Es wait-on?
SÃ, wait-on, asÃ.
Vale.
Lo que le podemos decir también es dónde está el servidor y que tiene que esperar que se levante
antes de ejecutar los tests end-to-end.
En nuestro caso, http localhost 5000.
¿Por qué localhost 5000?
Bueno, esto no es una cosa que venga de la nada, sino que si vamos a nuestro app.js,
aquà tenemos el puerto, si no le indicamos ninguno, utiliza el 5000.
Y como este es el puerto por defecto...
Por cierto, que esto está mal.
Esto deberÃa ser asÃ.
Porque el puerto puede cambiar.
Pero bueno, era una tonterÃa.
Entonces, si no se le pone ninguno, será el puerto 5000.
Pues asà que, si no le pongo ninguno con el start test, será el puerto 5000.
Y con esto ya tendrÃamos todo el tema de los tests end-to-end.
Asà que vamos a ver si funciona correctamente.
Voy a cerrar esto, voy a cerrar esto también.
Vamos a mirar todos los cambios que tengo.
Keyhub, vale.
Hay una cosa aquà que es importante para...
Claro, porque ya la iba a liar.
Cuando tú ejecutas Cypress en local, fÃjate la de archivos que te ha creado.
¿Ves?
Me ha creado aquà un montón de archivos.
Este sà que es normal, este es el nuestro.
Vale.
El app.js he hecho este pequeño fix.
La configuración de Cypress vale.
En el package.json hemos añadido los scripts que necesitamos.
Perfecto.
En el pipeline hemos añadido los tests end-to-end.
Vale.
Pero estos archivos de aquÃ, estos archivos son...
Que los ha creado Cypress al vuelo.
Estos archivos no los necesitamos.
Para evitar que los subamos sin ninguna necesidad, especialmente el vÃdeo.
Que harÃa que todo fuese bastante más lento.
Lo que vamos a hacer aquà es poner Cypress y lo que vamos a decirle es que Cypress plugins fuera.
Cypress barra support fuera.
Cypress barra videos.
Y estos vamos a hacer que no los suba, que los ignore.
Y con esto, bueno, el support luego podrÃa...
Y plugins puede ser que luego tenga sentido, pero en nuestro caso no tiene ningún sentido.
Asà que vamos a evitarlo para que no los suba sin ninguna necesidad.
Porque son generados y no nos añade nada.
Vamos a añadir el gitignore también.
Bueno, lo vamos a añadir después.
Add end-to-end test to deployment pipeline.
¿Vale?
Y aquà en el gitignore, pues ignore Cypress folders.
Ahora puxamos los cambios.
Y volvemos a nuestro repositorio, a actions.
Vamos a...
Bueno, aquà saldrá en amarillo.
Vámonos al deployment pipeline.
Y esto tardarÃa un ratito.
Asà que mientras se ejecuta, os voy a leer.
A ver qué me contáis mientras bebo también.
Empieza a tardar más, ¿vale?
Ya vamos viendo que nuestro continuous integration le empieza a costar un poquito más.
Entonces, podemos ver un poquito las instalaciones 21 segundos, el linter 2 segundos, la build 5 segundos, el test unitario 3 segundos y los end-to-end ya es 1 minuto 21.
Lo vamos a ver y podemos ver que ha funcionado correctamente.
Como os decÃa, la instalación...
Aquà también está haciendo la instalación de Cypress.
FÃjate aquÃ, ¿vale?
La instalación, pues 8 segundos.
8 segundos que nos hemos quitado del otro lado, pero bueno.
Y luego además, pues va a estar dando otras cosas.
Luego levanta.
Ejecuta el test 12 segundos.
Cosas asÃ, ¿no?
También es verdad que está haciendo el vÃdeo y el vÃdeo no es necesario.
Igual esto lo podrÃamos...
Voy a hacer...
Ahora lo voy a quitar.
De hecho, en Cypress.config podrÃamos ver y quitar el vÃdeo es bastante útil porque es muy difÃcil que tengamos acceso al vÃdeo.
Asà que, ¿ves?
VÃdeo por defecto es true.
Pues puedes hacer dos cosas.
Una, desactivar el vÃdeo completamente o que el vÃdeo solo sea para los errores.
Eso también puede ser interesante.
A ver, vÃdeos folder...
HabÃa uno que era vÃdeo...
¿Ves?
VÃdeo upload on passes.
Claro, para los que van bien no tiene mucho sentido el vÃdeo.
Pero bueno, nosotros lo vamos a desactivar porque no tiene mucho sentido que nos guarde un vÃdeo ahà para nada.
Vamos a ponerlo aquà en la opción.
VÃdeo.
False.
Antes os he dicho que Ãbamos a probar otra cosa para mejorar el npm install.
Pues lo vamos a hacer.
El tema es que cuando tú tienes un package lock, lo que puedes hacer en lugar de hacer un npm install,
el package lock lo que es es como un package JSON pero hipervitaminado
que lo que hace es indicar exactamente qué versiones ha instalado,
en qué orden lo ha hecho, justamente el hash que tiene de integridad.
O sea, es mucho más avanzado.
Y lo que permite es evitar mucho trabajo.
Asà que el npm install lo que hace es ir más rápido.
Pero en continuous integration justamente npm tiene un comando que se llama npmci,
de continuous integration.
O sea, ya lo dice el nombre exactamente.
¿Y qué es lo que hace npmci?
Pues lo que hace es ejecutar npm install de una forma mucho más optimizada
basándose en las dependencias que tienes en el package lock.
Entonces la resuelve mucho más rápido, hace muchas menos comprobaciones
porque no tiene que calcular cómo queda el árbol de dependencias.
Y esto lo que deberÃa hacer es hacer que nuestra continuous integration vaya un pelÃn más rápido.
Vamos a hacerlo, vamos a poner optimice ci with npmci and video cypress to false.
Vamos a enviar esto y vamos a ver si ahora funciona un pelÃn más rápido de cómo lo ha hecho antes.
Aquà ha tardado dos minutos, pues ahora veremos si el siguiente tarda un poquito menos.
Entonces, mientras va pasando y antes de ver todo esto, de cuánto ha tardado,
que bueno, el npm install sà que lo podemos ver porque deberÃa ser más rápido,
tampoco tarda mucho.
Ya os digo que proyectos realmente grandes puede tardar segundos y segundos.
En este caso, ¿ves? No hay mucha diferencia.
De hecho, parece que va a tardar exactamente lo mismo que antes.
O incluso parece que más.
O sea, está tardando más.
Más o menos lo mismo.
No me parece que...
Ah, pero es que no he guardado los cambios.
No he guardado los cambios.
Ay, npm install with ci.
Vale.
Es que no he guardado los cambios.
Pero bueno, con esto voy a enseñar otro tema que es bastante interesante
que también vamos a arreglar ahora un momentito.
FÃjate que yo he hecho otra vez un push de mis cambios.
Por lo tanto, he emergeado en main cambios.
Y aquà se me están acumulando los workflows.
Bueno, justo está cambiado.
Pero este y este se están ejecutando a la vez.
¿Qué pasarÃa si yo tengo dos acciones, dos workflows que se están ejecutando y los dos se despliegan?
Y resulta que el último que se despliega es el más viejo, o sea, este.
ImagÃnate que este termina antes y de repente este sigue ejecutándose y se despliega.
Pues tendrÃamos un error.
Porque tendrÃamos en producción una versión de nuestra aplicación anterior y no la última.
Esto que veis aquÃ, esto que está pasando aquà es súper peligroso.
En continuous integration hay que evitar que un mismo workflow tenga más de una versión ejecutándose a la vez en paralelo.
Y para eso veremos después cómo podemos utilizar una acción súper fácil para evitarlo.
Pero antes de hacer esto, lo que vamos a mirar, voy a mirar si el en pie visto la pesa ha mejorado un pelÃn.
16 segundos.
Antes estaba sobre los 20 segundos.
Bueno, unos segundos que hemos arrastrado.
Y ahora veremos el end to end.
Antes de intentar evitar que haya builds redundantes, lo que vamos a hacer es hacer el deploy con Heroku.
Asà que vamos a ello.
Voy a cerrar también otra vez todo esto.
Y nos vamos a ir a la terminal primero.
Si no tienes una cuenta de Heroku, te la puedes crear.
Es totalmente gratis.
No deberÃas tener ningún problema.
Para hacer esto, vamos a tener que empezar a conocer qué son los secrets.
¿Cómo podemos guardar variables de entorno para GitHub Actions?
Es súper fácil, pero te voy a explicar además por qué podemos tener entornos diferentes.
Primero vamos a conseguir el token de Heroku.
Asà que le damos a Heroku, create.
Vamos a crear una aplicación en la región de Europa y le ponemos el nombre de nuestra aplicación.
Vamos a poner Midu.
Mira qué grande que tiene aquà mis aplicaciones.
El autocomplete de FIC es brutal.
Vamos a poner Midu CIGH.
¿Vale?
Contiguous integration.
GitHub.
Oh, ja.
De GitHub Actions.
Midu CIGH.
Vale.
Vamos a crear esta aplicación.
Vamos a ver.
Vale.
Perfecto.
PodrÃamos entrar, y esto no hay ninguna aplicación ahora mismo.
Veremos si conseguimos desplegarla ahÃ.
Y ahora lo que podemos hacer es recuperar un token.
Asà que hacemos Heroku, authorizations, dos puntos, create.
Esto lo que va a hacer es crearnos un token que nos permitirá justamente hacer el despliegue.
Este token deberÃa ser totalmente privado.
Yo luego lo eliminaré.
Pero bueno, es este de aquÃ.
Lo vamos a copiar.
Y vamos a ir otra vez a nuestro repositorio.
A ver cuánto ha tardado.
Mira, ahora el end to enter se ha tardado 49 segundos.
Ha tardado 40 segundos menos que antes.
Estamos ahà poco a poco optimizando, optimizando.
Vale.
Vámonos a Settings.
Y aquà vamos a ver que tenemos Secrets y tenemos Environments.
En Secrets ya no dice Action Secrets.
O sea, son tokens secretos que podemos tener para nuestro GitHub Actions.
Podemos tenerlas a nivel de repositorio para tener como unos secretos que sean en general.
O lo podemos tener por Environment.
El Environment es súper útil para este caso.
¿Por qué?
Porque puedes tener variables de entorno para producción y para preproducción, por ejemplo.
Vamos a poner un ejemplo.
Voy a crear para el repositorio.
Vamos a poner aquà Heroku API Key.
Y aquà pongo el token que tengo.
Ahora, imagÃnate que por lo que fuese, este es el que tengo por defecto,
pero podrÃa tener uno que fuese para el entorno de producción.
Este serÃa el general que podrÃa utilizar.
Pues en Environments podrÃa crear aquà un New Environment, poner Production,
configurar Environment.
Aquà podrÃas configurarlo justamente para evitar que cualquier persona pueda hacer un push al workflow
y que se ejecute en ese entorno.
Y aquà podrÃamos añadir un secret.
Pues le das aquÃ.
Y aquà podrÃamos sobreescribir justamente el que hemos añadido.
Y aquà le podrÃamos poner otro diferente.
Para que producción se despliegue en otro sitio diferente al que tiene en general.
En nuestro caso, como solo vamos a tener el de general, pues lo vamos a dejar asÃ.
Pero bueno, es interesante que lo conozcas.
Vamos a añadir más.
Vamos a poner Heroku API Email, que es mi cuenta.
Vamos a poner otro más, que es Heroku App.
Que si no me equivoco, a ver qué he creado por aquÃ.
Midu CIGA.
Vale.
Estos son los tres secretos que vamos a necesitar.
¿Por qué la app la pongo aqu�
Lo mismo, ¿no?
Porque podrÃamos tener la app para preproducción, que fuese diferente a la que es de producción.
En este caso lo vamos a poner en general, pero es bastante útil que lo tenga diferenciado.
Ahora, vamos a irnos a nuestro pipeline, porque era de despliegue.
Pues vamos a conseguir que se despliegue, ¿no?
Venga, lo mismo.
Name.
Aquà vamos a poner deploy to Heroku.
Y vamos a poner que esto usa...
Uy, digo, a ver si me lo encuentra.
Me lo llega a encontrar Gijacopilot automáticamente.
A ver.
No.
Pensaba que a lo mejor si le daba una pista lo conseguÃa.
Pero no.
No lo he conseguido.
Bueno, vamos al marketplace y ahora encontramos uno.
Heroku.
Heroku deploy.
Heroku deploy.
A ver si encontramos el que conozco.
Vale.
Mira, aquà tenemos.
Deploy to Heroku.
Por desgracia, Heroku no tiene, o que yo sepa, no tiene una action que sea oficial.
Entonces, la que yo he visto que mejor funciona, y de hecho ya se ve por las estrellitas que tiene, es esta de aquÃ.
No sé si Heroku en algún momento sacará suya propia, ya me extraña que no tenga.
Pero bueno, esta es la que a mà personalmente me ha funcionado y la que os recomiendo que utilicéis.
Asà que vamos a copiarnos esto para utilizar esta Heroku deploy de Akhilensen.
Y aquà justamente tenemos las tres que necesitamos.
Las tres secrets y tal.
Y ahora te explicaré cómo funciona el tema de los secrets.
Vamos a poner esto por aquÃ.
El uses este no necesitamos.
El comentario lo quitamos.
Los secretos que he creado en GitHub, para acceder a ellos, lo único que tienes que hacer es secrets.
Y poner el secreto al que quieres acceder.
O sea, que yo aquà cuando he creado mis secretos, tenemos Heroku API Key, pues este lo harÃamos secrets.
Bueno, este encaja.
Ahora, el app name.
Bueno, pues esto lo mismo.
TenÃamos que poner el dólar, llaves, llaves, lo cerramos.
Y aquà secrets punto y utilizamos justamente el que sea nuestro.
Aquà Heroku app.
Y aquà en el email, pues serÃa lo mismo.
¿Vale?
Esto lo bueno que tienes es que una vez que lo configures por entornos y tal, esto te lo detecta automáticamente.
Y el environment lo puedes configurar aquÃ.
Y lo puedes hacer a través de objetos del contexto y tal, que luego veremos un poquito cómo se saca esa información del objeto del contexto.
¿Vale?
Y en el email, pues el API email.
No sé por qué le he puesto API email, pero bueno, con esto no deberÃa funcionar.
Con esto ya tenemos nuestro deploy a Heroku.
Vamos a añadir aquà add Heroku deploy.
Vamos a pushear los cambios.
Vamos a nuestro repositorio.
Vamos a quitar todas estas cosas.
Esto fuera.
Esto fuera.
Esto fuera.
Fuera.
Vamos a nuestro repositorio.
A ver si lo encuentro.
Ah, mira.
Menos mal que hay gente que le ha dado aquà y asà lo tengo por aquÃ.
Vale.
Vale.
Pues ya está aquà pensando.
Esto me deberÃa fallar.
Y ahora veremos cómo lo podemos solucionar.
Y cómo hacemos algo más para que no nos vuelva a ocurrir el error que va a cometer ahora.
¿Vale?
Asà que os leo un momentito.
¿Alguna action?
Vale.
Eso ya lo he leÃdo.
¿Quién es este último Pokémon?
Yo, como no me los conozco ya, los he perdido un poco de vista a los pobres Pokémon.
Si es que en Sensitive te va a fallar Pikachu.
No, canallazo.
Porque es una buena observación la que ha hecho canallazo.
El caso es que en el test, este, integration, yo he puesto aquà Iptazo.
Venga.
Se está ejecutando.
¿Ves?
Tarda un montón.
Tarda un montón el deploy de Heroku.
La verdad es que Heroku no está muy bien resuelto para el tema de los deploys continuous integration.
Se está quedando bastante atrás.
A mà personalmente no es el hosting que más me guste.
Pero bueno, este proyecto es un proyecto de Node.
Y tal y como está pensado, el mejor sitio para desplegarlo justamente es Heroku.
Entonces, podemos ver que se ha ejecutado correctamente.
Ha hecho la build.
Aquà un montón de cosas.
Ha instalado las dependencias.
Pero, fÃjate, ¿vale?
Se ha desplegado correctamente.
Esto deberÃa funcionar.
Pero, si yo me voy a ver cómo era el app name.
¿Cómo era mi proyecto?
A ver, aquÃ.
Este proyecto.
Si entro, fÃjate que tengo un application error.
O sea, acabamos de desplegar algo que no funciona.
Bueno, vamos a ver aquà en Heroku Logs.
Por suerte tenemos este comando.
Pero vamos a evitar que esto no vuelva a ocurrir, ¿vale?
Vamos a Heroku Logs.
Tail.
No, Tail no, porque nos dice lo...
Bueno, sÃ, nos dice lo último.
FÃjate, aquà me dice el error.
Mira, me dice que ha intentado hacer un npm start y me dice que webpack devserver not found.
Vale.
¿Qué es lo que ha pasado?
¿Cómo podemos solucionarlo?
¿Cómo lo vamos a solucionar?
¿Y qué es lo que ha pasado?
Lo que ha pasado es que por defecto Heroku lo que hace es ejecutar este comando aquÃ, npm start.
Pero Heroku solo instala las dependencias de producción, no las de desarrollo, porque se supone que no las necesita.
Entonces, este start, como está utilizando esta dependencia de desarrollo, no la encuentra.
Aquà lo que deberÃamos hacer más bien es que esto, en lugar de ser start, sea dev.
Y este start prot lo vamos a cambiar a start.
Pero esta es la solución, ¿no?
Con esto lo solucionarÃamos.
Vamos a ir un poquito más allá.
Aparte de hacer esto, de arreglar cómo va a encontrar bien correctamente Heroku la aplicación para iniciarla,
lo que vamos a hacer es añadir a nuestra aplicación un health check.
Esto es súper importante y súper básico, por tonto que parezca.
Hay mucha gente que no lo hace y deberÃa eso.
Vamos a crear dos.
Vamos a crear el health y vamos a crear el de la versión también, ¿vale?
Mira, un health check básicamente es una ruta, vamos a ponerle health,
que lo que hace es responder diciendo que funciona correctamente.
¿Por qué?
Porque con este health check nosotros hubiéramos evitado un montón de problemas.
Ya hubiéramos evitado el problema de intentar deployar algo que no funciona.
Incluso cuando no funcione vamos a poder hacer un rollback,
que eso es bastante fácil hacerlo con esta acción de Heroku y nos puede evitar problemas en producción.
Asà que tenemos este health.
Lo único que hacemos cuando entramos en este health es decir, ok, además de este,
también puedes tener uno que sea versión.
Y aquà hay un trucazo que está muy chulo, que tú puedes recuperar la versión del Package.json.
Package.json.
Que lo tenÃamos aquÃ, Package.json.
En el Package.json esta versión de aquà la puedes recuperar de forma que cada vez que cambie la versión
tú podrÃas indicarle a partir de este endpoint qué versión es la que está desplegada en producción.
Asà que puedes hacer esto y ya lo tendrÃamos.
He puesto un más ahÃ, ¿vale?
Y ya tendrÃamos nuestros dos endpoints.
Uno el del health check y otro el de la versión.
A ver, no creo que haga...
Bueno, vamos a hacerlo.
Bueno, no lo iba a levantar, pero he pensado, venga, va, qué más da.
Puerto 5000, health.
¿Vale?
Aquà tenemos un OK.
Y luego si hago versión, esto deberÃa aparecer 1.0.0.0.
¿Vale?
De esta forma, pues podremos saber la versión que se ha desplegado.
Hay un montón de formas de la versión de hacerlo, pero bueno, esta serÃa una de las formas más sencillas.
Tener un endpoint que te diga la versión que hay en producción y ya está.
Puede ser un endpoint que no digas cuál es y en lugar de llamarle versión que sea un endpoint mucho más largo.
Ahora que tenemos el health check y el tema de la versión, vamos a volver a nuestro pipeline.
Y aquà en las configuraciones de Heroku, además de esto, vamos a poder decirle, mira, pues vamos a tener un health check y te voy a decir dónde está la ruta.
Esto va a estar en https, barra, barra, Heroku App.
¿Vale?
Luego ponemos barra, health.
¿Qué es lo que va a hacer con esto?
Pues va a mirar si realmente la aplicación, una vez que la despliega, el health check responde.
Y si no responde, lo que podemos decirle es un rollback on health check fail.
Y esto lo voy a buscar porque no estoy seguro si esto es asÃ.
Heroku Github Actions.
¿Vale?
Mira, sÃ.
Rollback health check fail.
¿Vale?
Cuando es true, lo que va a hacer es un rollback.
¿Qué es un rollback?
Un rollback es que automáticamente Heroku va a decir, vale, el health check no funciona, voy a hacer un rollback.
O sea, voy a tirar para atrás los cambios y voy a poner en producción una versión anterior que deberÃa estar funcionando.
Esto es un rollback, además, totalmente automático.
Asà que le vamos a decir true y ya tendrÃamos esto.
Ahora que tenemos esto, bueno, para que veas el rollback, lo mejor es que pongas Heroku releases.
Y aquà deberÃamos ver todas las releases que se han hecho.
En este caso son releases que no han funcionado por el problema que tenÃamos antes.
Pero ves, initial release, deploy, no sé qué.
Y estas son todas las releases.
Cada vez que vayamos haciendo despliegues y despliegues y despliegues, pues iremos viendo que cada vez hay más.
Vamos a pushar estos cambios con el health check, add health check, undo rollback if not working.
Y con esto deberÃa, además del cambio del npm start y esto, todo deberÃa funcionar bien.
Mientras se va haciendo, vamos a seguir trabajando nosotros en otra cosa.
Vamos a dejar ahà la action que vaya haciendo su magia.
Ahora, aquà lo tenemos, que está haciendo su magia, como tarda un ratito, mientras vamos a hacer nosotros otra cosa.
Porque, ¿qué pasa? Esto está muy bien.
Todo lo que hemos hecho está fantástico.
Pero claro, alguien me dirÃa, oye, ¿qué pasa si resulta que tú haces aquÃ?
Vamos a crear una nueva... voy a hacerlo aquÃ.
Vamos a crear una nueva rama que sea, no sé, add new feature.
¿Vale? Abro una nueva rama, y en esta nueva rama voy a añadir un cambio cualquiera, que es este de aquÃ.
Bump version.
Voy a pushar estos cambios en una rama y voy a crear una pull request.
Add new feature.
Creo la pull request.
¿Y cuál es el problema?
Pues que nuestra acción no está funcionando aquÃ.
No funcionan las pull requests.
¿Por qué no funcionan las pull requests?
Pues, porque justamente en el pipeline, si le echamos un vistazo, hemos dicho que esto debe funcionar cuando se haga push a la rama main.
Pero es que una pull request, esto, está pidiendo hacer el push, pero todavÃa no lo ha hecho.
Asà que tenemos que indicarle un nuevo evento.
No solo podemos admirarlo en el push, sino que tenemos que añadir un nuevo evento que sea pull request.
Como puedes ver, tienes pull request cuando se hace una review, cuando se abre una pull request.
En este caso, pull request.
Cuando se hace una pull request de la rama, en este caso main, esta serÃa la otra forma de hacerlo.
Mira, se puede hacer asÃ, que es como lo habÃamos hecho antes, o lo puedes indicar aquà como un array.
Asà que ponemos main, y aquà también vamos a ponerlo main, porque creo que se le...
A mà me gusta más esta forma de hacerlo, con un array directamente.
Asà lo tenemos asÃ.
Y aquà en types, además quedará mucho mejor.
Podemos decir cuando se ha abierto y cuando...
Mira, puedes decir cuando se ha abierto, cuando se ha asignado, cuando se ha cerrado, cuando...
Puedes decir cuando se ha sincronizado.
¿Vale?
Cuando se han vuelto a sincronizar los cambios.
Solo cuando se abre y cuando se le envÃa un nuevo cómic, cuando se sincroniza, con lo que sea.
Con esto, ahora sÃ, si voy a subir estos cambios, vamos a la terminal.
Vamos a decir add o listen pull request event for pipeline.
¿Vale?
Puseamos este cambio.
Y ahora, si vamos a la pull request, fÃjate que ahora pone this branch has no conflict with base branch.
Parece que no ha pasado nada.
Voy a refrescar, voy a refrescar la pull request.
Y fÃjate que ahora dice que hay unos checks que no se han completado.
Y es que está pasando aquà justamente el pipeline que hemos configurado antes.
Y está instalando las dependencias, está haciendo el linter, va a hacer la build, el test, hará el end-to-end y hará el deploy.
¿Y queremos que haga el deploy?
¿Queremos que haga el deploy y la pull request?
No, pues cancelamos el workflow que si no la liamos parda.
No queremos que haga el deploy, ¿vale?
Cáncélate, cáncélate, hazme caso, cáncélate.
Vale, ahora sÃ, se ha cancelado.
No queremos que haga el deploy.
Asà que antes, lo he cancelado, el de la pull request, antes de que la lia parda y me haga un deploy donde no debe.
¿Cómo podemos evitar que me haga un deploy en la pull request?
Que no es lo correcto, ¿vale?
Ahora le hemos dicho que sÃ, que tiene que escuchar las pull requests.
Pero los jobs se están ejecutando todos.
Pues existe una forma de indicarle estos pasos que tiene el job, cuál es el que se tiene que ejecutar, dónde.
Vale, para eso puedes utilizar un campo que se llama if.
Y tú aquà puedes hacer mil millones de cosas.
Una de esas cosas es utilizar justamente otra vez lo de la evaluación con las llaves, el dólar y las llaves.
Existe un objeto en la GitHub Actions que tiene toda la información, o sea, digamos que tiene todo el contexto de donde estás trabajando.
Tiene un montón...
Uy, este se ha puesto en rojo.
Espérate.
Espérate, que es que no sé si es el...
A hatchet undo rollback.
Vale, vamos a ver qué ha pasado.
¿Qué ha pasado aqu�
Hatchet...
Has been rollback.
Please check your logs.
No sé qué es o cuánto.
Vale, vamos a ver qué ha pasado aquÃ.
Que parece ser que no le ha gustado lo que...
Heroku logs.
Vamos a ver qué ha pasado.
¿Qué es lo que ha pasado?
Ah, y ha vuelto a hacer esto.
¿Será que no he guardado los cambios antes?
En el package.json.
El start.
No, esto sà que lo he hecho bien aquÃ.
A ver, espera.
Parece que no ha hecho el deploy este.
Health check.
Vamos a ver los commits.
A ver si...
Add health check.
No sé qué, no sé cuánto.
Pero aún asÃ, fÃjate que me ha recuperado lo anterior, ¿eh?
Aquà en el Heroku logs este, ¿eh?
Know the app.
Rollback to versión 3.
Release 5.
Creative user restarting.
¡Ostras!
FÃjate que no me la ha hecho, ¿eh?
Este build started...
Mira, aquà sà que parece que dice server started on port 74.15.
Claro.
Bueno, esto es normal.
De que haga el 74.15.
Vamos a ir a Heroku.
Un momento.
A ver qué le ha pasado.
¿Qué le ha pachado esto?
Heroku testing...
Uy, no me sale...
Ni siquiera me sale el mÃo.
No me sale mi app.
Vamos a ver cómo lo habÃa llamado.
Testing, testing...
Vamos a ver las releases.
SÃ, podemos ver.
MiduCIGA.
Heroku app.com
SÃ, no.
A ver.
Eno end.
A ver, esto es porque ha hecho después el rollback.
Pero al principio sà que parece que habÃa hecho el no de app,
que habÃa funcionado bien.
Lo único que...
Bueno, vamos a...
Para eso no funciona.
Para eso es el continuous integration.
Asà que vamos a ver en la action
cuándo ha fallado.
Si habÃa hecho la build y todo esto.
Vamos a ver.
Build.
La build.
Mientras os voy a leer también.
A ver si notáis dónde estaba el error.
Te hizo el rollback.
SÃ, no.
Me hizo el rollback, pero porque falló el otro.
Falló el otro.
O sea, falló.
Cuando hice la release del 4, hizo el deploy to Heroku.
Eso deberÃa haber hecho el deploy correctamente.
Coat and...
Trolling back to versión 3.
Es súper raro porque parece que todo ha funcionado bien.
O sea, espérate.
A ver si el...
Espérate.
HTTPS barra health.
A ver si el health check lo he puesto mal.
¿Sabes?
Dos puntos barra Heroku app.
Que igual el health check este que he puesto aquà está mal.
Lo que me extraña es que...
Ah, está aquÃ.
Vale, vale.
Ahora he visto.
Vale.
Vamos a ver en activity.
Rollback to versión 3.
Voy a hacer un rollback a la versión que yo quiero.
A ver si...
Build, build lock.
Bueno, esto es justamente lo mismo.
Lo que quiero ver es justamente si el midu este...
A ver si puedo ver...
Open up.
Es que sà que funciona bien.
Es como si el health...
El health está bien.
No sé, no sé.
Es como si esta app no hubiera detectado...
No es exactamente esta que está aquÃ.
O sea, que a lo mejor está mal el tema este de la opción.
Vamos por aquÃ.
En settings.
A ver si he puesto mal el secret o yo qué sé.
Vámonos a secrets.
El Heroku app no tiene toda la URL.
Ahà está.
Ahà está.
Ese es el problema.
Muy bien.
Bien visto.
Claro, el problema es que este Heroku app no tiene toda la URL.
Cuando ha intentado ir aquÃ...
Claro, yo he hecho esto.
Y esto...
Yo he sido super happy.
Lo que tiene que hacer es esto.
Esta parte solo tiene el nombre del subdominio.
¿Vale?
Entonces, donde tiene que mirar el health es en esta parte.
La verdad es que no sé si aquà podrÃamos incluso poner esto.
Pero bueno, vamos a ponerlo asÃ.
Aquà ahora sÃ.
Esta es la parte del app name.
Que es el midu cgi a este.
Luego tenemos aquà esto.
Y luego barra health.
Pero mira, asà hemos solucionado un error aquà en vivo en directo.
Creo que esto es lo mejor.
El que venga con un problema y ver cómo se soluciona de forma real.
Vale.
Lo arreglaremos en la PR.
¿Vale?
Y la PR luego lo mergearemos y tal.
Pero bueno, lo importante...
Bueno, claro, si lo dejamos en la PR...
Bueno, sÃ.
Lo arreglamos en la PR.
Bueno, ya lo tenemos arreglado, pues.
Muy bien.
Vamos a quitar esto por aquÃ.
¿Cómo podemos evitar?
Ahora que hemos arreglado el deploy...
Ahora el deploy va a funcionar correctamente.
Pero tenemos que evitar que ocurra el deploy en la pull request.
Aunque no vendrÃa bien que se hiciese, pero lo vamos a evitar.
¿Vale?
Ya tenemos la aplicación funcionando.
Queremos evitar que la pull request no machaque el deploy.
¿Cómo lo podemos hacer?
Lo que querÃa enseñar justamente antes era el hecho que está GitHub Actions Context Object.
Que tiene un montón de información.
A ver si esto...
Github...
Vale.
Tenemos Github, que es un objeto que tiene un montón de información.
Tienes el environment.
Tienes todo el tema del nombre del commit.
O sea, quién ha hecho el commit.
El nombre de la rama.
Tienes un montón de información.
El evento que lo ha hecho.
El workflow.
El job que se está ejecutando.
El actor.
El repositorio.
Un montón de información.
La información que en este caso nos interesa serÃa el tema del evento.
De hecho, deberÃa haber uno que sea event name.
¿Vale?
Que nos dice justamente el nombre del evento.
Con el nombre del evento podrÃamos decir.
Vale.
Si el deploy to Heroku este lo vamos a hacer solo si este evento, el nombre del evento, es el del push.
Porque el nombre del evento del push que estamos escuchando.
Que es este.
El nombre del evento es este.
Solo lo estamos escuchando en la rama main.
Por lo tanto, cuando sea el nombre del evento push, significa que lo que estamos haciendo es pusheando.
Estamos mergeando a master.
De esta forma, vamos a hacer que esto solo funcione en master.
Ya tenemos esto.
Perfecto.
Ya tenemos el tema del head check arreglado.
Vamos a ejecutar esto.
Para que ahora sÃ.
Make pipeline deploy to work only on master.
Y de esta forma, evitamos que funcione en la pull request.
Porque menuda liada que funcione en la pull request.
ImagÃnate que cada vez que se abre una pull request, te machaque lo que has desplegado.
Pues serÃa una locura.
A ver, podrÃa ser divertido.
PodrÃa estar divertido.
Pero también la gente se podrÃa tirar mucho de los pelos.
Mientras esto se va desplegando.
Veremos que el deploy este se lo salta.
O sea, aquà veremos un ignore.
No veremos ni un error, ni caÃdo bien.
Sino que veremos que se lo ha saltado.
Como un skip.
Mientras esto ocurre, te voy a explicar una cosita.
Que es bastante interesante.
Que es el tema de proteger master.
Ahora que estamos teniendo el tema este de las pull request.
Y todo esto, lo que podemos hacer justamente aquà serÃa en branches, proteger las ramas.
¿Veis que tenemos aquà branch protection rules?
Vamos a crear una nueva regla.
Y en esta regla aquà le vamos a decir que para branch name, para main,
vamos a requerir que el status check haya pasado antes de hacer un merge.
Esto es súper importante.
Porque si aquà añades las pull requests, añades que vas a pasar esto.
Pero fÃjate, tú puedes mergear aquà sin ningún tipo de problema.
Esto no tiene ningún sentido.
¿Qué es lo que estás evitando?
No estás evitando nada.
Solo es un tema informativo.
Asà que un check que tienes que poner es este.
Y luego además, fÃjate que te dice requerir además que la rama esté actualizada antes de mergear.
Esto también es súper útil.
Porque si no, tú aquà lo que puedes hacer es que vale, te voy a obligar.
Pero a lo mejor lo que estás intentando mergear es una versión antigua que no está sincronizada con lo que hay en master o en main.
Asà que también esto está bastante bien.
Además aquà le puedes poner los checks.
En los checks, a ver si creo que deploy.
SÃ, puedes decir el de Hello World, que no es muy útil, o el de deploy, que es el que nos interesa.
Tienes un montón más y ya verás que en mi caso, como soy administrador, si yo voy aquÃ, bueno, ahora porque ha pasado.
Pero si ahora cuando volvamos, mira, ha ido bien, ha hecho verde nuestra PR y fÃjate que el deploy se lo ha saltado.
Ha dicho, vale, me has dicho que me salte el deploy, pues me lo salto y ya está.
Como he dicho que os iba a explicar el tema de eliminar builds redundantes, vais a ver que esto es súper fácil.
Lo primero, donde se tiene que hacer esto de evitar builds redundantes, en el caso de que tengas más de una build a la vez,
que siempre lo vas a querer evitar porque si no puedes desplegar cosas que no es lo último, pues utilizando una acción, como siempre.
Aquà vamos a añadir antes de todo, antes del checkout, antes de todo, vamos a añadir una acción.
Le vamos a poner cancel, previous, redundant, builds.
Y lo que vamos a hacer aquà es que va a usar una acción que vamos a buscar en el Marketplace.
Es que en el Marketplace tiene de todo.
Cancel workflow.
Y creo que este no es.
Es este.
Yo me suelo fijar en el tema de las estrellas.
Si tiene 16 estrellas o tiene 487.
Y ya te digo, esta es la que yo he utilizado un montón de veces y a mà me ha funcionado correctamente.
Asà que vamos a utilizar esta.
Vamos a ponerla por aquÃ.
Y aquà le puedes decir, le tienes que decir el access token que quieres utilizar.
El access token es el token de acceso de GitHub para que pueda justamente utilizar la API de GitHub y cancelar el workflow.
Entonces, claro, no hay que preocuparse.
Esto que te pone aquÃ, esto está prohibidÃsimo.
No puedes tener un GitHub token que sea un secreto porque ya lo tienes disponible.
En GitHub.token, ¿te acuerdas del objeto contexto que te he dicho que no sé qué?
Pues justamente en este objeto contexto, GitHub context token, este objeto este, tienes el token.
Cuando utilizas todo el contexto de GitHub, cuida que incluya información sensible.
Claro, lo que no puedes hacer es un log de esto porque si no la puedes liar.
Pero mira, GitHub.token.
Esto es súper útil porque de esta forma no tienes que preocuparte nunca de crear tú un token, sino que siempre lo tienes disponible.
Y aquà lo tenemos, ¿vale?
Access token, GitHub.token.
Access lo he escrito bien, ¿no?
Con dos Cs y dos Ss.
SÃ.
Vale.
Pues con esto vamos a evitar.
Avoid redundant build.
Builds y de esta forma ya no podremos hacer dos builds en paralelo, sino que cuando detecte que hacemos dos en paralelo, la que no sea la última se cancelará.
¿Vale?
Con esto ya tendrÃamos nuestra PR ya más que hecha.
Vamos a pull request.
Vamos aquÃ, van version.
Y vamos a ver.
FÃjate que ahora me dice, como administrador, puedes mergear esta PR, pero me sale todo en rojo.
¿Por qué?
Porque me dice que es requerido que tiene que pasar antes de mergear el status de este check.
Esto es súper útil, ¿vale?
Esto es súper necesario.
Cuando quieras hacer continuous integration, parte de la gracia está aquÃ.
Que no tienes que desplegar.
Primero, no deberÃas mergear código si no pasa el continuous integration y no deberÃas desplegar a producción si no pasan los tests, si no linta bien el código y todo esto.
¿Vale?
Vale.
Pues vamos a ver cómo hace esto, que al final lo único que hemos hecho es lo del redundant.
Como no tenÃa redundance, ¿ves?
Pues esto no ha salido, no ha hecho nada.
Voy a forzar que haga unas cuantas builds redundantes.
Para ello lo que voy a hacer es cambiar justamente la versión del package.json.
Y asà vas a ver cómo los cancela.
Vamos a publish new version.
Vamos a pushar esto.
Voy a ver que realmente inicie esa acción.
¿Vale?
Con el bump version.
¿Vale?
Ahora, justo este acaba de empezar.
Está en la cola.
Vamos a hacer otro.
Para encolar uno más.
Para ver si hace bump new version.
Otra vez.
A ver si se van cancelando.
Vamos a refrescar aquÃ.
Vale.
FÃjate que este ya ha hecho este...
Que este workflow ha sido cancelado.
¿Vale?
Y este, dentro de poco, este también deberÃa cancelarse.
¿Por qué?
Porque tiene este arriba y están siendo redundantes.
Y entonces para no competir deberÃamos ver que este también se cancela.
Vamos a ver.
¿Vale?
¿Ves?
Se ha cancelado.
Si entro, vamos a ver que justamente el deploy ha sido cancelado, cancelado, cancelado.
Y todo esto que ha sido cancelado, esta cancelación ha venido porque este, cuando ha ejecutado el paso este del cancel a previous tal, ¿ves?
Aquà lo ha encontrado.
He encontrado el token, he encontrado un workflow, tengo que cancelar uno y lo ha cancelado.
Asà que, bueno, tenlo en cuenta que con esto funciona correctamente.
Una cosa que está bastante bien es el hecho de que si encuentra aquà un workflow y lo cancela, si estás en mitad de un deploy, no te preocupes que no cancela el deploy.
Sino que es justo cuando va a empezar el deploy.
Justo cuando va a empezar cada step.
Solo ahà es cuando lo cancela.
Porque si lo cancelase justo en medio mientras se está ejecutando el step, la podrÃa liar muy parda.
¿Vale?
Vale.
Con esto ya tendrÃamos el tema este del deploy.
Ahora te voy a enseñar una cosa que es lo que yo creo que es lo más poderoso, lo más potente de la GitHub Actions.
¿Vale?
Creo que esto es lo que realmente marca la diferencia respecto no solo a otras soluciones, sino que creo que es lo que habilita hacer pipeline.
Pipelines muy potentes.
Y esto es lo que, por ejemplo, estamos utilizando en mi empresa.
De hecho, para que lo veas, te lo voy a enseñar.
Y para ver que es totalmente cierto.
Es totalmente de código abierto.
Le puedes echar un vistazo.
Eso es el catálogo de componentes de Suite.
Vamos a Actions.
Y aquÃ, si yo entro a esta misma, ¿vale?
Puedes ver que el pipeline lo tengo como separado.
Y fÃjate que tiene como unas flechas.
Es como unas cosas un poco raras, ¿no?
Te dice el testing.
Vale.
Cuando termino el testing voy a release y a deploy.
Pero el deploy depende también de build.
Por lo tanto, espera la build.
Esto es justamente lo más poderoso que tiene la GitHub Actions.
Y lo que, en el ejemplo que vamos a ver hoy, o sea, en lo que tenemos hoy, es una aplicación muy pequeña.
Pero en este caso, cuando la aplicación es más real y más grande, es súper útil.
Porque lo que estás haciendo es esperar.
Justamente estamos esperando pasos anteriores antes de hacer el nuevo.
Y, además, paralelizamos pasos.
En este caso, ves que estamos haciendo el testing, el build y el check de hacer el skip del redunda.
Lo estamos haciendo a la vez.
Y luego, es que hacemos la release solo cuando termine el testing.
Pero el deploy lo hacemos cuando termina también la build, ¿vale?
O sea, bueno, lo vamos a ver para que veas cómo se hace.
No es súper...
A ver, es sencillo, pero puede ser un poco lÃo.
Pero, bueno, no te preocupes que lo vamos a hacer paso a paso.
Y a ver si sale bien.
Lo que hay que hacer...
Primero, vamos a ver la diferencia con este, con el nuestro, ¿no?
El nuestro ahora es un paso que es deploy.
Ya te digo que, a lo mejor, el tiempo que conseguimos es peor incluso.
Porque esto no es un caso real.
Pero, bueno, te quiero acercar un caso real que te pueda ayudar a hacer un Continuous Integration mucho más maduro y bien trabajado.
Y muy poca gente lo hace y lo sabe hacer.
Asà que creo que es bastante interesante el contenido.
Ahora solo tenemos un trabajo que es deploy.
Y entonces tenemos deploy y lo hacemos todo.
Uno detrás de otro y tal.
Puede tener sentido, pero normalmente en la vida real no es asÃ.
No funciona asÃ.
Vamos a empezar a dividir en diferentes trabajos.
Por un lado, podemos tener el de evitar la redundancia.
¿Vale?
Vamos a decir que esto va en 18.04.
Y cada trabajo vas a ver que además tiene que tener su runs on.
Le tienes que decir en qué sistema operativo tiene que trabajar.
Porque es que son máquinas separadas.
Y es parte de la magia decir...
Bueno, es que lo vas a ver y es que vas a flipar.
¿Cuáles son los pasos que tiene que hacer este de la redundancia?
¿Vale?
Los pasos los tenemos ya aquÃ, justamente.
Este steps.
Este de aquÃ.
¿Vale?
Vamos a formatear esto bien.
Y lo tenemos aquÃ.
Asà que en el deploy, esto ya lo podemos quitar.
Esto por un lado.
¿Vale?
¿Esto qué le ha pasado?
Que ahora dice...
Ah, que es que he quitado los steps.
¿Vale?
El de redundancy, este ya lo hemos quitado.
¿Cuál necesitamos ahora?
Ahora tenemos que tener el del linter.
El del linter.
Que este va a trabajar también 18.04.
¿Cuáles son los pasos que tiene el linter?
¿Vale?
Vamos a buscar por aquÃ.
Esto es un problema porque veremos que repetimos código.
Pero claro, es que es necesario ahora mismo.
¿Vale?
Luego os explicaré cómo se puede componer todo este tipo de cosas.
Que ya te puedes imaginar que se puede.
Porque fÃjate que este uses.
Tienes aquà un actions.
O sea que se pueden componer.
Vamos con el linter.
El linter necesita esta parte de aquÃ.
En este caso, nos lo vamos a copiar y pegar.
Y lo dejamos asÃ.
¿Qué es lo que necesita el paso del linter?
Tenemos que hacer un checkout porque necesitamos el código.
Tenemos que hacer un setup node porque tenemos que hacer luego un install.
Instalamos las dependencias con npmci.
Y hacemos el linter.
Ya está.
¿Qué más tenemos que hacer?
Aparte del linter, tenemos que hacer una build.
¿Vale?
Pues vamos a hacer la build.
¿Cómo os hacemos la build?
Vamos a quitar este que era el del linter que ya hemos copiado.
Y necesitamos este de build.
Y aquà en la build es una de las cosas más interesantes de los pasos que vamos a hacer.
¿Por qué?
Porque la build, cuando hacemos la build, ¿qué es lo que hace la build?
Pues empaqueta nuestra aplicación.
Pero ¿cuál es el problema?
Por ahora lo voy a dejar.
¿Cuál es el problema de los tests?
Pues que los tests necesitan nuestra aplicación empaquetada para poder ejecutarse.
Entonces, ¿cómo podemos compartir información entre este job?
Bueno, este job, el de build, y el de los tests.
Pues ahora lo veremos.
¿Vale?
Por ahora vamos a hacer el de test.
Me voy a eliminar este de build por aquÃ.
Y voy a añadir esto de test.
Lo vamos a añadir por aquà con el runson y todo esto.
¿Vale?
Como digo, el de los tests depende justamente de la build.
Pero deberÃa hacer aquà otra vez la build.
No tiene sentido.
¿Por qué?
Porque ya la hemos hecho aquÃ.
¿Qué es lo que podemos hacer para esto?
Pues lo que podemos hacer es guardar un artefacto.
Que básicamente guardar un artefacto lo que quiere decir es que le decimos,
oye, esta carpeta de aquà me la guardas en un zip que luego igual lo utilizo en otro sitio.
¿Vale?
Entonces, lo que hacemos en esta build, una vez que tenemos aquÃ,
el MPN run build y ya ha empaquetado nuestra aplicación correctamente,
lo que vamos a hacer aquà es tener un paso más,
que es utilizar una de actions, que es upload artifact, la versión 2.
Y le decimos, esta acción la quiero utilizar con la opción,
con un nombre que es dist y el path donde está el dist es dist.
¿Cómo sé que es dist?
Bueno, porque cuando yo hago, fÃjate, voy a eliminar el dist aquÃ.
Cuando yo hago un MPN run build, esto lo que hace es generarme una carpeta que se llama dist.
Y aquà es donde está empaquetada mi aplicación.
Entonces, lo que le estoy diciendo en esta acción es,
cuando hago el MPN run build con esta acción,
o sea, una vez, en esta acción voy a utilizar el upload artifact,
¿artifact?
SÃ, o upload artifact.
Con la opción name, el nombre puede ser el que tú quieras,
lo que pasa es que luego lo vamos a necesitar para indicarle de dónde lo queremos descargar,
y el path es la carpeta donde está la información que queremos empaquetar.
En este caso, dist.
Con esto ya estarÃamos subiendo a la nube lo que hemos construido,
la aplicación que hemos empaquetado.
Ahora que tenemos la aplicación empaquetada en algún sitio,
¿qué es lo que tenemos que hacer?
Pues lo que deberÃamos hacer es, en el test,
antes de ejecutar los test,
es posible que los test necesiten la aplicación empaquetada ya.
Por lo tanto, lo que podemos hacer es descargarla.
¿Pero qué pasa con esto?
Que para descargarla tenemos que utilizar exactamente lo mismo que aquÃ,
pero en lugar de decir upload, lo que vamos a decir es download.
Antes de ejecutar los test, vamos a ponerlo aquÃ,
vamos a hacer un download con el nombre dist
y lo vamos a guardar en la carpeta dist,
porque si no te lo dejarÃa en la raÃz,
si tú le quitas esto,
te dejarÃa el contenido que tenÃa el artefacto,
te lo dejarÃa en la raÃz.
Que esto es súper interesante,
esto lo sé porque te peleas con los ls
y miras ahà cómo te lo ha dejado y todo esto,
pero bueno, en este caso asà funcionarÃa correctamente.
Con esto ya podrÃamos ejecutar el test y tal.
¿Pero qué pasa con esto?
Antes de continuar,
que este trabajo test, tal y como está,
se va a ejecutar en paralelo con el de build
y nosotros no queremos eso.
Queremos que el de test solo se ejecute
una vez que haya pasado tanto la build como el linter.
Una vez que sepamos que el linter está bien
y que la build se ha hecho correctamente,
entonces ejecutamos el test.
Para ello tenemos que utilizar aquà needs,
que es un array que le decimos
este trabajo necesita el de lint y el de build.
Una vez que tenemos el de lint y el de build,
entonces ejecuta este job.
Ya tenemos el de test normal,
vamos a pasar con el de end to end.
Asà que vamos a poner end to end test.
Vamos a poner runs.
Vale, esto lo elimino de aquÃ
y vamos a copiar todo esto.
¿Qué le pasa al end to end test?
Le pasa exactamente lo mismo.
Los tests end to end,
cuando hace el npm start test,
no funciona si no tiene la aplicación empaquetada.
Pues nada, vamos a descargar el artefacto
y esto, una vez que se hace el npm install,
vamos a hacerlo aquÃ,
justo antes del end to end test.
¿Vale?
Ya tendrÃamos los end to end.
Vamos a quitar esto.
Install dependencies, este lo dejamos.
Y ahora nos faltarÃa el tema del deploy.
Más, perdón,
que el end to end test también depende de algo, ¿no?
No lo podemos dejar asÃ.
¿Qué pasa?
Que el end to end test y los tests unitarios
se pueden hacer en paralelo.
Lo único importante es que necesita
tanto el linter como la build,
pero no necesita el test.
O sea, que se puede hacer
tanto el test unitario como los de end to end
se pueden hacer en paralelo.
Asà que dejamos las mismas dependencias
que tenÃan los tests.
O sea, los tests de antes,
o sea, los dejamos para los end to end.
Y ahora tenemos por fin el deploy,
que seguramente es el más interesante de todos.
¿Qué es lo que necesita el deploy para funcionar?
Necesita que haya pasado los tests
y también los end to end test.
En este caso voy a poner el end to end
más fácil porque no sé si el guión,
no sé si el guión no le gusta.
Vale, el deploy necesita los tests y los end to end.
Y lo que va a hacer es ejecutar todo esto.
No necesita instalar las dependencias.
La verdad es que no necesita instalar...
Yo creo que no necesita tampoco hacer actualización de Node.
Yo creo que esto no lo necesita.
Si no, bueno, si falla, pues ya lo veremos.
Porque creo que el deploy to Heroku,
esto ya hace el npm install de forma interna,
que es una de las cosas que justamente no me gusta.
Pero bueno, lo importante de esto es que necesita los tests,
los end to end y tal.
Esto lo veremos cuando emergimos a master
porque esto hace un skip en...
Justamente hace un skip en la pull request.
Pero bueno, con esto lo que hemos logrado,
aunque hemos tenido que repetir mucho código y todo esto,
pero con esto lo que hemos logrado
es justamente paralelizarlo todo.
Hemos creado un pipeline que es mucho más complejo,
pero que es realmente mucho más realista
de cómo funciona el mundo real,
el trabajo real cuando se utiliza el GitHub Actions.
Asà que vamos a hacer un Parallelize CI
y vamos a ver si funciona.
A ver si no la he liado.
Nos vamos a Actions.
Vale, esto...
Uy, esto casillo.
Aquà ha fallado algo.
Vale, it's not valid.
Dove deploy depends on un nob test.
Vale, la he liado.
Pero fÃjate lo rápido, ¿eh?
Súper, súper rápido.
Acabo de pushear y ya se está quejando.
Bueno, he puesto que depende de un test.
¿Ves?
He puesto test y aquà he puesto tests.
Pero una de las cosas que me gusta mucho de GitHub Actions
es que realmente te dice,
oye, esto no está bien y tal.
Travis suele ser un poco más problemático.
Grown Job Tests.
Vale, venga, vamos a ello.
A ver ahora.
Vamos a Actions.
Ahora deberÃa aparecer aquà en un momentito.
Aquà lo tenemos.
Y fÃjate qué bonito, qué bonito ha quedado ahora, ¿no?
Ahora tenemos aquà en paralelo estos tres.
Mientras hace una void redundancy por un lado, ¿no?
Para ver si hay alguno que tiene que cancelar a un workflow.
Y como es anterior, no necesita depender de nada aquÃ,
ni paralelizar, o sea, ni parar este, ¿no?
Entonces, estos tres segundos son tres segundos que hemos ganado,
que sé que parece poco, pero tres segundos.
Piensa en miles y miles de ejecuciones de tu código.
Tres segundos son la vida.
Entonces, estos tres segundos lo que ha hecho de forma paralela
es cancelar builds anteriores.
El link y la build se han hecho en paralelo.
De hecho, lo podemos mirar.
Aquà el link, lo que ha hecho es solo el link.
Es verdad que ha tardado 15 segundos por instalar las dependencias,
que esto también se puede cachear de otra forma y tal.
De hecho, se le podrÃa hacer un paso para cachear las dependencias.
Una vez que ha terminado el link y el build,
lo que ha hecho es hacer los tests.
Y justamente la dependencia de los tests,
ahora dice, vale, pues cuando termina el link y build,
hago los tests y los send to end, y los hago en paralelo.
O sea, no hago primero los tests unitarios y luego los send to end,
sino que los hago en paralelo.
De forma que los segundos, aunque sean...
Esto es un ejemplo muy pequeñito,
pero en el mundo real, los tests unitarios,
a lo mejor, te pueden tardar tres o cuatro minutos.
Esto puede marcar la diferencia totalmente.
Puedes pasar de hacer continuous integration en 20 minutos
a hacer continuous integration que tardan siete minutos.
Donde son siete minutos porque ha sido el que más tarda,
el que más tiempo ha tardado,
que a lo mejor normalmente son los tests end to end,
pues a lo mejor tardan siete minutos.
Pero es que todo lo demás lo has hecho en paralelo.
Entonces, fÃjate que ahora, cuando termine este,
deberÃamos ver cómo pasa el deploy.
Como digo, es un ejemplo muy sencillo,
porque en este caso no vamos a ver ganancias de tiempo,
y seguramente incluso puede ser que veamos un impacto negativo,
porque la instalación tiene un gran peso,
aunque son 15 segundos,
que podrÃamos mirar de intentar cachearla.
Una vez que termine los send to end,
ves, el deploy todavÃa no ha empezado,
porque dice, no, no, es que el deploy,
ahora sÃ, porque el deploy depende de los dos tests.
Entonces, hasta que los dos tests no pasen,
no se desplega.
Asà de claro.
Y entonces, ahora que sà ha terminado,
ahora sà que está desplegando.
Pero el despliegue, bueno, se lo salta porque hace un skip.
Por eso aquà nos aparece como que ha tardado tres segundos.
No es que haya tardado tres segundos,
es que se lo ha saltado.
Es verdad que, ¡ah!
Una cosa muy bonita de esto.
Una cosa muy bonita de lo que acabamos de hacer, ¿vale?
Que esto es, mmm, palamerlo.
El tema es que en la pull request, ahora,
fÃjate lo bonito que quedan los checks.
Lo que hemos hecho, además de mejorar el tiempo,
nos ayuda a determinar mejor
qué paso del continuous integration ha fallado.
Porque aquÃ, en los checks, fÃjate aquÃ,
que me ha dividido todo.
Este, que además ha tardado tres segundos.
Tú puedes ir a la pull request
y ver cuál es el paso que está haciendo.
El linter, el build, el test, el end to end.
Y aquà los puedes ver todos y cada uno de ellos.
Para que lo veas más claro,
vamos a volver a hacerlo
y vamos a ponerlo en esa vista
para que veamos cómo,
the version,
para que veas cómo se va actualizando.
Esto es genial porque lo que te hace en la pull request
es darte de un vistazo,
si te fallase solo uno de los jobs,
te dirÃa, mira, este job es el que ha fallado.
¿Ves? Ahora mismo están ejecutando los tres en paralelo.
El de avoid, el de linked y el de build.
Entonces, cuando vaya, cuando termine uno,
¿ves? Este se pone en verde.
Entonces, se irán desbloqueando otros.
¿Qué falla uno?
Pues te aparece aquÃ
y además le podrÃas dar a details directamente
para ver exactamente por qué ha fallado ese.
Esto lo que hace es mejorar muchÃsimo la productividad.
No es lo mismo tenerlo todo en un solo paso
que te cuesta mucho decir,
ah, a ver qué ha fallado.
¿Sabes? A ver qué problema hay.
A verlo de esta forma mucho más granular.
De forma que cuando veas aquÃ,
uno, ver cuál es el paso en el que lo estás haciendo
y luego ver realmente cuál es el que ha fallado.
¿Ves? Ahora me dice, puedes ver completamente por dónde va.
Ahora doy cuenta que este es el test, el end to end y todo esto.
Puedes ir viendo cómo se va mejorando.
O sea, cómo va procesándose todo esto.
Y si falla uno, pues lo verÃamos también.
Vamos a ver ahora de emergear esta, una vez que termine,
que debe terminar en algún momento,
para ver cómo lo vemos
y cómo se emergea
y si le hace el despliegue,
si el despliegue funciona correctamente y todo esto.
¿Vale?
A ver, que voy leyendo mientras esto termina.
Si quieres ahorrar tiempo en aplicaciones grandes,
¿no podrÃas hacer varios end to end
para distintas partes del sitio
y que corran en paralelo?
Claro, por supuesto, franco.
De hecho, en mi empresa lo que hacemos,
esto se hace de forma automática incluso.
Cypress tiene un servicio que es de pago
y en mi empresa lo hacemos
y para nosotros los test end to end
tardan un minuto o algo asÃ.
Cypress tiene este servicio de paralelización.
¿Vale?
De forma gratis puedes ejecutar 500,
pero bueno, si eres una empresa
ya te puedes pagar y tienes 10.000 test
y lo que haces es paralelizar de forma automática
y tú le dices, vale, pues lo paralizo en cuatro procesos
y los procesos ellos mismos se comunican
de forma que lo que hacen es paralelizarlo por ti.
Tú no tienes que decirle, prueba esta parte,
prueba esta parte, tú no le dices eso,
sino que automáticamente lo hace por ti,
lo cual es muchÃsimo mejor.
Mucho, mucho, mucho, mucho mejor.
¿Vale?
También SetupNode provee de un parámetro width
que lo automatiza.
¿Que automatiza el qué?
No sé, ¿que automatiza el qué?
Ya no me he enterado.
CircleCI Jenkins, ¿cómo elegir la mejor opción?
¿Por cuál te vas?
Yo me quedo con Github Actions.
Jenkins no me gusta nada.
CircleCI estaba bien, pero me gustaba más Travis.
Si yo tuviera que elegir uno, elegirÃa Github Actions.
El único problema que tiene Github Actions es el tema de que,
obviamente, necesitas utilizar Github.
Si utilizas Github, yo creo que no hay ningún tipo de duda de
utilizar, de que deberÃas utilizar ese.
O sea, Github Actions.
Es que es demasiado, está muy bien integrado con Github.
Es brutal, es brutal.
SÃ, el tema de la caché, que decÃas lo de Setup Actions.
SÃ y no.
A ver, el problema que tiene el SetupNode, lo podemos probar,
lo podemos probar.
El problema es que no te lo caché exactamente muy bien.
Ahora cuando, mira, ya está.
Voy a mergearlo y lo probamos.
Pero cachear NPM es un rollazo.
Vamos a irnos a master.
Me voy a traer todos los cambios.
SÃ, se supone que aquÃ, en el SetupNode,
aquà tú tienes uno que pone caché y le tienes que decir NPM.
El problema es que no funciona muy bien cuando es en paralelo.
¿Sabes?
O sea, no funciona muy bien.
Y, de hecho, hay una acción que es de Github que se llama Caché.
Actions Caché.
Se llama asÃ.
Y tampoco funciona del todo bien.
Mira, ¿ves?
Es que yo he estado mirando ya aquÃ.
De hecho, mira, aquà hay alguien que ha creado una acción
que a lo mejor funciona mejor que la de...
Es que este es el problema.
Que es que hay que hacer todo esto.
Para cachear hay que hacer todo esto.
Y esto es un rollo.
Entonces, está bien que tenga su propia acción.
Pero el tema del Node Setup, ya te digo que lo que cachea
no es exactamente las dependencias y ya está.
Es un poco raro lo que hace.
Porque para cachearlo, ¿ves?
Hay que hacer el action Caché.
Para cachear bien hay que hacer esto.
Pero esto es un rollo hacerlo.
Entonces, me imagino que este lo hará este Caché en vista del Caché.
No sé si podemos ver cuándo es la última vez que se ha ejecutado esto.
Bueno, hace tres dÃas.
Bueno, igual.
Ah, lo miramos.
Ya os digo que el de NPM, el Setup Node ese, el de la Caché,
no es exactamente lo que estamos buscando.
Vamos a mirarlo.
Caché.
The action will first check the local cache for a Sember match.
Claro, yo creo que esto es para la Caché.
Mira.
Ah, mira.
Aquà esto sà que...
Caching Package Dependencies.
Vamos a ver.
The action has a build cache input is optional.
Caching is turning up with default.
Bueno, igual con el Package Lock no funciona bien.
Vamos a probarlo.
Dependencies.
Vamos a probar.
Total, he puesto aquà el Caché en EPE.
Vamos a poner este.
Igual es algo nuevo de la versión 2 porque yo he utilizado la versión 1.
Support Caching for MonoreposantReposit.
Bueno, puede ser.
Caché, caché, caché.
A ver si han puesto...
Caché, caché, caché, caché.
Caché, caché.
PNP Dependencies.
Pues parece sà que...
Mira, me parece a mà que la han puesto hace relativamente hace poco.
Igual, joder, serÃa genial, ¿eh?
O sea, ya serÃa la bomba.
SerÃa la bomba.
A ver, vamos a buscar todos estos.
Pa, pa, pa, pa, pa.
Caché.
En PNP.
Porque ya os digo que esto antes no funcionaba muy bien.
Lo que cacheaba...
Cacheaba fatal.
Vale, esto está dos veces.
Y no funcionaba, básicamente.
Ojalá que sÃ.
Vamos a verlo.
Add caché to setup note.
Pero sÃ, parece que es algo bastante nuevo, ¿no?
Porque esto es del 30 de junio.
Puede ser que...
Caching the action is a build...
Yo creo que sà que es nuevo.
The cache input...
Pues nada, fantástico.
Vamos a probarlo y a ver qué tal.
A ver si mejoramos un poquito el tiempo de la action.
A ver, voy cerrando todo esto.
Vale.
Nuestra aplicación se deploya correctamente.
Vale.
Aquà hemos añadido la caché.
Aquà tendrÃamos...
Bueno, aquà se ha cancelado la anterior del pipeline.
Estaba tardando sobre los 3 minutos, más o menos.
3 minutos 10.
Vamos a ver ahora.
Hombre.
Ojo, ¿eh?
11 segundos.
11 segundos.
No sé si...
Setup note.
Pero aquà no ha encontrado la caché.
O sea, caché is not found.
Se supone que en la siguiente, en la de test, deberÃa haber encontrado la caché.
A ver ahora si la encuentra la caché.
Aquà sà que ha encontrado la caché.
Bueno, nos ha ahorrado ahà 10 segundos.
Otra cosa serÃa hacer un solo paso que fuese para hacer el NPM install.
Pues sÃ, 10 segundos.
Parece que ahà sà que funciona bastante bien, ¿eh?
Porque aquÃ, claro, los primeros que hacen paralelo no tiene caché ninguno de los dos.
Por eso, es que da igual, porque podrÃa, al hacerlo en paralelo, cualquiera de los dos, una cosa que se podrÃa hacer es hacer primero el NPM install, cachearlo y luego hacer el link y el build.
Eso podrÃamos hacerlo.
O sea, podrÃamos hacer aquÃ.
Elaboy Redum sÃ.
PodrÃamos hacer aquÃ.
Install.
HarÃamos el install.
Pa, pa, pa.
Esto harÃamos esta parte de aquÃ, con steps.
Esta parte de aquÃ.
Esto, tenemos que poner que esto se ejecuta en Ubuntu.
¿Vale?
Checkout, caché, NPM.
Y ahora aquà le tenemos que decir que depende, a ver, no sé si esto nos va a dar mucho.
Depends on install.
Needs, perdón, no depends, es needs.
Needs install.
¿Vale?
Y le decimos que la build también necesita install.
Yo creo que esto no vale la pena, porque el tiempo que se gana es muy poco.
Y total, como se están haciendo los dos primeros en paralelo, pues ya está bien.
Pero esto lo que se le llama es calentar la caché.
Lo que quiere decir esto es calentar la caché.
¿Sabes?
Es hacer un paso solo para calentar la caché.
¿Está bien este paso?
La verdad es que la han puesto hace bastante poquito, porque ya te digo que la última vez que yo toqué el GitHub Actions en mi empresa,
esto no estaba y hacerlo era un percal y no funcionaba muy bien.
O sea, que genial.
Con la V1 tenÃas que hacerlo con Action.
¿Lo metieron en la versión 2?
SÃ, pero lo metieron en la versión 2 y es nuevo.
O sea, lo metieron después, porque en la versión 2 sà que la he estado utilizando y todavÃa no estaba.
Hostia, pues no sé si es 3Droid, no sé.
No sé, no sabÃa que no habÃa subido el de esto.
Entonces, diferente al Action caché de configurarlo en Node Setup.
Son dos cosas diferentes, ¿vale?
Porque tú tienes una acción para cachear y ahà puedes cachear lo que te dé la gana.
Es que puedes cachear, lo que pasa es que es como para cachear dependencias.
Claro, ¿qué pasa?
Que nosotros estamos pensando mucho en Node y en NPM, pero pensad que podéis utilizar un montón de lenguajes y frameworks diferentes.
Por ejemplo, Python.
Pues podéis utilizar el Action caché a lo mejor.
O Java, pues archivos de compilación y un montón de cosas asÃ, ¿vale?
¿Me puedes compartir tu playlist de Spotify o dónde puedo encontrar tu música?
Pues busca Música para Programar y Midudev, que ahà salgo yo.
Ahà está una de la música, una de mis listas de reproducciones con música.
Vale, GitLab me gusta como plataforma porque tiene manejo de revag, pero GitHub es muy bueno.
Hombre, GitLab está súper chulo y además tiene Continuous Integration también.
Ahora, claro, anteriormente sà que es verdad que tenÃa una...
TenÃa Continuous Integration y aquello era brutal, pero ahora GitHub Action la verdad que está muy, muy, muy bien.
Jenkins es muy poco intuitivo, parece una aplicación de 90.
SÃ, yo no lo recomiendo nada.
No recomiendo nada.
Pensé que era un mico que le parecÃa eso un lÃo.
SÃ, no, es un lÃo.
Es un lÃo.
A ver, ¿esto cuenta como ser DevOps?
Hombre, guay, como ser DevOps no, pero desde luego yo creo que es bastante importante.
A mà me sorprende el poco cariño que la gente tiene sobre estos conocimientos.
O sea, esto es súper, súper, súper mega importante dominarlo, entenderlo, saber hacerlo,
que con la clase de hoy estoy seguro que lo habéis entendido, lo habéis aprendido y tal,
pero que mucha gente lo ignora o no le importa.
No, yo quiero aprender JavaScript y React, que vale, que está muy bien.
Este conocimiento es vital para ser ingeniero de software.
O sea, súper vital, súper, súper importante.
Entonces, ser DevOps yo creo que te puede montar toda la infraestructura.
Esto es parte de algo que harÃa un DevOps, pero un DevOps llevarÃa mucho más, mucho, mucho, mucho más.
¿Cómo que última clase de full stack? Pensé que lo de full stack era interminable.
O eso, o termina con uno.
Hombre, petróleo se ha hecho hoy.
Muchas gracias por vuestro apoyo.
Gracias por toda la ayuda, por cada like, por cada vez que le dais a compartir, por todo.
Me ayudáis un montón, ¿vale?
No es necesario que os suscribáis, que os hagáis mecenas.
Si os hacéis, os quiero con locura, muchÃsimo.
O sea, de verdad, muchas gracias.
Pero también me ayudáis compartiendo mi contenido, dándole like, comentándolo, comentándosele al trabajo a la gente.
De verdad, eso me ayuda un montón.
Porque cuanto más seamos, más fácil será que le pueda dedicar más tiempo.
Asà que, muchas gracias.
Espero que lo hayáis pasado muy bien.
Ha sido un viaje.
Pero, oh, qué viaje.
Ha sido tremendo.
Muchas gracias.
¿Seguirán los directos los domingos?
Me lo tengo que pensar.
Creo que en agosto no vamos a hacer más directos en domingo.
Pero lunes, miércoles y viernes sà haremos directos.
Para tu web a juicio.
Para seguir haciendo Meneadev, Codilink, aprendiendo cosas y todo esto.
Asà que os mando un abrazo enorme.
Muchas gracias a todos.
Todos, sois unos cracks, todos y cada uno de ellos.
Todos adoramos la forma de ser de Mido.
El curso de Fullstack ha llegado a su fin.
Con Bond de Dragon Ball.
Qué granda.
Gracias Davor, Leito, Asessing, Gebo Beta, Perro Bomba, Miyazi, Andres, Efedaza, Kemilio, Luichidev, Egló, De Julio, Xitziar.
Muchas gracias, Xitziar, por tu ayuda y por ayudarme un montón con un montón de vÃdeos.
Mido Embajadores.
Eso sois, Mido Embajadores.
Claro que sÃ, Gebo Beta.
Gracias Davorpe, Waiko, Immanuel, De Zagiel, Ambe Kout, SeisGamePlayer.
Además me voy acordando de vuestros nombres y me hace mucha ilusión ver que vais repitiendo.
Carlos Neri, Iloinfi, Daddu06, Leito, Gastón, Joder, Héctor, Vimox, Sabe75, StripteM, Tibor, Alan Sánchez.
Muchas gracias.
Cuidado mucho, Maximineto, Jorge, David Pong.
Muchas gracias a todos mis subs.
A todos, cuidaos mucho, sed buenos y disfrutad lo que queda del fin de.
Un abrazo.
Os llevo en el corazón.
Os llevo en mis No Modules, que lo sepáis.
Hasta luego.
Chao.