Category: Phing

Using Phing To Deploy To FTP

31 January, 2010 | Phing | 2 comments

Although most developers might not like it FTP is quite a common way of deploying the files for a site to the server. To simplify this process Phing comes with a handy FTP transfer action called ftpdeploy.

In order to use the ftpdeploy we first need to install the Net_FTP package. To install this package just enter the following command:

pear install Net_FTP

The first thing we need to create is a build.properties file to store our ftp details

ftp.destination.host=ftp.theftphost.com ftp.destination.port=21 ftp.destination.username=theftpusername ftp.destination.password=theftppassword ftp.destination.dir=public_html ftp.destination.mode=binary

Below is a trivial example of ftpdeploy in action. The build file simply defines a single fileset, which contains a single file in a directory. The ftpdeploy task accepts the parameters of the build.properties file and uses the fileset to determine which files should be uploaded. The only option that might not be obvious is the mode option. This is for telling ftpdeploy which FTP transfer mode to use, these are either ascii or binary, the default value being binary.

<?xml version="1.0"?> <project name="FtpUpload" default="main">     <!-- Include properties file. -->     <property file="build.properties" />       <fileset dir="upload" id="TheFiles">         <include name="phpinfo.php" />     </fileset>       <ftpdeploy          host="${ftp.destination.host}"         port="${ftp.destination.port}"         username="${ftp.destination.username}"         password="${ftp.destination.password}"         dir="${ftp.destination.dir}"         mode="${ftp.destination.mode}">         <fileset refid="TheFiles" />     </ftpdeploy>       <target name="main">         <echo>FTP Upload Finished!</echo>     </target>  </project>

Assuming you have called your build file ftpupload.xml, you can run this Phing build file like this.

phing -f ftpupload.xml

This will produce the following output.

Buildfile: \ftpdeploy.xml  [property] Loading \build.properties   FtpUpload > main:        [echo] FTP Upload Finished!   BUILD FINISHED   Total time: 2.4250 seconds

There is an additional option called clearfirst which can be used to delete all of the files from the remote directory. The default value for this setting is "false". The Phing documentation states that once the directory has been cleared the set files will be uploaded. I have found that although Phing will clear the directory, it will not upload the files.

Have a look at the Phing documentation for more information about the Phing ftpdeploy task.

Written by Philip Norton.

Drupal Files Migration Script Using Phing

24 November, 2009 | Drupal, Phing | 1 comment

The other day I needed to copy a Drupal project from my source folder to another folder, so rather than manually copy the files I decided to create a Phing script that would do it for me in one go. This Phing script will export your Drupal project into another directory, change the database credentials and create zip and tar files of the project. The first thing to do is create a properties, here is the contents of that file.

drupal.destination.database.host=externalhost drupal.destination.database.database= drupaldatabase drupal.destination.database.password=password drupal.destination.database.username=username drupal.destination.database.prefix=dru_   drupal.destination.database.url=mysql://${drupal.destination.database.username}:${drupal.destination.database.password}@${drupal.destination.database.host}/${drupal.destination.database.database}   drupal.source.directory=D:/drupal/ drupal.source.name=MyDrupalProject   drupal.destination.directory=D:/${drupal.source.name}/ drupal.destination.compressedfile=${drupal.source.name}

Just save this file as build.properties and change the properties to your needed settings.

The build file part of the the contains a fileset to include all of the needed files and then some targets to do things with those files. Those of you used to Phing and Drupal will notice that we are including a lot of files but we are missing one called settings.php. This is deliberate for the reason that trying to match the parameters in our build.properties file into the database settings in the settings.php file is going to be tricky. So rather than enter multiple database parameters we can just use the destination parameters, the default.settings.php file (which we will know the format) and a small amount of regular expression replacing in order to create a new settings.php file for our destination. Here is the contents of the build file.

<?xml version="1.0"?> <project name="DrupalExport" default="main">     <!-- Include properties file. -->     <property file="build.properties" />       <fileset dir="${drupal.source.directory}" id="DrupalFiles">         <include name="cron.php" />         <include name="index.php" />         <include name="install.php" />         <include name="robots.txt" />         <include name="update.php" />         <include name="xmlrpc.php" />         <include name=".htaccess" />         <include name="scripts/**" />         <include name="themes/**" />         <include name="misc/**" />         <include name="modules/**" />         <include name="profiles/**" />         <include name="includes/**" />         <include name="sites/all/**" />         <include name="sites/default/files/**" />                 <include name="sites/default/default.settings.php" />     </fileset>       <target name="prepare">         <!-- Reset the permissions on the setttings.php file so we can delete it. -->         <exec command="php -r &quot;var_dump(chmod('${drupal.destination.directory}sites/default/settings.php', 0777));&quot;" />               <!-- Delete the destination directory. -->         <delete dir="${drupal.destination.directory}" />         <echo>Prepare complete.</echo>     </target>          <target name="copyFiles" depends="prepare">         <copy todir="${drupal.destination.directory}" overwrite="false" tstamp="false">             <fileset refid="DrupalFiles" />         </copy>         <echo>copyFiles complete</echo>     </target>       <target name="drupalDatabaseConnection" depends="copyFiles">         <copy file="${drupal.source.directory}/sites/default/default.settings.php"             tofile="${drupal.destination.directory}/sites/default/settings.php"             overwrite="true">             <filterchain>                             <replaceregexp>                     <!-- Add some rules to replace settings with real values. -->                     <regexp pattern="\$db_url = 'mysql:\/\/username:password\@localhost\/databasename';" replace="\$db_url = '${drupal.destination.database.url}';"  ignoreCase="true"/>                     <regexp pattern="\$db_prefix = '';" replace="\$db_prefix = '${drupal.destination.database.prefix}';" ignoreCase="true"/>                 </replaceregexp>             </filterchain>                  </copy>         <!-- Make settings.php readonly -->         <exec command="php -r &quot;var_dump(chmod('${drupal.destination.directory}sites/default/settings.php', 0444));&quot;" />                   <echo>drupalDatabaseConnection complete</echo>     </target>            <target name="zipFiles" depends="drupalDatabaseConnection">         <fileset dir="${drupal.destination.directory}" id="DestinationFiles">             <include name="**" />         </fileset>         <!-- Delete original file. -->         <delete file="${drupal.destination.compressedfile}.zip" />                 <zip destfile="${drupal.destination.compressedfile}.zip">             <fileset refid="DestinationFiles" />         </zip>         <echo>zipFiles complete</echo>         </target>          <target name="tarFiles">         <fileset dir="${drupal.destination.directory}" id="DestinationFiles">             <include name="**" />         </fileset>         <!-- Delete original file. -->                 <delete file="${drupal.destination.compressedfile}.tar" />                   <tar destfile="${drupal.destination.compressedfile}.tar" compression="gzip">             <fileset refid="DestinationFiles" />         </tar>         <echo>tarFiles complete</echo>         </target>                <target name="main">         <phingcall target="copyFiles" />         <phingcall target="zipFiles" />         <phingcall target="tarFiles" />           <echo>Export finished!</echo>     </target>  </project>

To run this script save this xml into a file called drupalexport.xml use the following command to run it.

phing -f drupalexport.xml

You will now have a directory containing your Drupal project, as well as a zip and a tar file with the same files in them in the directory above.

Written by Philip Norton.

Using Different Loggers In Phing

17 November, 2009 | Phing | 1 comment

When you run a phing script it will print things out to the console. These messages are either system messages (eg. BUILD STARTED) or echo messages that you have put into your build.xml file. All of this output is controlled and created by a logger file. The default logger is called (unsuprsingly) DefaultLogger and will be used as a default. There are a few different types of logger available, all of which can be found in the listener folder in your PEAR\phing directory.

(more...)

Written by Philip Norton.

Integrating Phing With PHPUnit

16 January, 2009 | Phing | No comments

PHPUnit is a unit testing framework, written in PHP, and which is used to test PHP code. You can integrate the testing that PHPUnit does into Phing. You might want to use Phing to create a nightly build that contains the latest version of your program. The last thing you want is Phing to create a nightly build that is riddled with errors.

The way around this is to use PHPUnit to test our code whilst we are running Phing. If any tests fail then Phing will not finish the build.

Create a target at the top of your build.xml file and make sure it is run first. Then add the following code to the target, This will use PHPUnit to test your code.

<phpunit haltonfailure="true" haltonerror="true">   <batchtest>     <fileset dir="tests">       <include name="**/*Test*.php"/>     </fileset>   </batchtest> </phpunit>

The phpunit element contains an element called batchtest, which can contain one or more fileset elements. It is the files defined by the fileset elements that define which files are to be used in the testing. The code above includes all PHP files that have the word Test in their name.

The phpunit element contains two attributes called haltonfailure and haltonerror. These attributes will cause the build to exit if any errors or failed tests are found during the testing.

Automated Build With Phing

Written by Philip Norton.

Create Compressed Files With Phing

15 January, 2009 | Phing | 2 comments

Building your projects into directories is nice, but distributing these projects is difficult if you have to build the compressed files yourself. Phing has the ability to create zip and tar files using simple commands.

The most convenient way of using the tar and zip commands is by using a fileset. But rather than use the fileset that was used to copy the files into the build directory it is best to create a separate fileset that is used to compress the contents of the build directory.

<fileset dir="./" id="zipFiles"> <include name="myProject_build/**" /> </fileset>

To compress the files into a tar use the tar element. This accepts two parameters, the destination file (called destfile) and the compression to use (called compression). The compression attribute can take one of three values, these are gzip, bzip2 and none. Using none will not run any compression algorithms on the files. The following example will create a file called myProject.tar in the current directory, which contains all of the files and directories from the myProject_build directory.

<tar destfile="myProject.tar" compression="gzip"> <fileset refid="zipFiles" /> </tar>

To compress the files into a zip file you need to use the zip element. This works in exactly the same way as the tar element, except it doesn't have a compression attribute.

<zip destfile="myProject.zip"> <fileset refid="zipFiles" /> </zip>

The tar element works very well and the file created was as expected, but I had a little bit of trouble with the zip element. I am using Windows XP to run phing and the file that was created was blocked by Windows for having odd content. After I figured out how to open it I realized that phing had used the full path to the build folder. So rather than the zip file containing a folder called myProject_build, it contained the following folder structure, with the correct files included in the end directory.

C:\dev\tests\phing\myProject_build

Has anyone else seen this? I would be grateful for any help on the subject.

You can also use the zip and tar elements without the fileset element by using the basedir attribute. By setting the basedir you are telling phing to use everything in that directory and every sub directory.

<tar destfile="phing.tar" basedir="." compression="gzip"/>

There is a warning on the phing website that states using basedir and fileset simultaneously can result in strange contents in the archive. So I would suggest using one or the other.

Automated Build With Phing

Written by Philip Norton.