Posts tagged with “build”

Ant Build Templates: The Script

This is the sixth and final post in a series of posts meant to outline my Ant build script template. If you’re interested, it may be helpful to read the first five:

  1. Prelude
  2. Environment
  3. Process
  4. Why Two Files?
  5. External Tasks

It took entirely too long to get here, but here it is, the scripts themselves. I was trying to decide what I should write to accompany these scripts, but the truth is, I’ve probably written too much already. There may be some properties or tasks that could stand for some additional clarification, but I think both files are pretty well documented so I’m just going to set them loose on the world. Most questions are probably answered either in the script documentation itself or in one of the previous posts.

To use this script:

  1. Ensure that Ant is correctly installed. Yeah, I know it’s obvious, but if I didn’t say it you just know I’d get questions.
  2. Ensure that the required external tasks are installed.
  3. Download build.properties.sample and build.xml to any directory, but keep both files in the same directory.
  4. Copy build.properties.sample to build.properties.
  5. Modify the newly created build.properties file, as required.
  6. Modify build.xml, as required.
  7. Execute, execute, execute.

Feel free to ask questions or make suggestions either in the comments for this post or by using the contact form.

Ant Build Templates: External Tasks

This is the fifth in a series of posts meant to outline my Ant build script template. If you’re interested, it may be helpful to read the first four:

  1. Prelude
  2. Environment
  3. Process
  4. Why Two Files?

So at this point in this thing that I’ll loosely call a series, I’ve talked a lot, but in the put-up-or-shut-up debate, I’m still leaning heavily towards the shut up side. Today I hope to move that needle, at least a little bit, in the other direction.

Ant is the cat’s meow. The bee’s knees, if you’d rather. But then, I probably don’t need to sell anyone on the fact that I’m a fan. What Ant is not, though, is perfection. At least not without help. My build script requires three external task libraries to function properly. Technically, it’s two external libraries and one external dependency for a native task library, but at least we’re starting to talk code. First, a little information about the required tasks and then some information about making them work in the build script.

SSH and SCP

Fundamental to any build that includes deployment is the ability to move resources from one server to another. Unless absolutely necessary, I prefer to use SCP or, at the very least, SFTP. Both of these are better than FTP, but my infrastructure supports SCP, so that’s what I use. My build template also requires SSH, the protocol on which SCP is built, so there’s a nice two-for-the-price-of-one effect. Ant ships with SSH and SCP tasks but, perhaps counter intuitively, not with the library required to actually execute those tasks, jsch, a pure Java implementation of the SSH2 protocol.

There’s more information in a post I wrote over a year ago, but be sure to download the 0.1.29 version even though it’s not current. I’ve tried every version between 0.1.30 and 0.1.33 and they don’t work. Versions above 0.1.33 may work, but I can vouch for the fact that 0.1.29 works so it may be worth sticking with that.

SvnAnt

For years now, I’ve been using Subversion as my source control solution. I’m taking some early stabs at learning git, but I’m still primarily a Subversion user. It’s not hard to figure out, I’m sure, that SvnAnt is a collection of Ant tasks for interacting with Subversion. This library supports the full range of commands available with Subversion (certainly every one that I need) in addition to the ability to connect using an installed svn executable or via JavaHL.

AntelopeTasks

Antelope is a very useful – so useful that I actually think of it as critical – library of utility tasks designed to give Ant more power. The library includes conditionals, try/catch, grep, string manipulation and several other handy tasks that are used throughout my build script. Its capabilities are similar to those of AntContrib, but I think that Antelope offers more functionality and more options.

Including External Tasks

There’s an easy way to run external tasks in a build script and a hard way. I actually prefer the hard way. The easy way is to simply download the task library and extract its jar files anywhere in the system classpath. A typical approach would be to drop the jar files in the ANT_HOME/lib/ directory. The “hard” way is to extract the libraries anywhere at all and tell the script where they’re located. Sort of a lazy loading technique, I suppose. I prefer the latter method because it allows me to keep my external tasks, well, external.

I extract my external libraries to ~/Library/ant/tasks/ (again, let me state that this can be anywhere). I then set a few variables in my build.properties file:

tasklib.dir=/Users/me/Library/ant/tasks
<!--
   Libraries associated with the SvnAnt task
 -->
tasklib.svnant.tasks=${tasklib.dir}/svnant-1.0.0/lib/svnant.jar
tasklib.svnant.adapter=${tasklib.dir}/svnant-1.0.0/lib/svnClientAdapter.jar
tasklib.svnant.javahl=${tasklib.dir}/svnant-1.0.0/lib/svnjavahl.jar
<!-- 
   Antelope only has one library
 -->
tasklib.antelope.tasks=${tasklib.dir}/AntelopeTasks_3.4.2/
AntelopeTasks_3.4.2.jar

Note that any wrapping that occurred in this list of properties is a function of the limited display space on this site. Each property should appear on a single line in the properties file itself. In this code, any line that does not begin with “tasklib” (and is not a comment) is wrapped from the line above. I couldn’t think of a way to indicate that in the code without it being more, rather than less, confusing.

Once I have properties to indicate where my tasks reside, I can explicitly include them in my classpath and load the tasks by adding this code to my build.xml file:

<!-- load properties set in the build.properties file -->
<property file="build.properties" />
<!-- 
   add external library file paths to  the project classpath
 -->
<path id="project.classpath">
   <pathelement location="${tasklib.svnant.tasks}" />
   <pathelement location="${tasklib.svnant.adapter}" />
   <pathelement location="${tasklib.svnant.javahl}" />
   <pathelement location="${tasklib.antelope.tasks}" />
</path>
<!-- make the svn tasks available -->
<taskdef resource="svntask.properties"
         classpathref="project.classpath"
/>
<!-- make the antelope tasks available -->
<taskdef resource="ise/antelope/tasks/antlib.xml"
         classpathref="project.classpath"
/>

That covers SvnAnt and Antelope, but the jsch library still needs to go somewhere. I treat that one a little differently, but the difference makes sense in my head. Since jsch is an external library that fulfills a dependency for a native task, I just drop the library in my ANT_HOME/lib/ directory. There it gets picked up automatically.

Alternatively, if I plan to run builds exclusively from within Eclipse (which is often the case), I might store it in ~/Library/ant/lib/ and tell Eclipse to find it there in its preferences. To set that preference:

  1. Go to Preferences > Ant > Runtime
  2. Select the Classpath tab
  3. Highlight Global Entries
  4. Select Add External JARs
  5. Navigate to jsch-0.1.29.jar, wherever its located
  6. Click Open in the file browser dialog
  7. Click OK in the Eclipse preferences dialog)

With external libraries in place and properly added to the classpath, previously unavailable or unusable tasks are now available for use. Up next: the unveiling.

Ant Build Templates: Why Two Files?

This is the fourth in a series of posts meant to outline my Ant build script template. If you’re interested, it may be helpful to read the first three:

  1. Prelude
  2. Environment
  3. Process

If you’ve been reading this series (or any of my other Ant-related content), you may have noticed that I occasionally reference my build scripts. Plural. It’s kind of involuntary, but you may have wondered exactly how many there are. Although there’s really only one build script (per project), I have, and recommend to anyone else, an accompanying properties file. Two files that I occasionally, and inconsistently, mind you, lump together into a plural use of the word “script”.

So there it is. Two files. One is the actual Ant build script, traditionally build.xml and the other, build.properties, an external set of property definitions. I do this for exactly the same reason that I – and most other developers I know – maintain a configuration file of some sort for my applications; it’s nice to know where to go when something needs to be changed. Moreover, it’s nice to know that it’s the only place that those changes need to be made.

Build operations, especially when deployment is part of that build operation, typically require an awful lot of information – file paths, for example – about the build or deployment environments, information – think usernames – about the user running the build, sensitive information like authentication credentials or simply information about the build itself. The latter might include the project name and version or the source control revision number.

All of this information is usually, or at least could be, variable. I deploy to multiple environments and I’m not the only person in my group that can run builds. Additionally, I want developers themselves to test their own build scripts. Finally, I want build scripts to be versioned and I sure as hell don’t want to be dropping my authentication credentials into a build file and then committing those credentials to a revision all their own until the end of days. That would be bad.

Given all of this variable and/or sensitive information, I could still just throw everything directly in the build script. I have to manage and update it no matter where it goes, so the where doesn’t really matter. Um, in theory. Maybe it’ll be easier to understand when you see the file, but the build script (build.xml is much more verbose. There’s a lot of stuff going on in there. Remembering what needs to change, finding it and then changing it isn’t a trivial effort and it would have to be done for every build. No thanks.

Instead, I move the variable data out to build.properties. In addition, I store a generic version named build.properties.sample in source control. That generic version contains dummy values for most of the properties. I copy that file to build.properties in my working copy, set my source control configuration to ignore the copied file and then I can merrily go about including sensitive data without fear of an accidental commit. There are also other benefits to having a separate properties file:

  1. It contains nothing but variable values. If a property is in this file then it either is or could be variable. There’s no other stuff to wade through.
  2. Likewise, the build script itself is fixed. Nothing in there should need to be changed (unless, of course, the fundamental nature of the build changes).
  3. It’s much, much smaller than the executable script so specific properties can be found much quicker that they would be in the larger build script.
  4. Specific properties will only exist once in the properties file. They may be used any number of times in the script itself.
  5. Risk mitigation. At build time, I don’t have to touch the executable that’s actually doing all of the work. All I have to do is update the properties file and run the build.

The moral of the story: use a properties file. You’ll be glad you did. Your sanity is important so preserve it. In this case, less is not more. Two is better than one.

Ant Build Templates: Prelude

I’ve long been an Ant enthusiast and advocate for its use beyond simple Java compilation tasks. A while back, I wrote a post, available in my InstantSpot archive, describing how I employ Ant to build and deploy web applications. It was intended to be the first in a series, but additional posts just never materialized for a number of reasons. Abort.

In that post, I somewhat casually mentioned that I had created a build template that meets my needs for most projects. More people that I expected caught that casual mention and have asked me to post those templates. I’ve procrastinated in doing so, at least in part, because I didn’t feel like these scripts were ready for public consumption. They were built by me, for me and specifically to meet my needs. Not exactly stellar code, but code that functioned the way I needed it to function.

One of the things I’ve been doing over those past few months of procrastination is editing the script templates that I use. In little snippets of time between then and now, I’ve finally managed to make and test those changes. Not only have I added comments and generally gotten the code to a point where I wouldn’t be mortified to have it go public, but I’ve also tried to make the script a little more robust than the original version(s). I’ve:

  1. Added sanity checks that provide an opportunity to cancel the build before any significant damage gets done.
  2. Added a more robust backup of any existing version that already exists in the deployment environment.
  3. Included a modicum of intelligence so that the script detects its deployment environment and does the right thing based on that environment.
  4. Included a secondary path to handle upgrades in addition to new installs.

All of that said, these are not generic scripts that can be dropped in anywhere. They make a lot of assumptions that may be specific to my environment. The scripts should be (relatively) easily tailored to other environments, but should not be expected to run without modifications. To that end, I’ll build up to revealing the scripts by providing the background information that I think is necessary, important, appropriate or just plain prudent. Some of this has been covered in other posts in the archive, either here on robwilkerson.org or on InstantSpot, but bear with me. I think it’ll be helpful to have it all in one place and focused.

My goal is to write a post each day on the following topics:

  1. My Environment
  2. My Process
  3. Two Files or One
  4. External Tasks

Once I’ve provided that background, I’ll link the scripts under an MIT license. At any step along the way, I’d certainly appreciate any (constructive) input. I’d like to think that I’ve thought of everything, but I’m old enough to know better.