Implementación de Aplicaciones Heroku en Entornos de Preproducción y Producción con GitLab CI/CD

En un artículo anterior, exploramos cómo automatizar despliegues en Heroku utilizando GitLab CI/CD. Esa configuración desplegaba la aplicación en su entorno de producción cada vez queíamos código a la rama main.

En este artículo, consideraremos una approaches ligeramente más matizada: ¿Qué pasa si tenemos varios entornos? La mayoría de las organizaciones de ingeniería utilizan al menos tres entornos: un entorno de desarrollo local, un entorno de staging y un entorno de producción.

Además, algunos equipos de ingeniería siguen una estrategia de ramas Gitflow, donde tienen una rama dev y una rama main. Esta estrategia ha caído en desuso y ha sido reemplazada por desarrollo basado en tronco, pero no es poco común encontrar organizaciones que aún siguen esta práctica.

Hoy vamos a ver cómo configurar GitLab CI/CD para desplegar nuestra aplicación en nuestro entorno de preproducción cuando hacemos push a la rama dev y desplegar nuestra aplicación en nuestro entorno de producción cuando hacemos push a la rama main.

Getting Started

Antes de comenzar, necesitarán dos cosas: una cuenta de Heroku y una cuenta de GitLab.

Heroku es un excelente lugar para alojar y desplegar sus aplicaciones. Como plataforma como servicio (PaaS), Heroku le permite centrarse en construir cosas geniales abstractando gran parte de la complejidad de la infraestructura. Puede crear una cuenta de Heroku aquí.

GitLab es un excelente lugar para almacenar su código. Más allá de ser solo una herramienta de gestión de código fuente, GitLab también ofrece capacidades nativas de CI/CD para que pueda configurar pipelines y probar y desplegar su código sin necesitar otra herramienta de tercero. Puede crear una cuenta de GitLab aquí.

La aplicación de demostración mostrada en este artículo utiliza tanto GitLab como Heroku. Puede encontrar todo el código en el repositorio de GitLab aquí.

Ejecutar Nuestra Aplicación Localmente

Puedes ejecutar la aplicación localmente clonando el repositorio, instalando las dependencias y ejecutando el comando de inicio. En tu terminal, haz lo siguiente:

$ git clone https://gitlab.com/tylerhawkins1/heroku-gitflow-staging-production-gitlab-cicd-demo.git
$ cd heroku-gitflow-staging-production-gitlab-cicd-demo
$ npm install
$ npm start

Después de iniciar la aplicación, visita este host local en tu navegador, y verás la aplicación ejecutándose localmente:

Aplicación de demostración en Heroku

Desplegando Nuestra Aplicación en Heroku

Ahora que la aplicación se ejecuta localmente, despleguemos en Heroku para que puedas acceder a ella desde cualquier lugar, no solo en tu máquina.

Recuerda que vamos a desplegar tu aplicación tanto en un entorno de staging como en un entorno de producción. Eso significa que tendremos dos aplicaciones de Heroku basadas en el mismo repositorio de GitLab.

Si aún no tienes el Heroku CLI instalado en tu máquina, necesitarás instalarlo antes de seguir.

Después de instalar el Heroku CLI, ejecuta los siguientes comandos desde tu terminal para cambiarte al branches main, crear una nueva aplicación de Heroku de producción, desplegarla a tu entorno de producción y abrirla en tu navegador:

$ git checkout main
$ heroku create heroku-gitlab-ci-cd-production --remote heroku-production
$ git push heroku-production main
$ heroku open --remote heroku-production

Con eso, deberías ver la misma aplicación, pero esta vez ejecutándose en una URL de Heroku en lugar de en localhost. Buen trabajo — has desplegado tu aplicación de Heroku en producción!

Pero, aún no hemos terminado. También necesitamos configurar y desplegar tu aplicación de staging. Para hacer esto, ejecuta el siguiente conjunto similar de comandos que se muestra a continuación:

$ git checkout dev
$ heroku create heroku-gitlab-ci-cd-staging --remote heroku-staging
$ git push heroku-staging main
$ heroku open --remote heroku-staging

Ahora tendrá la misma aplicación desplegada nuevamente, pero esta vez en una URL diferente que servirá como su entorno de preproducción. ¡Ahora tenemos configurados ambos entornos!

Observe las diferencias y similitudes entre los comandos para la aplicación de producción y la aplicación de preproducción:

  1. La aplicación de producción utiliza la rama main, y la aplicación de preproducción utiliza la rama dev.
  2. La aplicación de producción se llama heroku-gitlab-ci-cd-production, y la aplicación de preproducción se llama heroku-gitlab-ci-cd-staging.
  3. El remote de git de la aplicación de producción se llama heroku-production, y el remote de git de la aplicación de preproducción se llama heroku-staging.
  4. Tanto el remote de git de la aplicación de producción como el de la aplicación de preproducción utilizan una rama main, ya que Heroku solo despliega la aplicación cuando se poussan cambios a su rama principal.

Recuerde que esta rama main es diferente de su conjunto de ramas main y dev. La rama main a la que está poussando aquí es la rama main en su remote de git — en este caso, Heroku.

Entonces, cuando estás en tu rama local main y ejecutas git push heroku-production main, estás enviando tu rama main a la rama main de la aplicación de producción de Heroku. Y cuando estás en tu rama local dev y ejecutas git push heroku-staging main, estás enviando tu rama dev a la rama main de la aplicación de staging de Heroku.

Realizar Cambios en Nuestra Aplicación

Ahora que tenemos nuestra aplicación de Heroku funcionando, ¿qué pasa si queremos hacer algunos cambios? Siguiendo una aproximación aproximada de la estrategia de ramas Gitflow, podríamos hacer lo siguiente:

  1. Crear una copia de la rama dev
  2. Hacer cambios en el código
  3. Añadir, comprometer y enviar esos cambios a la rama dev
  4. Desplegar esos cambios en la aplicación de staging de Heroku ejecutando git push heroku-staging main
  5. Crear una copia de la rama main
  6. Fusionar la rama dev en la rama main
  7. Desplegar esos cambios en la aplicación de producción de Heroku ejecutando git push heroku-production main

(Si realmente estuviéramos siguiendo Gitflow, habríamos creado una rama de características para fusionarla en dev, y una rama de lanzamiento para fusionarla en main, pero hemos omitido esos pasos para mantener las cosas simples.)

Ahora, ¿no sería genial si pudieramos automatizar el despliegue en cualquiera de nuestros entornos en lugar de tener que desplegar manualmente todo el tiempo?

Es aquí donde entra en juego GitLab CI/CD.

Integración Continua/Despliegue Continuo

La integración continua (CI) se trata de comprometerse con frecuencia y mantener la compilación en un buen estado en todo momento. típicamente, verificarías que la compilación está en buen estado ejecutando verificaciones en un pipeline de CI. Estas verificaciones pueden incluir correctores, pruebas unitarias y/o pruebas de extremo a extremo.

El despliegue continuo (CD) se trata de desplegar con frecuencia. Si las verificaciones en el pipeline de CI pasan, la compilación se despliega. Si las verificaciones en el pipeline de CI fallan, la compilación no se despliega.

Con GitLab CI/CD, podemos configurar nuestro pipeline de CI para hacer exactamente esto — ejecutar nuestras pruebas y luego desplegar nuestra aplicación en Heroku si todas las pruebas pasan. Lo más importante para nuestra configuración, podemos establecer reglas dentro de nuestro pipeline de CI para especificar dónde debe desplegarse la aplicación.

Configuración de GitLab CI/CD

Podemos crear un pipeline de CI en GitLab de manera programática utilizando un archivo .gitlab-ci.yml. Nuestro archivo se ve así:

YAML

 

image: node:20.10.0

cache:
  paths:
    - node_modules/

before_script:
  - node -v
  - npm install

stages:
  - test
  - deploy

unit-test-job:
  stage: test
  script:
    - npm test

deploy-job:
  stage: deploy
  variables:
    HEROKU_APP_NAME: $HEROKU_APP_NAME_PRODUCTION
  rules:
    - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
      variables:
        HEROKU_APP_NAME: $HEROKU_APP_NAME_PRODUCTION
    - if: $CI_COMMIT_REF_NAME =~ /dev/
      variables:
        HEROKU_APP_NAME: $HEROKU_APP_NAME_STAGING
  script:
    - apt-get update -yq
    - apt-get install -y ruby-dev
    - gem install dpl
    - dpl --provider=heroku --app=$HEROKU_APP_NAME --api-key=$HEROKU_API_KEY

Los pipelines de CI de GitLab consisten en etapas y trabajos. Cada etapa puede contener uno o más trabajos. En nuestro pipeline, tenemos dos etapas: test y deploy. En la etapa test, ejecutamos nuestras pruebas unitarias en el unit-test-job. En la etapa deploy, desplegamos nuestra aplicación en Heroku en el deploy-job.

Solo podemos avanzar a la siguiente etapa si todos los trabajos en la etapa anterior pasan. Eso significa que si las pruebas unitarias fallan, la aplicación no se desplegará, ¡lo cual es algo bueno! No querríamos desplegar nuestra aplicación si está en mal estado.

Notarás que la etapa deploy tiene una sección rules con algunas lógicas condicionales en su lugar. Aquí es donde especificamos a qué entorno debe desplegarse nuestra aplicación. Si estamos en la rama main, entonces desplegamos nuestra aplicación de producción. Si estamos en la rama dev, entonces desplegamos nuestra aplicación de staging.

También notarás que la etapa deploy hace referencia a varias variables llamadas $HEROKU_APP_NAME_PRODUCTION, $HEROKU_APP_NAME_STAGING y $HEROKU_API_KEY. Estas se almacenan como variables CI/CD dentro de GitLab.

Si estás configurando esto en tu propia cuenta de GitLab, primero necesitarás encontrar tu clave API en tu cuenta de Heroku. Dentro de la configuración de tu cuenta de Heroku, deberías ver una sección para tu clave API. Si aún no has generado una clave API, genera una ahora.

Heroku API key

Luego, en tu proyecto de GitLab, haz clic en Configuración > CI/CD > Variables. Expande esa sección y agrega tres nuevas variables:

  1. El valor para $HEROKU_API_KEY será la clave API de tu cuenta de Heroku.
  2. El valor para $HEROKU_APP_NAME_PRODUCTION será el nombre de tu aplicación de producción en Heroku. El nombre de mi aplicación de producción es heroku-gitlab-ci-cd-production, pero dado que los nombres de aplicaciones de Heroku son universalmente únicos, el tuyo será algo diferente.
  3. El valor para $HEROKU_APP_NAME_STAGING será el nombre de su aplicación Heroku de preproducción. El nombre de mi aplicación de preproducción es heroku-gitlab-ci-cd-staging. De nuevo, ya que los nombres de las aplicaciones Heroku son únicos universalmente, el suyo será diferente.
GitLab CI/CD variables

Con eso, su pipeline de CI de GitLab está listo para usar. Vamos a probarlo.

Desplegando Nuestra Aplicación Heroku en el Entorno de Preproducción

Vamos a revisar la rama dev y hacer un cambio en el código de nuestra aplicación. Hice un cambio simple en el texto del encabezado y añadí varias nuevas líneas al texto en la interfaz de usuario. Puedes hacer un cambio similar en tu código.

Ahora, añade, compromete y empuja ese cambio a la rama dev. Esto iniciará el pipeline de CI de GitLab. Puedes ver el pipeline dentro de GitLab y seguir el progreso en tiempo real.

GitLab CI pipeline build for the dev branch

Si todo va bien, deberías ver que tanto la etapa test como la deploy han pasado. Ahora, revisa tu aplicación Heroku alojada en la URL del entorno de preproducción. El pipeline de CI de GitLab se encargó de desplegar la aplicación por ti, así que ahora verás tus cambios en vivo en el entorno de preproducción!

Demo Heroku app with updated copy

Con un entorno de preproducción configurado, ahora tienes un excelente lugar para probar manualmente tu código en un entorno alojado. También es el lugar perfecto para que los probadores de QA o los gerentes de producto verifiquen los cambios antes de que pasen a producción.

Ahora, revisa la URL de tu aplicación de producción. Notarás que aún muestra la vieja interfaz sin los cambios más recientes. Esto se debe a que el pipeline de CI de GitLab solo desplegó los cambios en el entorno de preproducción, no en el entorno de producción.

Hemos verificado que el código se ve bien en nuestro entorno de staging, así que vamos a promoverlo a nuestro entorno de producción.

Desplegando Nuestra Aplicación Heroku en el Entorno de Producción

Vamos a revisar la rama main y luego fusionar la rama dev en tu rama main. Podrías hacerlo a través de una solicitud de extracción o ejecutando git merge dev y luego git push.

Esto iniciará nuevamente el pipeline de GitLab CI, pero esta vez estará preparando para desplegar tu aplicación de producción.

GitLab CI pipeline build for the main branch

También puedes ver todas las ejecuciones del pipeline en la página de Pipelines en GitLab para ver las diversas construcciones para tus ramas dev y main:

All GitLab CI pipeline builds

Una vez que el pipeline finalice, visitar la URL de tu aplicación Heroku de producción. Ahora deberías ver tus cambios también desplegados en producción. ¡Gran trabajo!

Conclusión

A good CI pipeline allows you to ship new features quickly and confidently without manually managing the deployment process. Having multiple environments configured for local development, staging, and production gives you more control over where and when code is released.

Heroku y GitLab CI/CD te permiten automatizar todo esto para hacer que tus procesos DevOps sean una brisa!

Source:
https://dzone.com/articles/deploying-heroku-apps-to-staging-and-production