Thursday, September 24th, 2009...4:14 pm

My First Attempt With Phing

Jump to Comments

I’ve finally come to the place where I need some help in automated deployments. I’ve got a few weekend PHP projects that are getting large enough that deploying them takes a few minutes — minutes where stuff can break and stay broken until I remember the exact command line call I need to make to fix them. SVN export, symlinks, mkdir’s, etc etc. I want to automate this crap!

My first attempt was with using Capistrano. I’d heard it could be hacked a bit to make it deploy just about anything. So I installed the gem and tinkered. The trouble is, I don’t have time to learn Ruby right now. Furthermore, I don’t like having the Ruby/Capistrano dependencies.

…and in walks Phing — automated deployment using PHP and XML. Hey! I know those!

Installing Phing was a bit more troublesome than Capistrano — mainly because my hosting company (Dreamhost) has some restrictions around installing PEAR modules and also a small issue in that the default command line bin for PHP is v4 — no good for Phing, which requires PHP5.

A few hours later, and viola! Phing is ready to roll.

So here’s my first script (well, I stripped out some duplicate actions — these two are the most interesting). It imports two files: “mysql.properties” and “subversion.properties” as needed. If you have any comments, questions, or suggestions, post a comment.

Also, my xml is a bit wider than my blog here, so here’s the source

  1. < ?xml version="1.0"?>
  2. <project name="build" default="help">
  3.  
  4. <target name="help">
  5.         <exec command="phing -h" passthru="true" />
  6. </target>
  7.  
  8. <target name="load.subversion">
  9.         <property file="subversion.properties" />
  10. </target>
  11.  
  12. <target name="load.mysql">
  13.         <property file="mysql.properties" />
  14. </target>
  15.  
  16. <!–deploy a productionv version of an API I wrote.  SVN export with a build number’d folder, then change the symlink –>
  17. <target name="api-deploy" depends="load.subversion">
  18.         <!–setup properties–>
  19.         <property name="repo" value="http://${svn.username}:${svn.password}@${svn.base}/api/trunk" />
  20.         <!–display repo info–>
  21.         <exec command="svn info ${repo}" passthru="true" />
  22.         <!–ask user for revision num–>
  23.         <propertyprompt propertyName="svn.exportrevision" promptText="Enter the API revision number to deploy" />
  24.         <property name="exportdir"  value="/www/builds/api/${svn.exportrevision}" />
  25.         <echo>Will deploy to ${exportdir}</echo>
  26.         <exec command="svn export -r ${svn.exportrevision} ${repo} ${exportdir}"  />
  27.        
  28.         <!–make sure the export worked –>
  29.         <available file="${exportdir}" type="dir" property="export.success" />
  30.         <if>
  31.                  <equals arg1="${export.success}" arg2="TRUE" />
  32.          <then>
  33.                  <echo message="SVN successfully exported (${export.success})" />
  34.         </then>
  35.         <else>
  36.                 <fail message="There was an error with the SVN export.  Most likely, you supplied an incorrect revision number" />
  37.         </else>
  38.         </if>
  39.  
  40.         <!–create cache folder –>
  41.         <mkdir dir="${exportdir}/system/cache" />
  42.         <exec command="chmod 777 ${exportdir}/system/cache"  />
  43.         <echo>API Revision #${svn.exportrevision} exported to ${exportdir}</echo>
  44.  
  45.         <!–symlink api.mydomain.com to svn export –>
  46.         <exec command="ln -nfs ${exportdir} /www/api.mydomain.com"  />
  47.  
  48. </target>
  49.  
  50.  
  51. <target name="api-rollback">
  52.         <!–display possible rollback dirs–>
  53.         <echo msg="Possible directories to rollback to:" />
  54.         <exec command="ls" dir="/www/builds/api/" passthru="true" />
  55.         <propertyprompt propertyName="svn.rollbackrevision" promptText="Which revision to rollback to?" />
  56.         <property name="rollbackdir"  value="/www/builds/api/${svn.rollbackrevision}" />
  57.         <!–let’s make sure that directory exists–>
  58.         <available file="${rollbackdir}" type="dir" property="rollback.available" />
  59.         <if>
  60.                 <equals arg1="${rollback.available}" arg2="TRUE" />
  61.         <then>
  62.                 <exec command="ln -nfs ${rollbackdir} /www/api.mydomain.com"  />
  63.                 <echo>API rolled back to revision # ${svn.rollbackrevision}</echo>
  64.         </then>
  65.         <else>
  66.                 <fail message="The rollback revision folder you specified does not exist" />
  67.         </else>
  68.         </if>
  69. </target>
  70.  
  71. <!–sync my PRD DB and wordpress wp-content/uploads to DEV –>
  72. <target name="sync-dev-db" depends="load.mysql">
  73.         <property name="tmp.folder" value="/www/tmp" />
  74.         <property name="sql.filename" value="mydomain_prd_tmp.sql" />
  75.         <property name="sql.file" value="${tmp.folder}/${sql.filename}" />
  76.         <exec command="mysqldump -u${mysql.username} -p${mysql.password} -h ${mysql.server} mydomain_prd > ${sql.file}" />
  77.         <reflexive>
  78.                 <fileset dir="${tmp.folder}">
  79.                         <include pattern="${sql.filename}" />
  80.                 </fileset>
  81.                 <filterchain>
  82.                          <replaceregexp>
  83.                                 <regexp pattern="prd.mydomain.com" replace="dev.mydomain.com" ignoreCase="true"/>
  84.                         </replaceregexp>
  85.                 </filterchain>
  86.         </reflexive>
  87.         <!– next step, MySQL import to mydomain_dev and delete the tmp sql dump –>
  88.                 <exec passthru="true" command="mysql -u${mysql.username} -p${mysql.password} -h ${mysql.server} mydomain_dev < ${sql.file}" />
  89.                 <delete file="${sql.file}" />
  90.         <!– sync PRD wp-content/uploads to DEV wp-content/uploads –> 
  91.                 <exec command="rm -r /www/dev.mydomain.com/wp-content/uploads" />
  92.                 <exec command="cp -rp /www/prd.mydomain.com/wp-content/uploads /www/dev.mydomain.com/wp-content/" />
  93.         <!– make sure the dev uploads folder exists –>
  94.         <available file="/www/dev.mydomain.com/wp-content/uploads" type="dir" property="folder.available" />
  95.         <if>
  96.                 <equals arg1="${folder.available}" arg2="FALSE" />
  97.         <then>
  98.                 <fail message="Something’s wrong — the dev ‘uploads‘ folder isn’t where it should be." />
  99.         </then>
  100.         </if>
  101.  
  102. </exec></target>
  103.  
  104. </project>

Tags: > > > >

3 Comments

Leave a Reply