Thursday, February 4, 2010

Forget Part 1 - done right Groovy don't need a part 2

I had put this project on the shelf for time. New solution is half the code, requires only the one script file, and does even more.
Groovy's so flexible I can see where this could be condensed further, but then I'd have to double the comments to remember what it's doing next time I go to modify it.

def cruiseServer = 'http://build.server.com:9000'
def uploaddir = "user@123.123.123.123:/path/to/deployment/dir"
def downloaddir = 'D:\\localbuild\\downloaddir\\'

def rssPath = '/cruisebuild/rss/'
def artifactPath = '/cruisecontrol/artifacts'

//The common list of assets to download. With this list structure I can just comment out
// any asset to skip over each release or do the full download. Also can control if I want latest
// and greatest or a specific tested version.
def projects = [
//['comment out', 'assets not needed', 'latest'],
['Build-Project1', 'assetname.ear', 'latest'],
['Build-Project2', 'assestname.war', '12.12.1002']
]
//for the identified collection, do the download
projects.each() { project, ear, version ->
//get rss feed into a navigable object
def rssFeed = new XmlParser().parse( cruiseServer + rssPath + project).channel[0]
//get either the latest good build OR a specific version number
def passeditem
if ('latest'.equals(version) {
passeditem = rssFeed.item.find{ it.description.text() == 'Build passed' }
} else {
passeditem = rssFeed.item.find{ it.link.text() =~ version )
}
//link in RSS feed goes to the cruisebuild details, but what I need is asset download path.
def link = passeditem.link.text()
//reprocess the build number from link based on regex pattern for 4 sets digits w/ dot separator.
def buildMatcher = ( link =~ /\d+[.]\d+[.]\d+[.]\d+/ )
def buildNo = buildMatcher[0]
//Then the crucial info is the cruisebuild ID 14 digit number
def matcher = ( link =~ /\d{14}/)
def assetNo = matcher[0]
//so I can publish which ears were deployed
println "${project}.ear (V-${buildNo})"
//Now for the cool automatic download
def srcLoc = "${cruiseServer}${artifactPath}${project}/${assetNo}/${ear}"
def file = new File(dwnldDir + srcLoc.tokenize("/")[-1])
def out = new BufferedOutputStream(new FileOutputStream(file))
out <<>
//publish file size to confirm end of download
println file.length()
out.close()
} // end of download closure

//ah the miracle of AntBuilder - my files loaded straight to server after download
ant = new AntBuilder()
//note: in eclipse scp requires some path configuration.
//google the error you get when this runs to find correct jars for your version.
ant.scp( todir: "${uploadDir}",
password: "opensesme",
trust: "true" {
fileset(dir:"$dwnldDir") {
//this little closure ensures I only upload new assets.
//pretty cool to be able to mix builder syntax and script code.
projects.each() { project, ear, version ->
include(name: "$ear")
} //end projects.each closure
} // end fileset closure
} //end ant.scp closure