Showing posts with label Hudson. Show all posts
Showing posts with label Hudson. Show all posts

Thursday, January 22, 2009

Hudson Default Ant

Most Hudson configuration is self-explanatory and easy to find in the web configuration. Many props go to the developers of Hudson because it is quite easy to setup and use. However, there are a couple of things that I've found lately that don't seem to be documented in the Hudson docs.

Configuring Ant


From the Hudson dashboard, click on
  Manage Hudson -> Configure System
or you can simply navigate to
  http://your-server-here/hudson/configure

Look for the section labeled "Ant" and add your Ant installations by clicking "Add" and providing a name and the absolute path for ANT_HOME. This couldn't be simpler.

Default Ant


When you are configuring a build, you can tell Hudson which Ant you want to use. You may either use one of the named Ant installations that you previously added, or Hudson gives you the option of using the "Default Ant."

For some reason, I was thinking that I had somehow set the only Ant installation that I added as the default (since it was indeed the only one). But, this was not the case, and my build failed with this console output:

FATAL: command execution failed.Maybe you need to configure the job to choose one of your Ant installations?
java.io.IOException: Cannot run program "ant" (in directory "/home/tomcat/hudson/jobs//workspace/build")


Then, I got to looking at how to set the default Ant, and I could not for the life of me find the setting anywhere. This is because, there is NO default that can be changed from within Hudson.

If you tell Hudson to use the default Ant for a build, then it will use whatever ant it finds on the PATH. Note that I did not say that Hudson will use whatever ANT_HOME points to. Hudson must be able to find the ant command on the PATH.

In our case, Hudson runs as the user 'tomcat.'

So, if I wanted to use the default Ant for a build, I would typically solve this by setting both the ANT_HOME and PATH environment variables for the tomcat user. I would set ANT_HOME to the Ant installation that I wish to use as default, and I would then add $ANT_HOME/bin to the PATH environment variable.

What I Actually Did


Since I really didn't care to go to all that trouble of setting environment variables, I just used the named Ant instance that I had already configured in Hudson. We do not have a default Ant available to Hudson, and it's not a problem.

Wednesday, January 21, 2009

Hudson Gets an AccessControlException when starting on Ubuntu Tomcat

With fresh install of Ubuntu 8.10 I grabbed Tomcat 6 from Synaptic. Then, I dropped the hudson.war into the Tomcat webapps directory, and was greeted with an AccessControlException and a Hudson that would not start.

This is because on Ubuntu, Tomcat default installs with the Tomcat Security Manager enabled. This is probably a good thing for many installs of Tomcat, but it interferes with Hudson. When we finally found the problem, we took the lazy road and disabled the Tomcat Security. Depending on your install, this may be an unsafe decision. I would check the Tomcat documentation before doing this if your server is externally exposed. In our environment, the build server is on a completely trusted network. So, we didn't care much.

Here is the stack trace that is displayed when first trying to browse to the Hudson app:


HTTP Status 500 -

type Exception report

message

description The server encountered an internal error () that prevented it from fulfilling this request.

exception

javax.servlet.ServletException: Error instantiating servlet class org.kohsuke.stapler.Stapler
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:433)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
java.lang.Thread.run(Thread.java:636)

root cause

java.lang.ExceptionInInitializerError
org.apache.commons.beanutils.ConvertUtilsBean.(ConvertUtilsBean.java:130)
org.kohsuke.stapler.Stapler.(Stapler.java:659)
sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
java.lang.reflect.Constructor.newInstance(Constructor.java:532)
java.lang.Class.newInstance0(Class.java:372)
java.lang.Class.newInstance(Class.java:325)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:433)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
java.lang.Thread.run(Thread.java:636)

root cause

java.security.AccessControlException: access denied (java.util.PropertyPermission org.apache.commons.logging.LogFactory.HashtableImpl read)
java.security.AccessControlContext.checkPermission(AccessControlContext.java:342)
java.security.AccessController.checkPermission(AccessController.java:553)
java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
java.lang.SecurityManager.checkPropertyAccess(SecurityManager.java:1302)
java.lang.System.getProperty(System.java:669)
org.apache.commons.logging.LogFactory.createFactoryStore(LogFactory.java:320)
org.apache.commons.logging.LogFactory.(LogFactory.java:1725)
org.apache.commons.beanutils.ConvertUtilsBean.(ConvertUtilsBean.java:130)
org.kohsuke.stapler.Stapler.(Stapler.java:659)
sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
java.lang.reflect.Constructor.newInstance(Constructor.java:532)
java.lang.Class.newInstance0(Class.java:372)
java.lang.Class.newInstance(Class.java:325)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:433)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
java.lang.Thread.run(Thread.java:636)

note The full stack trace of the root cause is available in the Apache Tomcat/6.0.18 logs.



This was fixed by changing:

/etc/default/tomcat6


And setting the following property:

# Use the Java security manager? (yes/no, default: yes)
# WARNING: Do not disable the security manager unless you understand
# the consequences!
#TOMCAT6_SECURITY=yes
TOMCAT6_SECURITY=no


Note that we left the commented example in place for future reference. I hope this helps someone else. Mostly, I'm hoping that by writing this down, I will remember this in the future or at least be able to find the solution quicker.

Go forth and write tests...

Thursday, December 11, 2008

Publishing Build Artifacts With Hudson

Tonight, I found yet another reason to love the Hudson continuous integration server. Publishing build artifacts is way easy. What's better, the latest artifacts are available under a static link. So, it's easy to set a bookmark and always have the latest output available without digging through the server.

I've setup publicly visible builds for EasySpec along with the Groovy example and Java example projects. All of these projects use EasySpec for Behavior Driven Design. A major component of BDD is having the latest behavior report available. So, I have included a build target named "report" in each of these projects. This target simply runs EasySpec to generate the behavior report into a known location in the workspace.

Let's take the Groovy example and walk through it. After every checkin, the Hudson build does

gant clean test report

This cleans the working copy, then compiles everything, runs the tests, and finally generated the EasySpec report. Relative to the working copy base, the report ends up in build_output/reports/EasySpec/index.html

To publish this report, only a couple of simple steps are required. First, go to the project configuration page for the build that you wish to publish artifacts from. In this case, that's Hudson/GroovyExample/Configure. Then, find the checkbox, "Post-build Actions / Archive the artifacts" Enter the relative path of the artifacts that you wish to publish. In this case, that's "
build_output/reports/EasySpec/index.html" Click "Save" and it's all done.

Now, everytime this project builds successfully, the latest EasySpec report is published to a constant URL. If you want, checkout the latest example EasySpec report.

I love Hudson