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
- Usaremos Scrum como metodología de progamación ágil.
- Para empezar: http://www.scrumalliance.org/pages/scrum_student_resources
- 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.