Thursday, June 26, 2008

DVCS? I'm sold

As a casual reader of DVCS advantages like git and mercurial, I think I am ready. Motivated by a great article shared by Kit Plummer, I am sold and ready to start using it. Unfortunately, it's probably not going to happen any time soon at work until a) IT supports a mercurial server like they do svn or b) I start a new project were new decisions like language (ruby/groovy) and source control can be made and I'm not hindered by "we are already using svn, why switch" or "I just got comfortable with svn" or "every team member would have to learn mercurial". Reminds me of my favoriate Zed Shaw quote from this article:

"This folks is the classic problem with programmers today. They absolutely refuse to learn anything new unless they can see that learning the new hotness will give them an immediate 200% boost in salary or get them hot honeys at the next conference."
Now that I see that Hudson has a mercurial plugin and Jira does as well, then technically speaking, I can't think of any other reason not to switch.

Sunday, June 15, 2008

How to FTP artifacts in maven2

If there is one word a team should keep in mind when building a CI (Continuous Integration) environment it's Automate, Automate, and Automate (see Production-ready software, on-demand). Most teams, including mine currently, performs their releases manually; creating the branch, incrementing the POMs, uploading the artifacts to a repository, etc. This is one reason I wrote about using the maven release plugin to automate this process. I will say that having a CI server such as Hudson only helps in making automation easier.

My team also creates an official release about once every two months and supports that release anywhere between 1-2 weeks to months. It's also pretty intense during those 1-2 weeks when we have co-workers on-site installing and supporting our software in a completely different timezone and with limited access to the phone and internet.

Over the weekend I wrote a simple maven2 pom to help automate FTP'ing the release artifacts to an FTP server. Last week we created a branch and a job in hudson that builds that branch. After it successfully builds we use the assembly plugin to package our EAR, documentation, SQL files, and everything else into a single folder. In the past, a guy would then manually copy these files to the FTP server, which was used by the on-site team to download the latest artifacts containing improvements and bug fixes. This release we wanted to automate this step to increase our response time for the on-site team.

First Try using GMaven Plugin
I knew that Ant had an FTP task and I love doing Ant in Groovy because its so much easier so I decided to first try the GMaven plugin (maven groovy plugin). It was a short trip since the FTP task is an optional library in Ant and you have to include the jar in your POM, but I could never get the gmaven plugin to recognize the dependency (see MGROOVY-152). Look at the Jira issue attachments if you want to reference my POM as an example. It's too bad I couldn't get this to work because it would have been sweet:

log.info('Entering in ftp script')

def config = [server: 'localhost',
remotedir: '/home/jlorenzen/ftptest',
user: 'ftp',
password: 'ftp'
];

ant.ftp(config) {
fileset(dir: '
/home/jlorenzen/Documents')
}

Second Try Maven AntRun Plugin
I was finally able to get this to work using the maven-antrun-plugin. Here is my POM
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>ftp</id>
<phase>install</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<ftp server="localhost"
remotedir="/home/jlorenzen/ftptest"
userid="ftp"
password="ftp">
<fileset dir="/home/jlorenzen/Documents"/>
</ftp>
</tasks>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>ant</groupId>
<artifactId>ant-commons-net</artifactId>
<version>1.6.5</version>
</dependency>
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>1.4.1</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>