SymfonyWorld Online 2020
100% online
30+ talks + workshops
Live + Replay watch talks later

Paso 11: Ramificando el código

5.0 version
Maintained

Ramificando el código

Hay muchas maneras de organizar el flujo de trabajo de los cambios en el código de un proyecto. Pero trabajar directamente en la rama maestra de Git y desplegar directamente a la de producción sin realizar pruebas probablemente no sea la mejor.

Hacer pruebas no es sólo hacer pruebas unitarias o pruebas funcionales, sino que también se trata de comprobar el comportamiento de la aplicación con datos de producción. Si tú o el resto de partes interesadas podéis navegar por la aplicación exactamente como cuando sea desplegada a los usuarios finales, esto se convierte en una gran ventaja y te permite desplegarla con confianza. Es especialmente útil cuando personas sin conocimientos técnicos pueden validar nuevas características.

Continuaremos haciendo todo el trabajo en la rama master de Git en los próximos pasos por simplicidad y para evitar repetirnos, pero veamos cómo podría funcionar mejor.

Adoptando un flujo de trabajo en Git

Un posible flujo de trabajo es crear una rama por cada nueva característica o corrección de errores. Es simple y eficiente.

Describiendo tu infraestructura

Puede que aún no te hayas dado cuenta, pero tener la infraestructura almacenada en archivos junto con el código ayuda mucho. Docker y SymfonyCloud utilizan archivos de configuración para describir la infraestructura del proyecto. Cuando una nueva característica necesita un servicio adicional, el código cambia y los cambios en la infraestructura son parte del mismo parche.

Creando ramas

El flujo de trabajo comienza con la creación de una rama de Git:

1
$ git branch -D sessions-in-redis || true
1
$ git checkout -b sessions-in-redis

Este comando crea la rama sessions-in-redis desde la rama master. Se «bifurca» el código y la configuración de la infraestructura.

Almacenando sesiones en Redis

Como habrás adivinado por el nombre de la rama, queremos cambiar el almacenamiento de sesión del sistema de ficheros a un almacén Redis.

Los pasos necesarios para hacerlo realidad son típicos:

  1. Crea una rama de Git;
  2. Actualiza la configuración de Symfony si es necesario;
  3. Escribe y/o actualiza alguna parte del código si es necesario;
  4. Actualiza la configuración de PHP (agrega la extensión Redis PHP);
  5. Actualiza la infraestructura en Docker y SymfonyCloud (agrega el servicio Redis);
  6. Prueba localmente;
  7. Prueba remotamente;
  8. Fusiona la rama con master;
  9. Despliega a producción;
  10. Elimina la rama.

Todos los cambios necesarios del 2 al 5 se pueden generar en un parche:

patch_file
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
--- a/.symfony.cloud.yaml
+++ b/.symfony.cloud.yaml
@@ -15,8 +15,13 @@ runtime:
 build:
     flavor: none

+variables:
+    php-ext:
+        redis: 5.3.1
+
 relationships:
     database: "db:postgresql"
+    redis: "rediscache:redis"

 web:
     locations:
--- a/.symfony/services.yaml
+++ b/.symfony/services.yaml
@@ -2,3 +2,6 @@ db:
     type: postgresql:11
     disk: 1024
     size: S
+
+rediscache:
+    type: redis:5.0
--- a/config/packages/framework.yaml
+++ b/config/packages/framework.yaml
@@ -7,7 +7,7 @@ framework:
     # Enables session support. Note that the session will ONLY be started if you read or write from it.
     # Remove or comment this section to explicitly disable session support.
     session:
-        handler_id: null
+        handler_id: '%env(REDIS_URL)%'
         cookie_secure: auto
         cookie_samesite: lax

--- a/docker-compose.yaml
+++ b/docker-compose.yaml
@@ -8,3 +8,7 @@ services:
             POSTGRES_PASSWORD: main
             POSTGRES_DB: main
         ports: [5432]
+
+    redis:
+        image: redis:5-alpine
+        ports: [6379]

¿No es precioso?

«Reinicia» Docker para iniciar el servicio Redis:

1
2
$ docker-compose stop
$ docker-compose up -d

Te dejaré hacer pruebas localmente navegando por el sitio web. Como no hay cambios visuales y como aún no estamos utilizando las sesiones, todo debería funcionar como antes.

Desplegando una rama

Antes de desplegar en producción, debemos probar la rama en la misma infraestructura que tiene producción. También debemos validar que todo funciona bien para el entorno de Symfony prod (el sitio web local utiliza el entorno de Symfony dev).

Primero, asegúrate de hacer commit a tus cambios en la nueva rama:

1
2
$ git add .
$ git commit -m'Configure redis sessions'

Ahora, vamos a crear un entorno SymfonyCloud basado en la rama de Git:

1
$ symfony env:delete sessions-in-redis --no-interaction
1
$ symfony env:create

Este comando crea un nuevo entorno de la siguiente manera:

  • La rama hereda el código y la infraestructura de la rama actual de Git (sessions-in-redis);
  • Los datos vienen del entorno master (también conocido como producción) tomando una instantánea consistente de todos los datos del servicio, incluidos los archivos (por ejemplo, los archivos cargados por el usuario) y las bases de datos;
  • Se crea un nuevo clúster dedicado para desplegar el código, los datos y la infraestructura.

Como la implementación sigue los mismos pasos que el despliegue en producción, también se ejecutarán las migraciones de bases de datos. Esta es una excelente manera de validar que las migraciones funcionen con los datos de producción.

Los entornos que no son master son muy similares al master anterior, excepto por algunas pequeñas diferencias: por ejemplo, los correos electrónicos no se envían por defecto.

Una vez finalizado el despliegue, abre la nueva rama en un navegador:

1
$ symfony open:remote

Ten en cuenta que todos los comandos de SymfonyCloud funcionan en la rama actual de Git. Este comando abre la URL que ha sido desplegada para la rama sessions-in-redis; la URL será algo similar a https://sessions-in-redis-xxx.eu.s5y.io/.

Prueba el sitio web en este nuevo entorno, deberías ver todos los datos que creaste en el entorno master.

Si se añaden más conferencias en el entorno master, no aparecerán en el entorno sessions-in-redis y viceversa. Los entornos son independientes y aislados.

Si el código se desarrolla en master, siempre puedes hacer rebase a la rama de Git y desplegar la versión actualizada, resolviendo los conflictos tanto para el código como para la infraestructura.

Incluso puedes sincronizar los datos desde la rama master con el entorno sessions-in-redis:

1
$ symfony env:sync

Depurando las implementaciones de producción antes del despliegue

Por defecto, todos los entornos SymfonyCloud utilizan la misma configuración que el entorno master/prod (también conocido como entorno Symfony prod). Esto te permite probar la aplicación en condiciones reales. Te da la sensación de desarrollar y probar directamente en servidores de producción, pero sin los riesgos asociados con ello. Esto me recuerda a los buenos tiempos en los que estábamos realizando la implementación a través de FTP.

En caso que tengas algún problema, es posible que quieras cambiar al entorno Symfony dev:

1
$ symfony env:debug

Cuando hayas terminado, vuelve a los ajustes de producción:

1
$ symfony env:debug --off

Advertencia

Nunca habilites el entorno dev y nunca habilites el Symfony Profiler en la rama master; esto haría tu aplicación realmente lenta y abriría muchas vulnerabilidades serias de seguridad.

Probando las implementaciones de producción antes del despliegue

Tener acceso a la próxima versión del sitio web con datos de producción te abre un abanico de oportunidades: desde pruebas visuales de regresión hasta pruebas de rendimiento. Blackfire es la herramienta perfecta para este trabajo.

Consulta el paso «Rendimiento» para obtener más información sobre cómo puedes utilizar Blackfire para probar tu código antes del despliegue.

Fusionando en producción

Cuando estés satisfecho con los cambios en la rama, vuelve a fusionar el código y la infraestructura con la rama master de Git:

1
2
$ git checkout master
$ git merge sessions-in-redis

Y haz el despliegue:

1
$ symfony deploy

Cuando se despliega, sólo los cambios de código e infraestructura son enviados a SymfonyCloud; los datos no se ven afectados de ninguna manera.

Limpiando

Finalmente, elimina la rama Git y el entorno SymfonyCloud:

1
2
$ git branch -d sessions-in-redis
$ symfony env:delete --env=sessions-in-redis --no-interaction

  • « Previous Paso 10: Construyendo la interfaz de usuario
  • Next » Paso 12: Escuchando eventos

This work, including the code samples, is licensed under a Creative Commons BY-NC-SA 4.0 license.