Deployment mit Phing z.B. Joomla Teil 2

Archiv deployen und Wartungsseite anzeigen


Nachdem im ersten Teil beschrieben wurde wie man ein Archiv für das Deployment erstellt, wird hier gezeigt wie man dieses auf dem Zielsystem weiterverarbeiten kann. Da die meisten Server unter Linux laufen, wird nun Kombination aus Shell-Script und Phing genutzt.

Das Archiv befindet sich nun auf dem Zielserver. Sicherlich könnte man es manuell entpacken und verarbeiten. Das ist jedoch sehr zeitaufwändig und vor allem fehleranfällig. Leider ist dieses Vorgehen auch heute noch bei vielen Unternehmen verbreitet. Da wir die Vorteile der Automatisierung nicht nur für die Entwicklung sondern auch für das Deployment nutzen wollen, nehmen wir Phing zu Hilfe. Folgendes wird automatisiert ausgeführt:

  1. Backup des Codes und der Datenbank erstellen
  2. Entpacken des Archivs
  3. Einen Symlink erstellen damit die Wartungsseite angezeigt wird
  4. Alte Dateien löschen
  5. Neue Dateien an den Zielort kopieren
  6. Rechte anpassen
  7. Neue Datenbank einlesen (sowas ist nur zu empfehlen wenn die Datenbank nicht allzu groß ist)
  8. Aufräumen, löschen des Deployment-Archivs sowie der temporären Dateien

phing-config.xml


<?xml version="1.0" encoding="UTF-8"?>

<project name="JoomlaDeploymentDeploy" default="clean">

    <fail unless="projectName" message="Please provide a projectName." />
    <fail unless="dbHost" message="Please provide the database host." />
    <fail unless="dbName" message="Please provide the database name." />
    <fail unless="dbUser" message="Please provide the database user." />
    <fail unless="dbPassword" message="Please provide database password." />
    <fail unless="archiveDir" message="Please provide the directory where the archive is located." />
    <fail unless="archiveBaseName" message="Please provide the file name of the archive without extension." />
    <fail unless="baseTmpDir" message="Please provide the base build directory." />
    <fail unless="tmpSrcDirName" message="Please provide the temporal source directory." />
    <fail unless="tmpDataDirName" message="Please provide the temporal data directory." />
    <fail unless="tmpBackupDirName" message="Please provide the temporal backup directory." />
    <fail unless="targetDir" message="Please provide the target directory." />
    <fail unless="maintenanceDir" message="Please provide the maintenance directory." />
    <fail unless="wwwDir" message="Please provide the www directory." />
    <fail unless="linkName" message="Please provide the maintenance directory." />
    <fail unless="backupDir" message="Please provide the backup directory." />

    <tstamp prefix="mytime"></tstamp>

    <property name="tmpDir" value="${baseTmpDir}/${archiveBaseName}" />
    <property name="srcTmpDir" value="${tmpDir}/${tmpSrcDirName}" />
    <property name="dataTmpDir" value="${tmpDir}/${tmpDataDirName}" />
    <property name="backupTmpDir" value="${tmpDir}/${tmpBackupDirName}" />
    <property name="archiveName" value="${archiveBaseName}.tar.gz" />
    <property name="archiveFile" value="${archiveDir}/${archiveName}" />
    <property name="backupName" value="${projectName}_${mytime.DSTAMP}_${mytime.TSTAMP}" />
    <property name="codeBackupFileName" value="${backupName}.tar.gz" />
    <property name="dbBackupTmpFileName" value="${backupName}.sql" />
    <property name="dbBackupFileName" value="db.${codeBackupFileName}" />

    <available file="${archiveFile}" property="archiveFileExists" value="1"/>
    <fail unless="archiveFileExists" message="Archive ${archiveFile} does not exist." />

    <!-- ============================================  -->
    <!-- Target: prepare                               -->
    <!-- ============================================  -->
    <target name="prepare">
        <mkdir dir="${tmpDir}" />
        <mkdir dir="${backupTmpDir}" />
    </target>

    <!-- ============================================  -->
    <!-- Target: backup code                           -->
    <!-- ============================================  -->
    <target name="backup-code" depends="prepare">
        <echo msg="Creating code backup in ${backupDir}/${codeBackupFileName}" />
        <exec checkreturn="true" command="tar -czvPf ${backupDir}/${codeBackupFileName} ${targetDir}" />
    </target>

    <!-- ============================================  -->
    <!-- Target: backup database                       -->
    <!-- ============================================  -->
    <target name="backup-database" depends="backup-code">
        <echo msg="Creating database backup in ${backupDir}/${dbBackupFileName}" />
        <exec checkreturn="true" command="mysqldump  -h ${dbHost} -u${dbUser} -p${dbPassword} --default-character-set=utf8 --databases ${dbName}  > ${backupTmpDir}/${dbBackupTmpFileName}" />
        <exec checkreturn="true" command="tar -czvPf ${backupDir}/${dbBackupFileName} ${backupTmpDir}/${dbBackupTmpFileName}" />
    </target>

    <!-- ============================================  -->
    <!-- Target: extract                               -->
    <!-- ============================================  -->
    <target name="extract" depends="backup-database">
        <echo msg="Extracting archive ${archiveFile} to ${tmpDir}" />
        <exec checkreturn="true" command="tar -xzvf ${archiveFile} -C ${tmpDir}" />
    </target>
    
    <!-- ============================================  -->
    <!-- Target: linkmaintenance                       -->
    <!-- ============================================  -->
    <target name="linkmaintenance" depends="extract">
        <echo msg="Symlinking to maintenance directory." />
        <exec checkreturn="true" command="rm ${wwwDir}/${linkName}" />
        <exec checkreturn="true" command="ln -s ${maintenanceDir} ${wwwDir}/${linkName}" />
    </target>

    <!-- ============================================  -->
    <!-- Target: cleantarget                           -->
    <!-- ============================================  -->
    <target name="cleantarget" depends="linkmaintenance">
        <echo msg="Cleaning ${targetDir} from old files." />
        <exec checkreturn="true" command="rm -rf ${targetDir}/*" />
    </target>
    
    <!-- ============================================  -->
    <!-- Target: copy                                  -->
    <!-- ============================================  -->
    <target name="copy" depends="cleantarget">
        <echo msg="Copy files from ${srcTmpDir} to target dir ${targetDir}." />
        <exec checkreturn="true" command="cp -r ${srcTmpDir}/* ${targetDir}" />
    </target>
    
    <!-- ============================================  -->
    <!-- Target: permissions                           -->
    <!-- ============================================  -->
    <target name="permissions" depends="copy">
        <echo msg="Adjusting permissions." />
        <exec checkreturn="true" command="chmod 0777 ${targetDir}/cache" />
    </target>

    <!-- ============================================  -->
    <!-- Target: importdb                              -->
    <!-- ============================================  -->
    <target name="importdb" depends="permissions">
        <echo msg="Importing database" />
        <exec checkreturn="true" command="mysql -h ${dbHost} -u${dbUser} --password=${dbPassword} --default-character-set=utf8 ${dbName} &lt; ${dataTmpDir}/${dbName}.sql" />
    </target>

    <!-- ============================================  -->
    <!-- Target: linksource                            -->
    <!-- ============================================  -->
    <target name="linksource" depends="importdb">
        <echo msg="Symlinking to target directory." />
        <exec checkreturn="true" command="rm ${wwwDir}/${linkName}" />
        <exec checkreturn="true" command="ln -s ${targetDir} ${wwwDir}/${linkName}" />
    </target>
    
    <!-- ============================================  -->
    <!-- Target: clean                                 -->
    <!-- ============================================  -->
    <target name="clean" depends="linksource">
        <echo msg="Performing cleanup." />
        <exec checkreturn="true" command="rm ${archiveFile}" />
        <exec checkreturn="true" command="rm -rf ${tmpDir}" />
    </target>
    
</project>

run.sh


#!/usr/bin/env bash

if [ $# -ne 1 ]
  then
    echo "Please provide exactly one argument, the deployment archive without file extension."
    exit
fi

ARCHIVE_BASE_NAME=$1

PROJECT_NAME="your-project.com"
DB_HOST="localhost";
DB_NAME="your-db-name";
DB_USER="your-db-password"
DB_PASSWORD="super@geheim"
ARCHIVE_DIR="/home/user123/deployment/your-project.com/archive"
BASE_TMP_DIR="/home/user123/deployment/your-project.com/tmp"
TMP_SRC_DIR_NAME="src"
TMP_DATA_DIR_NAME="data"
TMP_BACKUP_DIR_NAME="backup"
TARGET_DIR="/var/www/vhosts/somefolder/your-project.com.src"
MAINTENANCE_DIR="/var/www/vhosts/somefolder/your-project.com.maintenance"
WWW_DIR="/var/www/vhosts/somefolder"
LINK_NAME="your-project.com"
BACKUP_DIR="/home/user123/backup/your-project.com"

BUILD_FILE="/home/user123/my-deployment-scripts/your-project-phing-config.xml";
PHING_BIN_PATH="/home/user123/opt/phing/vendor/phing/phing/bin/phing"

php "$PHING_BIN_PATH" -f "$BUILD_FILE" \
-DprojectName="$PROJECT_NAME" \
-DdbHost="$DB_HOST" \
-DdbName="$DB_NAME" \
-DdbUser="$DB_USER" \
-DdbPassword="$DB_PASSWORD" \
-DarchiveDir="$ARCHIVE_DIR" \
-DarchiveBaseName="$ARCHIVE_BASE_NAME" \
-DbaseTmpDir="$BASE_TMP_DIR" \
-DtmpSrcDirName="$TMP_SRC_DIR_NAME" \
-DtmpDataDirName="$TMP_DATA_DIR_NAME" \
-DtmpBackupDirName="$TMP_BACKUP_DIR_NAME" \
-DtargetDir="$TARGET_DIR" \
-DmaintenanceDir="$MAINTENANCE_DIR" \
-DwwwDir="$WWW_DIR" \
-DlinkName="$LINK_NAME" \
-DbackupDir="$BACKUP_DIR"

Nun muss nur noch run.sh mit dem Archivnamen (ohne Dateiendung .tar.gz) als Parameter aufgerufen werden.

Sicherlich kann man das Deployment noch weiter automatisieren. Man könnte das Archiv nach Erstellung z.B. mit SCP hochladen und anschließend per ssh den Shell-Script-Aufruf machen.

Zurück zur Kategorie: Dev-Ops
Zurück nach oben