Deploy de un proyecto en Symfony 1.4

La forma más fácil de «trasladar» un proyecto desarrollado bajo el framework Symfony 1.4 es a través del comando project:deploy de la herramienta. Este comando nos permite a nosotros implementar el proyecto en otro servidor distinto al que estamos usando para el desarrollo, ya sea para el testing o bien el mismo servidor de producción.

Para la realización en forma correcta del deploy del proyecto son necesarias básicamente 2 herramientas o programas. Como sabrán yo me manejo en un 99% bajo el OS Linux, por lo que esta explicación y los programas a instalar van a estar bajo este OS.
Como les comentaba, van a necesitar 2 programas fundamentales para que funcione el comando: el rsync y el ssh.

El Symfony 1.4 es obligatorio estar instalado en el entorno donde se vaya a realizar el deploy del proyecto, ya que va a intentar acceder la aplicación a funcionalidades de la herramienta en /usr/share/php/symfony

El rsync es el que permite el sincronismo entre servidores de los archivos y directorios del proyecto. Despues veremos más en detalle como configurar el proyecto en Symfony para utilizar el rsync. Dato importante a tener en cuenta es que el programa del rsync van a tener que tenerlo instalado en ambos servidores, en el de desarrollo y en el que van a realizar el deploy

Otro de los programas que van a necesitar también tener instalados en ambos servidores es el ssh. Este programa permite la conexión remota en forma segura entre máquinas dentro de una red. En la instalación por defecto se configura para la conexión a través del puerto 22, pero se puede configurar en cualquier otro puerto que deseen, pero lo que si es necesario es que si modifican el puerto que utiliza por default el ssh para la comunicación, también van a tener que especificarlo en la configuración del deploy en el proyecto del Symfony.

Si se encuentran en ambos servidores linux basados en debian pueden instalar los programas simplemente ejecutando el siguiente comando:

sudo apt-get install ssh rsync

En caso de no tener instalado el comando de sudo para autenticarse como el administrador, pueden ejecutar el siguiente comando que los autentica como tal:

su -

Esto los va autenticar como el administrador (o superusuario) con las variables de entorno del perfil.

Si no tienen los servidores linux basados en debian pueden googlear como compilarlos e instalarlos en su OS.

Ahora que ya tenemos los 2 programas fundamentales para la funcionalidad del deploy procedemos a ver como se configura el proyecto en el Symfony 1.4.

Dentro de la carpeta config del proyecto, donde se encuentran el archivo databases.yml para la configuración de la base de datos para los distintos entornos de desarrollo y el ProjectConfiguration.class.php que configura el proyecto entre otros, se encuentra 2 archivos esenciales para el funcionamiento del deploy que son el properties.ini y el rsync_exclude.txt.

El primero es el que configura la funcionalidad que se encarga del sincronismo entre los servidores. En el properties.ini se encuentra la siguiente estructura:

[production]
  host=jobeet.com
  port=22
  type=rsync
  user=server_username
  dir=/var/www/jobeet.com/web/

[testing]
  host=testing.jobeet.com
  user=server_username
  dir=/var/www/jobeet.com
  name=testing.jobeet.com
  author=author
  orm=Doctrine

Como se puede apreciar en el código anterior, existen 2 entornos configurados: el production y el de testing.

En el primer entorno que es el de production se muestra una configuración mas específica si se lo quiere llamar, en el que se define el puerto de conexión que utiliza el ssh (por defecto el 22) y el tipo de conexión que utiliza para el sincronismo en este caso rsync.

En el segundo entorno que pertenece al de testing no se especifica el puerto de conexión ni el protocolo que se utiliza para el sincronismo ya que por defecto son el puerto 22 para la conexión y a través del protocolo del rsync para llevar a cabo el sincronismo. Estos pueden obviarse en el ejemplo siempre y cuando estén configurados los valores por defecto.

Sabiendo las salvedades especificadas entre los 2 entornos, veamos ahora las siguientes propiedades:

[testing]
  host=testing.jobeet.com
  user=server_username
  dir=/var/www/jobeet.com
  name=testing.jobeet.com
  author=author
  orm=Doctrine

Utilizando como ejemplo el entorno de testing explicaremos cada una de los atriburos que posee la estructura definida anteriormente:

  • host: Es la ip o dns del servidor en donde se va a realizar el deploy del sistema.
  • user: Es el usuario del servidor con el cual va a autenticar.
  • dir: Es el directorio raíz en donde se encontrará el código fuente del sistema.
  • name: Nombre representativo del sistema.
  • author: Es el nombre del autor del script o el del sistema.
  • orm: Es el patrón que se utiliza para la abstracción de la base de datos.

Una vez que ya configuramos en forma precisa los datos de los entornos en el properties.ini, queda definir que directorios/archivos se van a excluir del sincronismo.
Para esto se configura otro archivo llamado rsync_excludes.txt. Este es el encargado de manejar que archivos o directorios de mi sistema no quiero que se sincronicen.
Esto muchas veces es muy práctico ya que existen varios directorios como lo es cache y log que se sobrescriben en forma reiterada para el uso interno del Symfony y provocaría el constante sincronismo de los mismos ya que tendrían en cada momento un contenido distinto al sincronizado anteriormente y esto seria engorroso y muchas veces podría traer aparejado problemas que se pueden evitar.

Para que esto no suceda se configura el archivo rsync_excludes.txt el cual tiene la siguiente estructura:

# Project files
/cache/*
/log/*
/web/*_dev.php
/web/uploads/*

# SCM files
.arch-params
.bzr
_darcs
.git
.hg
.monotone
.svn
CVS

Como se puede ver en este archivo se excluyen los contenidos de los directorios antes mencionados que son cache y log. También se excluye el contenido del directorio upload en el que se vuelcan los temporales de los archivos que se suben al sitio o que interactúan con el mismo y también se excluye el archivo *_dev.php del proyecto.

El *_dev.php se suele no sincronizar ya que supuestamente un deploy se lo realiza en un entorno en el cual va a ser para prueba o para la interacción con un usuario final y darle la posibilidad al mismo que pueda acceder al modulo de auditoria es un poco inestable, pero igualmente en muchos de los casos, si se lo envía a un entorno de testing puede que sea de forma interna en una primera instancia y que no tenga salida a un usuario final por lo que es bastante útil tener el modulo de auditoria por cualquier conflicto que pueda surgir en el testing y poder acceder al error de manera mas rápida pero todo esto esta fuertemente relacionado a la forma de trabajar del que realiza el deploy.

También se puede observar en la sección # SCM files que aparece dentro del listado la instrucción .svn, el cuál excluye la sincronización de los archivos vinculados al programa que maneja el control de versiones mejor conocido como o svn.
Esto es necesario ya que sino se estaría sincronizando contenido que se sobrescribe en forma continua e información que no es de carácter obligatorio para el correcto funcionamiento del sistema.

A continuación les muestro una configuración más especifica y detallada del archivo rsync_excludes.txt como una buena práctica.

# Project files
/cache/*
/log/*
#/web/*_dev.php
/web/uploads/*
/config/databases.yml
/lib/model/doctrine/SfGuard*
/lib/model/doctrine/base/BaseSfGuard*
/lib/form/doctrine/SfGuard*
/lib/form/doctrine/base/BaseSfGuard*
/lib/filter/doctrine/SfGuard*
/lib/filter/doctrine/base/BaseSfGuard*

# SCM files
.arch-params
.bzr
_darcs
.git
.hg
.monotone
.svn
CVS

En la configuración anterior se puede hacer mención a 2 bloques de gran importancia.
El primer bloque a destacar es en donde dice:

#/web/*_dev.php

Como se puede observar, se comenta la sentencia que excluye al archivo que audita el proyecto. Esto se realiza simplemente cuando se quiere un control mayor del aplicativo sin importar en que entorno este. El caso más sencillo es cuando se quiere implementar una versión en un entorno de testing, entonces frente a cualquier error que se produzca en el sistema, se podrá acceder al entorno de desarrollo para poder ver en forma mas clara el error.
Para poder realizar esto tenemos que comentar o bien eliminar la linea del archivo rsync_exclude.txt que hace referencia al archivo que realiza esta funcionalidad que es el *_dev.php del proyecto.

El otro bloque de código muy importante a tener en cuenta y que es lo que puede traer varios dolores de cabeza es el siguiente:

/config/databases.yml
/lib/model/doctrine/SfGuard*
/lib/model/doctrine/base/BaseSfGuard*
/lib/form/doctrine/SfGuard*
/lib/form/doctrine/base/BaseSfGuard*
/lib/filter/doctrine/SfGuard*
/lib/filter/doctrine/base/BaseSfGuard*

Veamos en forma mas detallada cada sentencia:
Lo primero a destacar es la inclusión del archivo databases.yml en el listado. Esto se debe ya que si se incluyera, este se sincronizaría cada vez que queremos actualizar algún cambio en el entorno nuevo y como seguramente, el sistema en el nuevo entorno va a estar apuntando a otra base de datos tendríamos que estar modificando el databases.yml cada vez que sincronice y realizar un clear:cache cada vez, entonces para ahorrarnos ese problema solo basta con agregar el archivo al listado de archivos que se excluirán de la sincronización.

Como segunda cosa a tener muy en cuenta y que va a hacer posible el funcionamiento de su aplicación en otro entorno, siempre y cuando (obviamente) su aplicación utilice el plugin de seguridad sfDoctrineGuardPlugin. En caso de usar este plugin para manejar la seguridad en su aplicación tengan a bien incluir los siguientes archivos:

/lib/model/doctrine/SfGuard*
/lib/model/doctrine/base/BaseSfGuard*
/lib/form/doctrine/SfGuard*
/lib/form/doctrine/base/BaseSfGuard*
/lib/filter/doctrine/SfGuard*
/lib/filter/doctrine/base/BaseSfGuard*

Cada uno de estos pertenecen a las clases del plugin generadas por el schema.yml que se formula a partir de la estructura de la base de datos. Si estas tablas existen en la base de datos (las cuales deberían existir sino no funcionaría el plugin) cuando se ejecute el doctrine:build-schema y luego doctrine:build-model se generarán las clases respectivas a estas tablas, pero no son las que utiliza el plugin, sino que son otras que aparecen en /lib en un directorio se les generará llamado sfDoctrineGuardPlugin. Allí dentro se encuentran las clases que utiliza el plugin, y no las que se encuentran en la raíz de cada aspecto (model, form, filter).
Con esto se quiere dar a entender que cuando se realice un deploy en otro servidor, si estos archivos no están incluidos en el listado de archivos/directorios a excluir, van a tener conflictos a la hora de probar la aplicación, ya que va a tratar de levantar estas clases y no las que realmente debería invocar para su ejecución.
En el entorno de desarrollo puede que no traiga problemas ya que es un ambiente totalmente de desarrollo y existan variables que hagan posible su funcionamiento sin importar cuantas definiciones de la misma clase tengan ni donde, pero en otro entorno, más restringido, puede que no las tenga y surjan los problemas que anteriormente les mencioné.

Si realizan estos pasos que se describieron anteriormente, no deberían tener ningún problema en la ejecución de la aplicación, y no deberían tener problemas con el plugin de seguridad.

Según pruebas realizadas los únicos inconvenientes que podrían llegar a tener (que son los que tuve yo e investigue a más no poder) es con respecto al plugin de seguridad a la hora de hacer un deploy del proyecto, más allá de eso, debería funcionar todo en forma correcta sin tener que tocar absolutamente nada en el nuevo entorno.

Si fueran a tener algún error con el plugin de seguridad y ya realizaron el rsync, lo único que tienen que hacer es eliminar todos las clases SfGuard* de todos los aspectos. Con aspectos me refiero a module, form y filter y los BaseSfGuard* de los 3 aspectos también.
Una vez hecho esto, sumado a la inclusión de las expresiones en el archivo rsync_exclude.txt el sistema debería levantar correctamente.

Algo importante que olvidé mencionar es que cuando se ejecute el comando del project:deploy nombre_proyecto solo les va a realizar una prueba de la transacción, quiere decir que no se va a hacer efectivo el deploy sinó que va a realizar una especie de emulación del rsync, hasta que ustedes se lo indiquen pasándole un parametro más a la linea de comando. Esta prueba es muy útil ya que les permite conocer si existe algún error en el sincronismo puesto que en caso de error se los identificaría y poder arreglar el problema hasta que todo este bien que es en el caso de que no les muestre más nada, ese es el momento en el que ya pueden hacer efectivo el cambio.
Este nuevo parámetro que hace efectivo el cambio se denota –go.

Entonces a modo de ejemplo con la siguiente linea de comando ustedes prueban el deploy para verificar si hay algún error:

symfony project:deploy project_name

Y con la siguiente linea confirman que el deploy lo realize de forma física y no que sea emulada:

symfony project:deploy project_name --go

En caso de tener alguna complicación pueden enviarme un mail consultándome y ver si le podemos encontrar una solución.

2 Respuestas a “Deploy de un proyecto en Symfony 1.4

  1. Muy bueno aporte Nico. Me recontra sirvió. Un detalle quizás zonzo es que al poner symfony project:deploy nombre_entorno solo simula y se debe agregar –go: symfony project:deploy nombre_entorno –go.

    Muy buena la página.

    • Jajajajja, re contra pequeño detalle que me olvide de aclarar, ahi ya lo modifiqué al post y agregue esa parte 😛 menos mal que estas para salvarme jajaja 😀

Replica a phpnico Cancelar la respuesta