14 Jan 2011

SBT builds with Hudson

We build our Lift applications with Hudson Jenkins, and we're in the process of converting some projects from Maven to SBT.  This is mostly straight-forward but there are a couple of non-obvious things you might need to know.

Running SBT

There's the start of a Hudson SBT plugin, but at the moment we're running SBT from Hudson by simply shelling out to execute the SBT command.

To do this, install SBT somewhere (.hudson/tools/sbt for us) and then create a new free-style Hudson job and add a build step of "Execute Shell".  We have:

/usr/lib/jvm/java-6-sun/bin/java -Dsbt.log.noformat=true -jar /home/hudson/.hudson/tools/sbt/sbt-launch-0.7.4.jar clean update test package

That's it. Your project will build.

(The -Dsbt.log.noformat=true part turns off the SBT colour formatting which you want off otherwise your build file will contain weird formatting control characters).

Controlling the WAR name

By default the WAR filename will be something like foo-scala_2.8.1-1.0.war, which is fine, except because of the way we deploy we wanted to drop the Scala version number.  That's easy to do, and you can configure it in your SBT project file:

override def artifactID = "foo"

Adding build information to your MANIFEST.MF

In our apps we like to include the Hudson build number in the footer of every page. We do this by using the fact that Maven Hudson builds include the build number in the META-INF/MANIFEST file.  SBT doesn't.

Fortunately, the fine Scala team at The Guardian have published an SBT plugin to add information to the MANIFEST.  The install details are in the README.  

Hudson sets the build number as an environment (shell) variable.  To pick these up via the plugin we just set them as -D parameters:

/usr/lib/jvm/java-6-sun/bin/java -DBUILD_NUMBER=$BUILD_NUMBER -DGIT_BRANCH=master -DJOB_NAME=$JOB_NAME -Dsbt.log.noformat=true -jar /home/hudson/.hudson/tools/sbt/sbt-launch-0.7.4.jar clean update test package

When that executes:

/usr/lib/jvm/java-6-sun/bin/java -DBUILD_NUMBER=212 -DGIT_BRANCH=master -DJOB_NAME=FooHudsonJob  -Dsbt.log.noformat=true -jar /home/hudson/.hudson/tools/sbt/sbt-launch-0.7.4.jar clean update test package

Our SBT project file picks up these System properties:

def revision = systemOptional[String]("GIT_BRANCH", "DEV").value
def build = systemOptional[String]("BUILD_NUMBER", "DEV").value
def versionName = systemOptional[String]("JOB_NAME", "DEV").value

The result is a WAR file with a META-INF/MANIFEST.MF file that looks something like this:

Manifest-Version: 1.0
Revision: 
Implementation-Title: foo-1.0
Title: foo-1.0
Implementation-Version: FooHudsonJob
Branch: master
Date: Fri Jan 07 14:41:51 UTC 2011
Build: 212

Test results

With what we have at the moment if a test fails, the build fails.  This is good.

What we don't have is the nice graph of tests.  If you want that, take a look at  Christoph Henkelmann's Blog:  How to build sbt projects with Hudson and integrate test results.

For us, the next step is adding in the Undercover code coverage reporting tool instead. 

 

 

2 Dec 2010

Running SBT (or any shell command) from Eclipse

(download)
Mostly when I'm writing code I'm in the Scala IDE for Eclipse, with a separate terminal window containing SBT running ~test-quick or jetty-run. But flipping back and forth between terminal and Eclipse is non-optimal, so I went digging for Eclipse + SBT integrations.

There are a few mentioned on the SBT site, but I realized all I needed was a shell prompt as a view in Eclipse and I'd be happy.  And of course it exists already as "Target Management Terminal", part of the Galileo update site.

  1. Eclipse > Install New Software....
  2. From "Work with:" select Galileo (or whatever's appropriate for your version of Eclipse).
  3. Type "terminal" in the search box, and select Target Management Terminal.
  4. Go through the download, restart process.
  5. Eclipse > Preferences and search for Terminal if you want to invert the colours (I did).
  6. Window > Show View > Other and select Terminal to show the Terminal view in Eclipse.
  7. Click the green connect button and set up the type of terminal you want (ssh to localhost in my case, and I'm prompted for a password).
  8. Login, you have a shell, do what you want, such as cd into your project and run SBT.

Probably totally obvious, but I missed this trick of having access to a shell from Eclipse.

11 Nov 2010

Intro to the Simple Build Tool at LSUG

John at the London Scala User Group ran "LSug Workshop: Up-close and personal with SBT" yesterday at Skillsmatter.  It was a kind of mini-unconference, and I contributed an introduction to SBT.  The video above is the first half of a screen recording I made, and it continues into part 2 on Youtube.

I learnt a lot from the evening on how others use SBT, and from Maciej Matyjas talk on giter8 and plugins (including what looks like a wonderful plugin to Posterous). Phil Wills showed us how to create a SBT plugin, and that doesn't look too scary now.

Skillsmatter should post video of the evening at some point, and Chris Tuner live blogged the event.

 

30 Oct 2010

Screencast on using Lifty

Lift development has moved on from the depressingly long Maven commands to start a new project.  I made the above screencast to show the simple build tool that I'm growing fond of, and an add-on for SBT called Lifty that makes it easy to create Lift projects.

It took me a couple of attempts to make the video, so of course many of the automatically downloaded libraries were locally cached.  It'll take longer for you if you're starting from scratch, but not as long as I'd expected. For some reason (possibly imaginary) the SBT downloads for Lift seemed much smaller, and consequently faster, than I'm used to with Maven. YMMV.

If you want to know more about Lifty, check out Mads Hartmann's talk from the Scala LiftOff London.  There's also an "Up-close and personal with SBT" workshop from the London Scala User Group in the evening on 10 November 2010 (free, just sign up).

Going beyond the screencast

I don't use SBT projects exactly as I've shown in the screencast: I use JRebel and the Scala IDE for Eclipse.

"JRebel maps your project workspace directly to your running application. When a developer makes a change to any class or resource in their IDE the change is immediately reflected in the application, skipping the build and redeploy phases".  And the Scala IDE compiles on save, so the combination gives me "press save in the IDE, hit reload in the browser" development.

I've paid for the enterprise version of JRebel as I have legacy Java apps to live with, but for pure Scala/Lift development you can pick up a free Scala license of JRebel — and you should. 

The configuration is just in two places.  For SBT itself, modify the sbt launch script to include the JRebel magic.  I have:

export REBEL_HOME=/opt/zeroturnaround/jrebel
export REBEL_JAR=$REBEL_HOME/jrebel.jar 
export REBEL_LIC=/opt/zeroturnaround/javarebel.lic 
export WITH_REBEL="-Drebel.license=$REBEL_LIC -noverify -javaagent:$REBEL_JAR"
java $JAVA_OPTS -XX:MaxPermSize=256m -Xmx512M $WITH_REBEL -jar `dirname $0`/sbt-launch.jar "$@"

The other change is to prevent Jetty from restarting itself on change.  That's an edit to your project/build/Project.scala file (or whatever you called it):

override def jettyWebappPath = webappPath
override def scanDirectories = Nil

That's all, and when you fire up SBT and run the jetty command, you have a pretty efficient working environment.

Oh, to generate the Eclipse project files, there are a few options listed on the SBT wiki, but I'm currently trying SbtEclipsify.

Richard Dallaway's Posterous

Director at Spiral Arm Ltd. We build stuff using Scala+Lift, offer consulting & create new projects. I live in Brighton, UK.