Builds and Deployments

At my previous companies, there have been two ways of putting code onto a QA or production server. FTP the files up or svn up a checkout of the production branch.

But builds are so much cooler. You can have a build process that runs unit tests and other code analysis, removes unit tests or other things not required on the production server, and then packages this up into a tarball or zip. For this, I use a very simple phing build script. Phing is a great tool built for PHP that allows you to accomplish tasks like creating builds. A simplified version of this is as follows:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project name="BuildSystem" default="all">
  3.   <property name="name" value="flexistat" override="true" />
  4.   <property name="svnLoc" value="svn+ssh://zefram@svn-server/dev/svn" override="true" />
  5.   <property name="svnTags" value="${svnLoc}/tags" override="true" />
  6.   <property name="versionName" value="${name}-${version}" override="true" />
  7.   <property name="svnTagLoc" value="${svnTags}/${versionName}" override="true" />
  8.   <property name="tmpdir" value="/tmp/${versionName}" />
  9.  
  10.   <target name="run-migration">
  11.     <exec command="php symfony –env=build propel:diff" dir="/Users/jgillis/Documents/workspace/rynek" checkreturn="true" />
  12.   </target>
  13.  
  14.   <target name="all" depends="tag,build,copy-to-repo">
  15.   </target>
  16.   <target name="tag">
  17.     <fail unless="version" message="Version must be set to build" />
  18.     <echo>Tagging ${version} in svn</echo>
  19.     <svncopy repositoryurl="${svnTrunk}" todir="${svnTagLoc}" message="Tagging version ${version} of ${name}" />
  20.   </target>
  21.   <target name="export">
  22.     <echo>Exporting ${name}</echo>
  23.     <svnexport repositoryurl="${svnTagLoc}" todir="${tmpdir}" />
  24.   </target>
  25.   <target name="clean" depends="export">
  26.     <echo>Cleaning up…</echo>
  27.     <delete dir="${tmpdir}/contrib/symfony/lib/plugins/sfDoctrinePlugin" />
  28.     <delete dir="${tmpdir}/contrib/symfony/lib/plugins/sfPropelPlugin" />       <delete dir="${tmpdir}/contrib/symfony/lib/test" />
  29.     <delete dir="${tmpdir}/contrib/symfony/test" />
  30.     <delete>
  31.       <fileset dir="${tmpdir}/plugins">
  32.         <include name="*/test" />
  33.       </fileset>
  34.     </delete>
  35.     <delete dir="${tmpdir}/test" />
  36.   </target>
  37.  
  38.   <target name="build" depends="export,test,clean">
  39.     <echo>Compressing</echo>
  40.     <tar destfile="${versionName}.tar.gz" compression="gzip" basedir="${tmpdir}" />
  41.     <echo>All finished. You now have ${versionName}.tar.gz</echo>
  42.     <phingcall target="clear-export" />
  43.   </target>
  44. </project>

There’s a bit missing from this, but you get the idea…

Once you have this build, it will be exactly the same no matter where you put it. There’s no worrying about which revision number you’re on, you have a simple build number that’s ready for deployment.

Then, once you have this build, you can deploy it anywhere you want. While you can use phing to deploy, my favorite deployment tool is Capistrano. There’s a great extension to Capistrano called capifony, which adds tasks to capistrano that are symfony specific. I further extend this to allow deployments to other environments than production, switches for the build version that I’ve created previously, and all applications that I create are deployable with one central capistrano build.

All in all, I think that’s so much cooler than FTP.

This entry was posted in Lessons learned. Bookmark the permalink.

Comments are closed.