Programación y sistemas

Integración continua: Automatizando la creación de proyectos WordPress, Drupal, Symfony, etc. (II)

En el post anterior hemos actualizado el script que crea los repositorios, para poder añadirle unas cuantas acciones para automatizar la creación del proyecto (creación de directorios, directorios ignorados, etc.). Ahora vamos a desarrollar la segunda parte, que consistirá en la automatización de la instalación del cms o framework elegido.

Automatizando la instalación de WordPress

En primer lugar vamos a copiar el archivo wp-config-sample.php de la raíz de WordPress a /var/www/dev/utils/wp-config-sample.php. Lo tendremos que modificar para poder trabajar más cómodamente con él.

Sustituye las líneas:

 

[codesyntax lang=»php»]

<?php

/** The name of the database for WordPress */
define('DB_NAME', 'database_name_here');

/** MySQL database username */
define('DB_USER', 'username_here');

/** MySQL database password */
define('DB_PASSWORD', 'password_here');

/** MySQL hostname */
define('DB_HOST', 'localhost');

[/codesyntax]

 

por:

 

[codesyntax lang=»php»]

<?php

/** The name of the database for WordPress */
define('DB_NAME', '@DB_NAME@');

/** MySQL database username */
define('DB_USER', '@DB_USER@');

/** MySQL database password */
define('DB_PASSWORD', '@DB_PASSWORD@');

/** MySQL hostname */
define('DB_HOST', '@DB_HOST@');

[/codesyntax]

 

Sustituimos las siguientes líneas:

[codesyntax lang=»php»]

<?php
define('AUTH_KEY',         'put your unique phrase here');
define('SECURE_AUTH_KEY',  'put your unique phrase here');
define('LOGGED_IN_KEY',    'put your unique phrase here');
define('NONCE_KEY',        'put your unique phrase here');
define('AUTH_SALT',        'put your unique phrase here');
define('SECURE_AUTH_SALT', 'put your unique phrase here');
define('LOGGED_IN_SALT',   'put your unique phrase here');
define('NONCE_SALT',       'put your unique phrase here');

[/codesyntax]

Por:

@UNIQUE_PHRASES@

Sustituye o añade las siguientes líneas:

/**
 * WordPress Localized Language, defaults to English.
 *
 * Change this to localize WordPress. A corresponding MO file for the chosen
 * language must be installed to wp-content/languages. For example, install
 * de_DE.mo to wp-content/languages and set WPLANG to 'de_DE' to enable German
 * language support.
 */
define('WPLANG', '@I18N@');

Si en tu wp-config-sample.php tienes esta línea:

define('WP_DEBUG', false);

Sustitúyela por:

define('WP_DEBUG', @DEBUG@);

Sino tendrás que añadirla igualmente.

Guarda el archivo

Ahora creamos un nuevo script en bash llamado content-wordpress.sh en /var/www/dev/utils, con el siguiente contenido:

[codesyntax lang=»bash»]

#!/bin/bash

#Variables
TIPO_REPOSITORIO=$1
URL_REPO=$2
URI_REPO=$3
TEMP_DIR=$4
DIR_SOURCES=$5
NOMBRE_REPOSITORIO=$6
SED_TEMP_DIR=$(echo $TEMP_DIR | sed -e 's/\//\\\//g')
DIR_BASE_PROJECTS="var/www/"

[/codesyntax]

Aquí guardamos en variables los parámetros que le hemos pasado al script. Si recuerdas del post anterior, al finalizar la creación del repositorio llamamos al archivo content-wordpress.sh con algunos parámetros:

/var/www/dev/utils/./content-wordpress.sh $TIPO_REPOSITORIO $URL_REPO $URI_REPO $TEMP_DIR_TRUNK $DIR_WORDPRESS $NOMBRE_REPOSITORIO

Debajo de las variables añadimos el siguiente código:

[codesyntax lang=»bash»]

echo "Bienvenido/a, en primer lugar vamos a añadir el archivo wp-config a tu WordPress."
echo "Voy a añadir las unique phrases para proteger la app de posibles ataques."

SALT=$(wget https://api.wordpress.org/secret-key/1.1/salt/ -q -O -)
$(cp "/var/www/dev/utils/wp-config-sample.php" "${TEMP_DIR}/src/wp-config.php")
$(printf '%s\n' "g/@UNIQUE_PHRASES@/d" a "$SALT" . w | ed -s "${TEMP_DIR}/src/wp-config.php")

[/codesyntax]

Añadimos un texto de bienvenida y procedemos a ejecutar el primer paso: crear las unique phrases. Las obtenemos a través de wget; a continuación copiamos el archivo wp-confi-sample.php al directorio src del proyecto. Por último sustituimos el texto «@UNIQUE_PHRASES@» por los datos obtenidos de wget, que previamente hemos guardado en la variable $SALT.

Ahora añadimos el código correspondiente para obtener las credenciales para que WordPress conecte con la base de datos:

[codesyntax lang=»bash»]

echo "Ahora necesito conocer algunos datos para configurar la base de datos"

while [ -z $DB_NAME ] 
do
	echo "Nombre de la base de datos: "
	read DB_NAME
done

while [ -z $DB_USER ]
do
	echo "Nombre del usuario de la base de datos: "
	read DB_USER
done

while [ -z $DB_PASSWORD ]
do
	echo "Password del usuario de la base de datos: "
	read DB_PASSWORD
done

while [ -z $DB_HOST ]
do
	echo "Host de la base de datos (por defecto localhost): "
	read DB_HOST

	if [ -z $DB_HOST ]
	then
		DB_HOST="localhost"
	fi
done

[/codesyntax]

Le preguntamos al usuario por el idioma en el que estará WordPress, y si quiere activar el modo de depuración:

[codesyntax lang=»bash»]

while [ -z $I18N ]
do
	echo "Idioma de la app (recuerda que debe tener el siguiente formato en_EN, es_ES, etc., (por defecto es_ES): "
	read I18N

	if [ -z $I18N ]
	then
		I18N="es_ES"
	fi
done

while [ -z $DEBUG ]
do
	echo "¿Activar modo depuración? (y/n)(por defecto y): "
	read DEBUG

	if [ -z $DEBUG ]
	then
		DEBUG="y"
	fi
done

[/codesyntax]

Ahora se modifica el archivo wp-config.php del proyecto para añadir los valores que ha indicado el usuario:

[codesyntax lang=»bash»]

echo "Modificando el archivo wp-config.php, un momento por favor..."
$(printf '%s\n' "g/@DB_NAME@/d" a "define('DB_NAME', '$DB_NAME');" . w | ed -s "${TEMP_DIR}/src/wp-config.php")
$(printf '%s\n' "g/@DB_USER@/d" a "define('DB_USER', '$DB_USER');" . w | ed -s "${TEMP_DIR}/src/wp-config.php")
$(printf '%s\n' "g/@DB_PASSWORD@/d" a "define('DB_PASSWORD', '$DB_PASSWORD');" . w | ed -s "${TEMP_DIR}/src/wp-config.php")
$(printf '%s\n' "g/@DB_HOST@/d" a "define('DB_HOST', '$DB_HOST');" . w | ed -s "${TEMP_DIR}/src/wp-config.php")
$(printf '%s\n' "g/@I18N@/d" a "define('WPLANG', '$I18N');" . w | ed -s "${TEMP_DIR}/src/wp-config.php")

if [ $DEBUG == "y" ]
then
	$(printf '%s\n' "g/@DEBUG@/d" a "define('WP_DEBUG', true);" . w | ed -s "${TEMP_DIR}/src/wp-config.php")
elif [ $DEBUG == "n" ]
then
	$(printf '%s\n' "g/@DEBUG@/d" a "define('WP_DEBUG', false);" . w | ed -s "${TEMP_DIR}/src/wp-config.php")
fi

[/codesyntax]

Debajo de lo anterior añadimos el siguiente código:

[codesyntax lang=»bash»]

echo "Copio todos los archivos del proyecto al directorio ${NOMBRE_REPOSITORIO} en /var/www/ para poder recuperar la base de datos base."
mkdir "/var/www/${NOMBRE_REPOSITORIO}"

cp -r "${TEMP_DIR}/src/*" "/var/www/${NOMBRE_REPOSITORIO}"

[/codesyntax]

Ahora creamos la base de datos:

[codesyntax lang=»bash»]

echo "Creo la base de datos"
$(mysqladmin -u ic --password=12312312 create ${DB_NAME})

echo "Creo el usuario de MySQL"
$(mysql -u ic --password=12312312 --execute="GRANT ALL on ${DB_NAME}.* to ${DB_USER}@localhost identified by '${DB_PASSWORD}'")

[/codesyntax]

Al realizar la instalación de WordPress desde el navegador, nos piden algunos datos que debemos indicar, por tanto se los pedimos al usuario:

[codesyntax lang=»bash»]

echo "Antes de iniciar el proceso de instalación para obtener una copia de la BD es necesario que me indiques algunos datos"

while [ -z $TITLE ]
do
	echo "¿Título del blog?: "
	read TITLE

	if [ -z $TITLE ]
	then
		echo "Es necesario indicar un título"
	fi
done

while [ -z $ADMIN_NAME ]
do
	echo "¿Nombre del administrador? (por defecto: admin): "
	read ADMIN_NAME

	if [ -z $ADMIN_NAME ]
	then
		ADMIN_NAME="admin"
	fi
done

while [ -z $ADMIN_PASS ]
do
	echo "¿Contraseña para el administrador? (por defecto: 12312312): "
	read ADMIN_PASS

	if [ -z $ADMIN_PASS ]
	then
		ADMIN_PASS="12312312"
	fi
done

while [ -z $ADMIN_EMAIL ]
do
	echo "¿Email para el administrador? (por defecto: tuemail@mail.com): "
	read ADMIN_EMAIL

	if [ -z $ADMIN_EMAIL ]
	then
		ADMIN_EMAIL="tuemail@mail.com"
	fi
done

while [ -z $SEARCH_ENGINES ]
do
	echo "¿Permite que los motores de búsquedas indexen este sitio.? y/n (por defecto: y): "
	read SEARCH_ENGINES

	if [ -z $SEARCH_ENGINES ]
	then
		SEARCH_ENGINES="y"
	fi
done

[/codesyntax]

Puedes sustituir «tuemail@mail.com» por la dirección de email que uses en tus desarrollos.

Ahora añadimos una línea para ejecutar la instalación de WordPress en Selenium:

[codesyntax lang=»bash»]

echo "Ejecuto el script de Selenium para instalar WordPress y así poder hacer una copia de la BD"

$(php /var/www/dev/selenium/wordpress/instalar_wordpress.php -- ${NOMBRE_REPOSITORIO} "${TITLE}" ${ADMIN_NAME} ${ADMIN_PASS} ${ADMIN_EMAIL} ${SEARCH_ENGINES})

[/codesyntax]

El contenido del script lo explicaré con detenimiento en el próximo post.

Una vez finalizado el script de Selenium es necesario guardar una copia de la BD, por seguridad:

[codesyntax lang=»bash»]

echo "Realizo la copia de la estructura de la BD"
$(mysqldump -uic -p12312312 --no-data --add-drop-database --databases ${DB_NAME} > "${TEMP_DIR}/db/basic/basic_structure.sql")

echo "Realizo la copia de los datos de la BD"
$(mysqldump -uic -p12312312 --complete-insert --no-create-info ${DB_NAME} > "${TEMP_DIR}/db/basic/basic_data.sql")

[/codesyntax]

Le preguntamos al usuario por los plugins y/o temas a instalar en el proyecto:

[codesyntax lang=»bash»]

echo "Ahora necesito saber los temas y plugins a instalar"

while [ -z $IFEATURE ]
do
	echo "¿Desea utilizar iFeature como Tema? (y/n) (default=n)"
	read IFEATURE

	if [ -z $IFEATURE ]
	then
		IFEATURE="n"
	fi
done

while [ -z $ERRORLOGMONITOR ]
do
	echo "¿Desea utilizar el plugin de desarrollo error-log-monitor? (y/n) (default=y)"
	read ERRORLOGMONITOR

	if [ -z $ERRORLOGMONITOR ]
	then
		ERRORLOGMONITOR="y"
	fi
done

[/codesyntax]

En mi caso tengo bastantes más plugins en el script, pero para que te hagas una idea de la estructura que debe tener el código solo te muestro dos, el resto es siempre igual: Se crea el while, se muestra la pregunta y se comprueba que el usuario haya escrito algo o no. Para otros temas o plugins tendrías que replicar el mismo código tantas veces como temas y plugins quieras añadir al script. Recuerda que en cada bloque debe existir una variable única para cada tema o plugin.

Copiamos los temas y plugins a sus respectivos directorios dentro del proyecto:

[codesyntax lang=»bash»]

echo "Con esta información voy a copiar los temas y plugins elegidos al directorio temporal."

if [ $IFEATURE == "y" ]
then
	$(mkdir "${TEMP_DIR}/wp-content/themes/ifeature")
	$(cp -r "${DIR_SOURCES}themes/ifeature/"* "${TEMP_DIR}/src/wp-content/themes/ifeature")
	THEME="iFeature"
fi

[/codesyntax]

Para el tema que vayas a instalar es necesario añadir la variable THEME con el nombre del tema. Esto permitirá instalar el tema a través de Selenium.

El código de arriba será igual para todos los temas y plugins (exceptuando la línea «THEME» que solo se utiliza en los temas), tendrás que cambiar las rutas para que apunten a sus respectivos directorios.

Y debajo de este código, añadimos el siguiente:

[codesyntax lang=»bash»]

echo "Copio de nuevo el contenido del directorio temporal a /var/www/ para obtener una copia de la BD"
cp -r "${TEMP_DIR}/src/*" "/var/www/${NOMBRE_REPOSITORIO}"

echo "Activo los plugins utilizando un script de Selenium"
$(php /var/www/dev/selenium/wordpress/instalar_plugins_wordpress.php -- ${NOMBRE_REPOSITORIO} ${ADMIN_NAME} ${ADMIN_PASS})

echo "Activo el tema que se ha elegido"
$(php /var/www/dev/selenium/wordpress/instalar_tema_wordpress.php -- ${NOMBRE_REPOSITORIO} ${ADMIN_NAME} ${ADMIN_PASS} ${THEME})

echo "Hago un backup de la base de datos con los plugins y el tema ya instalados"
$(mysqldump -uic -p12312312 --no-data --add-drop-database --databases ${DB_NAME} > "${TEMP_DIR}/db/modules/modules_structure.sql")

echo "Realizo la copia de los datos de la BD"
$(mysqldump -uic -p12312312 --complete-insert --no-create-info ${DB_NAME} > "${TEMP_DIR}/db/modules/modules_data.sql")

[/codesyntax]

Al instalar los plugins y temas, volvemos a realizar la copia de la base de datos.

Para los plugin de desarrollo como error-log-monitor, lo que hice es separarlos del resto de plugins, con lo que ahora toca copiarlos e instalarlos:

[codesyntax lang=»bash»]

echo "Instalo los plugins de desarrollo elegidos"

if [ $ERRORLOGMONITOR == "y" ]
then
	$(mkdir "${TEMP_DIR}/wp-content/plugins/error-log-monitor")
	$(cp -r "${DIR_SOURCES}plugins/error-log-monitor/"* "${TEMP_DIR}/src/wp-content/plugins/error-log-monitor")
fi

[/codesyntax]

Esto me permite crear dos copias de la base de datos: una con los plugins de desarrollo y otra sin ellos. Esto es muy útil a la hora de poder cambiar entre bases de datos y entornos.

Hacemos copia de la BD con los nuevos plugins:

[codesyntax lang=»bash»]

echo "Copio de nuevo el contenido del directorio temporal a /var/www/ para obtener una copia de la BD"
cp -r "${TEMP_DIR}/src/*" "/var/www/${NOMBRE_REPOSITORIO}"

echo "Activo los plugins utilizando un script de Selenium"
$(php /var/www/dev/selenium/wordpress/instalar_plugins_dev_wordpress.php -- ${NOMBRE_REPOSITORIO} ${ADMIN_NAME} ${ADMIN_PASS})

echo "Hago un backup de la base de datos con los plugins de desarrollo ya instalados"
$(mysqldump -uic -p12312312 --no-data --add-drop-database --databases ${DB_NAME} > "${TEMP_DIR}/db/modules-dev/modules-dev_structure.sql")

echo "Realizo la copia de los datos de la BD"
$(mysqldump -uic -p12312312 --complete-insert --no-create-info ${DB_NAME} > "${TEMP_DIR}/db/modules-dev/modules-dev_data.sql")

[/codesyntax]

El script de Selenium lo veremos más adelante.

El código es practicamente igual, con la excepción de que ahora se crea un archivo sql con los plugins de desarrollo ya instalados.

Ahora copiamos algunos scripts para la instalación de la base de datos en los diferentes entornos:

[codesyntax lang=»bash»]

echo "Añado el archivo de instalación de la base de datos en el directorio sh"
cp "${DIR_BASE_PROJECTS}dev/sh/instalar_db.sh" "${TEMP_DIR_TRUNK}/sh/instalar_db.sh"
cp "${DIR_BASE_PROJECTS}dev/sh/instalar_db.sh" "${TEMP_DIR_TRUNK}/sh/instalar_db_dev.sh"
sed -i -e "s/@USER@/ic/g" "${TEMP_DIR_TRUNK}/sh/instalar_db_dev.sh"
sed -i -e "s/@PASS@/12312312/g" "${TEMP_DIR_TRUNK}/sh/instalar_db_dev.sh"
sed -i -e "s/@BD@/${DB_NAME}/g" "${TEMP_DIR_TRUNK}/sh/instalar_db_dev.sh"
sed -i -e "s/@STRUCTURE_FILE@/${SED_TEMP_DIR}\/db\/modules-dev\/modules-dev_structure.sql/g" "${TEMP_DIR_TRUNK}/sh/instalar_db_dev.sh"
sed -i -e "s/@DATA_FILE@/${SED_TEMP_DIR}\/db\/modules-dev\/modules-dev_data.sql/g" "${TEMP_DIR_TRUNK}/sh/instalar_db_dev.sh"

sed -i -e "s/@USER@/ic/g" "${TEMP_DIR_TRUNK}/sh/instalar_db.sh"
sed -i -e "s/@PASS@/12312312/g" "${TEMP_DIR_TRUNK}/sh/instalar_db.sh"
sed -i -e "s/@BD@/${DB_NAME}/g" "${TEMP_DIR_TRUNK}/sh/instalar_db.sh"
sed -i -e "s/@STRUCTURE_FILE@/${SED_TEMP_DIR}\/db\/modules\/modules_structure.sql/g" "${TEMP_DIR_TRUNK}/sh/instalar_db.sh"
sed -i -e "s/@DATA_FILE@/${SED_TEMP_DIR}\/db\/modules\/modules_data.sql/g" "${TEMP_DIR_TRUNK}/sh/instalar_db.sh"

[/codesyntax]

De esta manera podemos tener siempre una copia de la base de datos con diferentes plugins instalados, lo que nos da muchas facilidades a la hora de cambiar de entorno de desarrollo a preproducción, testeo y/o producción.

Por último, y para acabar nuestro script hacemos commit y eliminamos los datos temporales:

[codesyntax lang=»bash»]

echo "Ahora procederé a realizar un commit del nuevo contenido"

cd $TEMP_DIR

if [ "$TIPO_REPOSITORIO" == 'git' ]
then
	$(git add *)
	$(git commit -m "Añadido los temas y plugins correspondientes")
	$(git push origin master)
elif [ "$TIPO_REPOSITORIO" == 'svn' ]
then
	$(svn commit -m "Añadidos los temas y plugins correspondientes" http://svn.ic.net/$NOMBRE_REPOSITORIO)
fi

#Eliminamos el directorio temporal
echo "Eliminamos el directorio temporal, la base de datos y su usuario y cerramos la máquina virtual"
$(mysql -u ic --password=12312312 --execute="REVOKE ALL ON *.* FROM '${DB_USER}'@'localhost';")
$(mysqladmin -uic -p12312312 drop ${DB_NAME})
$(VBoxManage controlvm Ubuntu poweroff)
$(rm -fr $TEMP_DIR)
$(rm -fr "/var/www/${NOMBRE_REPOSITORIO}"

[/codesyntax]

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Descubre más desde Interadictos

Suscríbete ahora para seguir leyendo y obtener acceso al archivo completo.

Seguir leyendo