Publishing you websites using ANT scripts

AID: 644
  • Status: Published

5430 points

  • ByRoonaan
  • TypeTutorial
  • Posted on2009-05-15 at 01:37:09
Awards
  • Community Pick
Are you into PHP development and curious how you can make your life easier when publishing your website? Do you sometimes worry you might forget to remove debug lines? Or you spend unnecessary time to double check you haven't accidentally uploaded 'phpinfo.php' or some local development powerscripts that shouldn't be online?

A first step in automating your website publishing is to automate your deployment process. Besides the fact you can stop worrying, you may even include some great optimizations, that might look complex and time consuming when done manually.

1

Introduction to ANT


In the world of software development there are several tools you can use to automate your software development. Tools like ANT, Maven, and Phing help you to compile files, swap in your optimized dependencies, run unit tests, create deployment packages and do all kinds of other cool stuff from a mouseclick.

ANT (http://ant.apache.org/) is an Apache project that allows you to specify routines using simple xml and property files. It is often used in java projects, although Maven has a large market share as well. For the PHP language, Phing could be instead or, depending on your personal taste, you can use Maven or ANT, like I used here.

A simple ANT buildscript consist of 'targets' which you can run one by one or in sequences.


2

A simple ANT script: upload your files


A very basic ANT script could be used to upload your files to your server, but exclude your local uploads, debug and temp files:

[mywebsite.build.xml]
<project name="myWebsite">

  <property name="ftp.host" value="ftp.mywebsite.com" />
  <property name="ftp.username" value="your-ftp-username" />
  <property name="ftp.password" value="your-ftp-password" />
  <property name="ftp.folder" value="httpdocs/myproject/" />

  <target name="uploadWebsite">
   <ftp server="${ftp.host}"
         userid="${ftp.username}"
         password="${ftp.password}"
         remotedir="${ftp.folder}"
   >
      <fileset dir="c:/xampp/www/myproject">
          <exclude name="uploads/**/*.*" />
          <exclude name="debug/**/*.*" />
          <exclude name="temp/**/*.*" />
       </fileset>
    </ftp>
  </target>
</project>
                                    
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:

Select allOpen in new window



The snippet shows you the basic usage of property tags. You configure one or more at the top of your buildscript, and easily reference them throughout the script.

After downloading and installing ANT you can write a simple .bat or .cmd file or bash script to run the script:

[uploadWebsite.bat]
c:/Apache-ant/bin/ant.exe -f mywebsite.build.xml uploadWebsite
                                    
1:
2:

Select allOpen in new window



Each time you double click the bat file, or run a similar bash script from command line, you can be sure that only the files you specified are uploaded.



3

Loose coupling: Using property files


In the last section I showed a simple example of using the property tag (e.g. <property name="some-property" value="some-value" />). In ANT you can use separate .properties files (simple INI files) to list your settings:

[myproject.build.properties]
# FTP Settings
ftp.host          = ftp.mywebsite.com
ftp.username = your-ftp-username
ftp.password = your-ftp-password
ftp.folder        = httpdocs/myproject/
                                    
1:
2:
3:
4:
5:
6:

Select allOpen in new window



The property file can be included in your project using the snippet below:

<project name="myWebsite">
  <property file="myproject.build.properties" />
  
  .. my targets here ..
 </project>
                                    
1:
2:
3:
4:
5:

Select allOpen in new window



Note that when a property has been set, it cannot be overwritten!



4

Multiple environments: Using target chains


As a professional or semi-professional PHP developer you will probably have a test server you need to deploy to before deploying to production. You might even have a complete OTAP street with four or more servers. Using ANT you can now use the same deployment routines for as many environments as required.
To make the ANT script aware of our multiple environments, we start by upgrading the property file to hold multiple server information sets:

[myproject.build.properties]
# FTP Settings for test
ftp.test.host          = ftp.mywebsite.com
ftp.test.username = your-ftp-username
ftp.test.password = your-ftp-password
ftp.test.folder        = subdomains/test/httpdocs/myproject/

# FTP Settings for production
ftp.production.host          = ftp.mywebsite.com
ftp.production.username = your-ftp-username
ftp.production.password = your-ftp-password
ftp.production.folder        = httpdocs/myproject/
                                    
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:

Select allOpen in new window



Unless we tell ANT exactly, the script will not know which environment we want to use. Therefore we create additional targets, each for a specific environment. The newly created target's sole task is to start the deployment using the correct environment settings. This is done by calling the uploadWebsite target, and passing the environment settings as target parameters:

<project name="myWebsite">

   <property file="myproject.build.properties" />

  <target name="uploadWebsiteToTest">
     <antcall target="uploadWebsite">
       <param name="ftp.host"     value="${ftp.test.host}" />
       <param name="ftp.username" value="${ftp.test.username}" />
       <param name="ftp.password" value="${ftp.test.password}" />
       <param name="ftp.folder"   value="${ftp.test.folder}" />
     </antcall>
  </target>

  <target name="uploadWebsiteToProduction">
     <antcall target="uploadWebsite">
	     	<param name="ftp.host"     value="${ftp.production.host}" />
     		<param name="ftp.username" value="${ftp.production.username}" />
     		<param name="ftp.password" value="${ftp.production.password}" />
     		<param name="ftp.folder"   value="${ftp.production.folder}" />
     </antcall>
  </target>

  <target name="uploadWebsite">
   <ftp server="${ftp.host}"
         userid="${ftp.username}"
         password="${ftp.password}"
         remotedir="${ftp.folder}">
      <fileset dir="c:/xampp/www/myproject">
          <exclude name="uploads/**/*.*" />
          <exclude name="debug/**/*.*" />
          <exclude name="temp/**/*.*" />
       </fileset>
    </ftp>
  </target>
</project>
                                    
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:

Select allOpen in new window


 
To conclude this section, we need to make the new targets run able by adding additional BAT files (or bash scripts). Note that you can easily upgrade the setup to include as many environments as you like, by adding properties, targets and BAT or bash scripts.

[uploadWebsiteToTest.bat]
c:/Apache-ant/bin/ant.exe -f mywebsite.build.xml uploadWebsiteToTest

[uploadWebsiteToProduction.bat]
c:/Apache-ant/bin/ant.exe -f mywebsite.build.xml uploadWebsiteToProduction
                                    
1:
2:
3:
4:
5:

Select allOpen in new window





5

Including some optimizations


With a basic understanding on how ANT works (we can use it to copy some files, re-use code, use properties), we have just scratched the surface of what automated deployment can do for web development projects. This section will show a basic process which probably benefits all web projects: Javascript and CSS optimization.

There are many different techniques you can use to improve your website's performance. An easy to implement optimization is to minimize your CSS and Javascript automatically as part of the deployment process. Using the ANT script the development files will not be affected, but the scripts on the live website will always be compact and tidy. The key to minifying Javascript and CSS files is a compressor tool. Yahoo provided the web development world with their great YUICompressor (http://developer.yahoo.com/yui/compressor/). Using the YUI compressor we can take any CSS or Javascript file and minify (compress and cleanup) them:

<!-- We need to know where the yuicompressor is located -->
<property name="yui.jar" value="path/to/yuicompressor-2.4.2.jar" />

<!-- @param yui.src  The source file
<!-- @param yui.dest The name of the minimized file -->
<!-- @param yui.type Use "css" or "js" -->
<target name="yuicompress">
		<java jar="${yui.jar}" fork="true">
			<arg value="-v" />
			<arg value="-o" />
			<arg value="${yui.src}" />
			<arg value="--type" />
			<arg value="${yui.type}" />
			<arg value="--line-break" />
			<arg value="60" />
			<arg value="${yui.dest}" />
		</java>
</target>
                                    
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:

Select allOpen in new window



By having this target in our script we can now start to compress files. To make sure we don't accidentally overwrite our source files, we first copy the tree of source files to a temporary folder (often referred to as the build directory). Inside the build directory the optimizations are performed, leaving the source files unharmed, after which the optimized files are uploaded to the servers.

  <property name="build.dir" value="build" />

  <target name="build" depends="clean">
    <!-- Make sure the build directory exists -->
    <mkdir dir="${build.dir}">
    
    <!-- Copy our files to create a build set -->
    <copy todir="${build.dir}">
      <fileset dir="c:/xampp/www/myproject">
      	<exclude name="uploads/**/*.*" />
      	<exclude name="debug/**/*.*" />
      	<exclude name="temp/**/*.*" />
      	<exclude name="build/**/*.*" />
      </fileset>
    </copy>    
    
    <!-- Start optimizing -->
    <antcall target="yuicompress">
      <param name="yui.src"  value="${build.dir}/scripts/main.js" />
      <param name="yui.dest" value="${build.dir}/scripts/main.js" />
      <param name="yui.type" value="js" />
    </antcall>

    <antcall target="yuicompress">
      <param name="yui.src"  value="${build.dir}/css/styles.css" />
      <param name="yui.dest" value="${build.dir}/css/styles.css" />
      <param name="yui.type" value="css" />
    </antcall>
  </target>

  <!-- An extra target we can use to cleanup before starting a fresh build -->  
  <target name="clean">
    <delete dir="${build.dir}" />
  </target>
                                    
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:

Select allOpen in new window




6

Putting it all together


We know how to upload and how to do some optimizations by using a temporary build folder. The final step for this tutorial is bringing it all together by showing some additional ANT methods. In our original multi-environment buildscript we used the uploadWebsiteToTest and uploadWebsiteToProduction targets to call the generic uploadWebsite target using the environment specific parameters. Because we want to insert the optimizations from the previous section we copy the build target and change the uploadWebsite to include it:

<target name="uploadWebsite" depends="build">
 <ftp server="${ftp.host}"
       userid="${ftp.username}"
       password="${ftp.password}"
       remotedir="${ftp.folder}">
    <fileset dir="${build.dir}" />
  </ftp>
</target>  
                                    
1:
2:
3:
4:
5:
6:
7:
8:

Select allOpen in new window



Notice the depends attribute on the target name? This is ANT's way of saying "We need to run the 'build' target every time before we run 'uploadWebsite'".

So by starting our uploadWebsiteToTest/uploadWebsiteToProduction we actually get the following targets run one after another:

1. uploadWebsiteToTest / uploadWebsiteToProduction
2. cleanup
3. build
4. uploadWebsite

You are probably wondering where the 'cleanup' target came from? It was added as a "depends" attribute to "build", just like the "build" target was added before the uploadWebsite target.

By now you can imagine that using just a basic set of ANT calls you have a very powerful deployment, just a mouse-click away.

Think of how powerful your scripts could get if you added:

- Automatically set your website in 'maintenance' mode by uploading a maintenance.txt to your server using an additional <FTP> task and deleting it at the end of your deploy.

- Automatically create a 'mywebsite-{currentdate}.zip' file in your backup folder by using ANT's <tstamp> and <zip> tasks

- Combine all those jQuery libraries into a single (compressed) file using ANT's <concat> with the 'yuicompress' target

- Call a diagnostics or cache cleaning PHP script on your server after FTP-ing, using ANT's <get> task.

- Mail your test team automatically at the end of your test deploy using ANT's <mail> task.

- Strip out debug sections in PHP, CSS and Javascript using ANT's <regexplreplace>:

<?php
  /* <debug> */
  // This code is for development purposes only. Luckely ANT removes it in our build
  set_time_limit(0);
  ini_set('display_errors','1');
  error_reporting(E_ALL);
  /* </debug> */
?>
[code]

[code]
<script type="text/javascript">
  /* <debug> */
  if(typeof console == "undefined") { 
    alert("Please use firebug. It will make your development life easier");
  } 
  /* </debug> */
?>
</script>
                                    
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:

Select allOpen in new window



The possibilities are numerous and the time invested in setting up a good build and deploy script are probably returning on their investment in as little as four or five runs.

Asked On
2009-05-15 at 01:37:09ID644
Tags

php

,

ant

,

yui

,

deployment

,

css

,

javascript

Topic

Miscellaneous Web Development

Views
4228

Comments

Add your Comment

Please Sign up or Log in to comment on this article.

Join Experts Exchange Today

Gain Access to all our Tech Resources

Get personalized answers

Ask unlimited questions

Access Proven Solutions

Search 3.2 million solutions

Read In-Depth How-To Guides

1000+ articles, demos, & tips

Watch Step by Step Tutorials

Learn direct from top tech pros

And Much More!

Your complete tech resource

See Plans and Pricing

30-day free trial. Register in 60 seconds.

Loading Advertisement...

Top Misc Web Dev Experts

  1. COBOLdinosaur

    144,341

    Master

    0 points yesterday

    Profile
    Rank: Genius
  2. Ray_Paseur

    142,428

    Master

    3,800 points yesterday

    Profile
    Rank: Savant
  3. jason1178

    102,330

    Master

    0 points yesterday

    Profile
    Rank: Genius
  4. DaveBaldwin

    76,853

    Master

    2,200 points yesterday

    Profile
    Rank: Genius
  5. ve3ofa

    50,168

    Master

    0 points yesterday

    Profile
    Rank: Genius
  6. nap0leon

    45,060

    0 points yesterday

    Profile
    Rank: Sage
  7. mplungjan

    45,026

    0 points yesterday

    Profile
    Rank: Savant
  8. leakim971

    33,300

    0 points yesterday

    Profile
    Rank: Genius
  9. ChrisStanyon

    28,132

    0 points yesterday

    Profile
    Rank: Sage
  10. tommyBoy

    26,968

    0 points yesterday

    Profile
    Rank: Genius
  11. Tiggerito

    26,204

    0 points yesterday

    Profile
    Rank: Sage
  12. kozaiwaniec

    19,800

    0 points yesterday

    Profile
    Rank: Guru
  13. shalomc

    19,268

    0 points yesterday

    Profile
    Rank: Genius
  14. LZ1

    17,720

    0 points yesterday

    Profile
    Rank: Genius
  15. webmatrixpune

    17,668

    0 points yesterday

    Profile
    Rank: Guru
  16. padas

    16,992

    2,000 points yesterday

    Profile
    Rank: Wizard
  17. sammySeltzer

    16,568

    0 points yesterday

    Profile
    Rank: Genius
  18. Gertone

    16,100

    0 points yesterday

    Profile
    Rank: Genius
  19. hielo

    15,700

    0 points yesterday

    Profile
    Rank: Savant
  20. singleton

    14,400

    0 points yesterday

    Profile
    Rank: Guru
  21. kaufmed

    14,376

    0 points yesterday

    Profile
    Rank: Genius
  22. paulmacd

    13,998

    0 points yesterday

    Profile
    Rank: Genius
  23. StingRaY

    13,668

    0 points yesterday

    Profile
    Rank: Wizard
  24. ahoffmann

    13,608

    0 points yesterday

    Profile
    Rank: Genius
  25. sudaraka

    13,000

    0 points yesterday

    Profile
    Rank: Sage

Hall Of Fame