Ya expliqué la semana pasada qué era eso de la integración continua, pues bien, ahora toca dar los primeros pasos. Obviamente necesitamos un ordenador que haga de servidor, una máquina virtual, o bien un servidor de verdad si lo que pretendes es utilizar de forma profesional.

Como sistema operativo para esta guía utilizaré Ubuntu 14.04. Tú puedes usar el que quieras pero tal vez te resulte más complicado encontrar algún software, con lo que tendrás que investigar más.

El hardware a usar dependerá de las necesidades que tengas, o para lo que quieras un servidor de integración continua. En mi caso utilizo un pc de gama baja con micro AMD, 8 GB de RAM, sin teclado, ratón, ni monitor (y por tanto sin escritorio gráfico), y con una tarjeta WiFi para conectar a internet. Y esto, para mí, es suficiente. Si lo fueses a usar en un grupo de desarrollo, lo mejor es usar un VPS o un servidor dedicado, ya que mejorará en gran medida el rendimiento.

Ya tenemos el hardware listo y nuestro sistema operativo está instalado, por tanto vamos a iniciar los primeros pasos para crear nuestro servidor de integración continua.

Actualizando el sistema operativo

Vamos a actualizar el sistema operativo con las últimas versiones de los paquetes desde los repositorios. Por tanto ejecutamos los siguientes comandos:

sudo update
sudo upgrade

Respondemos que sí a lo que nos pida y esperamos que termine.

Configurando la red

Para nuestro servidor de integración continua necesitaremos que tenga una IP fija. Si tienes un VPS o un servidor dedicado es posible que esto ya lo tengas solucionado.

Editamos el archivo /etc/network/interfaces para indicarle una IP fija de nuestra red para el servidor, Deberíamos escribir algo como esto:

auto eth0
iface eth0 inet static
    address 192.168.1.40
    gateway 192.168.1.1
    netmask 255.255.255.0

     Guardamos el archivo.

     Ahora configuramos los DNS en /etc/resolv.conf con los siguientes datos o los DNS que tu quieras; en este caso uso los de Google:

nameserver 8.8.8.8
nameserver 8.8.4.4

Y reiniciamos si procede.

Si estás usando una tarjeta de red WiFi tendrás que realizar algunas configuraciones más.

Vamos a comprobar que tenemos una tarjeta de red WiFi, para ello debemos instalar el paquete wireless-tools con el siguiente comando:

sudo apt−get install wireless−tools

Una vez instalado ejecutamos el siguiente comando:

iwconfig

Y nos debe aparecer algo como esto:

eth0 no wireless extensions.
lo no wireless extensions.
wlan0 IEEE 802.11bgn ESSID:"" 
Mode:Managed Frequency:2.437 GHz Access Point:
Bit Rate=39 Mb/s Tx−Power=20 dBm 
Retry long limit:7 RTS thr:off Fragment thr:off
Power Management:off
Link Quality=53/70 Signal level=−57 dBm
Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0
Tx excessive retries:1712 Invalid misc:2599 Missed beacon:0

Si la conexión a nuestro router se realiza a través de WPA, instalaremos la siguiente aplicación:

sudo apt−get install wpasupplicant

Ahora introducimos las credenciales para conectar a nuestro router (nombre de la red y contraseña):

sudo wpa_passphrase NOMBRE_DE_LA_RED CONTRASEÑA >> /etc/wpa_supplicant/wpa.conf

Si el directorio no existe crealo con el siguiente comando y repite el paso anterior:

sudo mkdir /etc/wpa_supplicant

En el archivo /etc/network/interfaces añadimos lo siguiente al final del archivo (recuerda modificar el nombre de la interfaz por el tuyo, al igual que el nombre de la red:

auto ra0
iface ra0 inet static
    address 192.168.1.40
    gateway 192.168.1.1
    netmask 255.255.255.0
    wireless−essid nombre_de_la_red
    wpa−conf /etc/wpa_supplicant/wpa.conf

Guardamos.

Ahora debemos configurar los DNS, para ello sigue los pasos indicados más arriba para modificar el archivo /etc/resolv.conf.

Reinicia la interface de red con:

sudo /etc/init.d/networking restart

Si no tienes conexión ejecuta el siguiente comando (sustituye «ra0» por la interfaz de red correspondiente:

sudo ifup ra0

Hay veces que hay dos interfaz de red al mismo tiempo, puedes desactivar una de ellas con:

sudo ifdown eth0

Apache, PHP, MySQL

Una vez que tenemos configurada la red correctamente es hora de instalar un sistema LAMP (Linux, Apache, MySQL, PHP).

Si no lo has instalado ya cuando instalabas el sistema operativo, ejecuta la siguiente línea:

sudo apt−get install apache php5 mysql−5.1

Y de forma optativa:

sudo apt−get phpmyadmin

Wiki

Para un servidor de integración continua es imprescindible un sistema de documentación, pues las tareas de instalación y configuración son tan densas en algunos casos, que es conveniente tenerlas escritas y a mano siempre. Por lo que pueda pasar.

Para ello vamos a descargar la última versión de mediaWiki, desde la página de descargas: https://www.mediawiki.org/wiki/Download

Para descargarlo por consola haríamos lo siguiente:

cd ~
wget −q −O − http://releases.wikimedia.org/mediawiki/1.23/mediawiki−1.23.2.tar.gz

Como lo que hemos descargado es un archivo comprimido, deberemos descomprimirlo con el siguiente comando:

tar zxf mediawiki−1.23.2.tar.gz

Se nos creará un directorio llamado mediawiki-1.23.2. El contenido de este directorio deberemos copiarlo en /var/www/ic.net.

¿Porqué ic.net? Puedes copiar el contenido a cualquier otra carpeta dentro de /var/www o el directorio que tengas configurado para que se ejecuten los proyectos web. He utilizado ic.net por que es más corto que integracion-continua.net, aunque puedes usar cualquier nombre para el directorio.

Como no tenemos permisos de escritura en /var/www vamos a concederselos:

sudo usermod −aG root nuestro_usuario
sudo usermod −aG www−data nuestro_usuario
sudo usermod −aG nuestro_usuario www−data
sudo chmod −R 775 /var/www

De esta manera a «nuestro_usuario» le añadimos a los grupos «root» y «www-data», además al usuario «www-data» lo añadimos al grupo de «nuestro_usuario». Por último damos permisos de escritura, lectura y ejecución al grupo con el último comando.

Ahora creamos el directorio y copiamos los archivos:

sudo mkdir /var/www/ic.net
sudo cp −r mediawiki−1.23.2 /var/www/ic.net

Una vez copiados los archivos tendremos que crear un virtual host para la wiki. Para ello ejecutamos el siguiente comando para crear el archivo de configuración del virtual host (también puedes usar vi, vim o el editor que prefieras):

sudo nano /etc/apache2/sites-available/001-ic.net.conf

En el archivo escribimos lo siguiente:

 ServerName ic.net

  DocumentRoot /var/www/wiki
  
     Options FollowSymLinks
     AllowOverride None
   

   
     Options Indexes FollowSymLinks MultiViews
     AllowOverride All
     Order allow,deny
     allow from all
   

   ScriptAlias /cgi−bin/ /usr/lib/cgi−bin/
   <Directory "/usr/lib/cgi−bin">
     AllowOverride None
     Options +ExecCGI −MultiViews +SymLinksIfOwnerMatch
     Order allow,deny
     Allow from all
   

  ErrorLog ${APACHE_LOG_DIR}/ic.net.error.log

  # Possible values include: debug, info, notice, warn, error, crit,
   # alert, emerg.
   LogLevel warn

  CustomLog ${APACHE_LOG_DIR}/ic.net.access.log combined

Ahora reiniciamos apache:

sudo /etc/init.d/apache2 reload

El lado del cliente

Es momento de configurar el pc desde el que nos conectaremos a nuestro servidor de integración continua.

Para acceder al servidor por el navegador, solo tendríamos que escribir la IP de éste, pero a corto plazo sería un problema. Así que primero tenemos que vincular un dominio con esa IP. Para ello debemos modificar el archivo host de nuestro sistema operativo.

Si es Windows, el archivo hosts se encuentra en C:/Windows/system32/drivers/etc/hosts.

Si es un derivado de Debian/Ubuntu se encontrará en /etc/hosts.

En ambos casos debemos añadir la IP del servidor junto con el nombre de dominio que queramos. En mi caso usaré ic.net:

192.168.1.40 ic.net

Ahora si escribimos ese dominio en la barra de direcciones del navegador podremos acceder a la Wiki para poder configurarla.

Te recuerdo que el archivo donde se guardan las credenciales de conexión para la base de datos de la Wiki está en el archivo LocalSettings.php.

El Checklist

¿Recuerdas los videos del artículo anterior (Integración continua: Introducción)? Pues bien, en ellos se explican diferentes herramientas para usar en un servidor de integración continua. Como ya tenemos una Wiki instalada, la utilizaremos para crear una lista de las aplicaciones que vamos a instalar. ¿Qué sistema de control de versiones utilizarás?¿Vas a usar métricas?¿Qué CMS utilizarás?¿Habrá proyectos personalizados, es decir, sin ningún CMS?¿Qué entornos vas a crear?¿Cómo harás los backups?¿Qué aplicación utilizarás para el control de errores?, etc.

Todas esas preguntas tendrás que responderlas tú y crear tu propio checklist, donde a medida que vayas completando tareas podrás ir tachándolas de la lista.

Os dejo mi Checklist para que veáis la cantidad de software que instalaremos en esta guía, y las decisiones y quebraderos de cabeza por los que pasé para crear mi servidor de integración continua:

Checklist integración continua

  • IDE
    • Usaremos NetBeans como IDE por defecto.
    • A considerar Cross referencing, control de versiones, search and replace potente (+ integraciones con Check Style, Unit Tests, etc.)
    • Todo lo relacionado con la instalación y configuración se añadirá a la wiki.
  • Coding Standards
    • Usaremos por defecto el standard para PEAR.
    • Para desarrollos sobre cms o frameworks usaremos el estandar correspondiente (WordPress, Drupal y Symfony 2 de momento).
    • phpcs (PHP Code Sniffer) Analiza el código fuente y genera resultados sobre las violaciones del estandar.
    • Documentarlo en la wiki.
    • Integrarlo como un precommit hook en el control de versiones.
    • Integrarlo con el servidor de integración continua.
  • Inline documentation
    • Usaremos por defecto Doxygen para crear la documentación de los proyectos.
    • Integrarlo con el servidor de integración continua.
    • La documentación no estará en el control de versiones.
  • Control version system
    • Usaremos GIT como sistema de control de versiones.
    • Instalar herramienta web de visualización para GIT.
    • Aplicar política de branching.
    • Utilizar los hooks para realizar acciones. (Vincular commits con tareas en un Bug tracker, php -l, comprobar los errores de coding standard, etc.)
    • Uso de «externals».
  • Issue tracker
    • JIRA, Redmine, Mantis, Trac, Bugzilla, etc. Aun por elegir. De momento Bugzilla.
    • Buscar soluciones que se integren fácilmente con otros elementos del sistema (Tracker + GIT, Tracker + IDE, etc.)
    • Buscar plugins que faciliten el Code Review siempre que sea posible.
  • Wiki
    • Usaremos como base para el wiki el cms MediaWiki.
  • Methodology
  • PHP frameworks
    • Usaremos por defecto Symfony2.
  • Librerías y componentes
    • ORM (Doctrine, Propel), templates (Smarty, Twig)
    • Recomendaciones: PEAR, PHP Extensions, Github
  • Seguridad
    • Controlar SQL Injection y XSS
    • «Essential PHP Security» (Chris Shiflett)
    • «Guide to PHP Security» (Ilia Alshanetsky)
  • Debugging and profiling
    • Xdebug http://www.xdebug.org
    • Zend Debugger
    • Xdebug + Visualizador: (KCacheGrind, Webgrind, Xdebugtoolkit)
  • Unit Test
    • Una tarea no está acabada sino tiene los unit tests escritos, en verde y con una cobertura de más del 80%.
    • phpUnit + (Db: commit/rollback | fixtures | DbUnit)
    • Integrar los unit tests con el servidor de integración continua.
    • La ejecución a de durar del orden de segundos.
  • Automated tests
    • Selenium RC + Selenium Grid (http://selenium.org/projects/)
    • Dentro del Control de versiones
    • Utilizar el package «Selenium» que hay dentro de phpUnit
    • Virtualización (VMWare sería lo mejor, nosotros usaremos VirtualBox)
    • Integrar los tests funcionales con el servidor de integración continua (que los ejecute por la noche)
    • Empezad por las funcionalidades críticas de vuestro negocio.
  • Integración continua
    • Jenkins
    • Cruise Control + phpUnderControl
    • Xinc
    • Respetar el tiempo de los jobs (unit test = segundos, métricas = minutos, etc.)
    • Mantener los builds estables lo máximo posible (Si el build se rompe, la prioridad es arreglarlo).
  • Metrics
    • phpmd (Mess detection)
    • phpcpd (Copy detection)
    • pdepend (Dependencia entre paquetes)
    • phpcs (Coding Standards)
    • Integrarlo con la herramienta de integración continua y evaluarlo semanalmente para poder tomar acciones al respecto.
  • Performance
    • Usaremos APC + Memcached (Output y Datos)
    • Para Background Prcessing (Colas): German, ActiveMQ, etc. Aun por elegir.
    • Sharding: entornos de alta escritura (redes sociales)
    • Client side: CDN + YSlow and PageSpeed Suggestion.
  • Deployment
    • Puedo elegir que versión y en qué servidor.
    • Automático (100%) – Código, CDN, BBDD, etc.
    • Menos de 15 min. aprox. para aplicaciones grandes.
    • Generar script de deployment.
    • Automatizarlo usando «ant» o «phing»
    • Capistrano (https://github.com/capistrano)
  • Entornos
    • Asegurar que los entornos son lo más parecidos (php.ini, extensiones, apaches, usuarios, versiones, etc.)
    • Desarrollo, test, producción.
    • Desarrollo, test, acceptance, producción.
    • Desarrollo, test, acceptance, producción, debug.
    • Virtualización (VMWare Workstation)
    • Puppet (https://github,com/puppetlabs/puppet).
  • Logging
    • Utilizar E_STRICT siempre
    • No os compliqueis la vida: Syslog
    • Logad en asíncrono con time out cortos.
    • Syslog, Splunk.
  • Search
    • Sphinx
    • Solr: php-solr, Solarium.