Jan 29 2010

iPad

Tag: Geekstuff, Ranting and Reflections, iphoneJoe @ 8:22 pm

I work, live, and play in technology. My job today is in technology – doing software to run software (a bit cyclical, yes)  - operations, in short. Almost everyone surrounding me at work is technical, smart, detailed, and very, very into computing and what it can do. To be honest, I’m mostly surrounded at work by people who happily use and understand Windows as a common operating system.

They’ve all been buzzing about the iPad. Shit, anyone in technology has been buzzing about it. Microsoft and HP (or laptop/tablet vendor of choice) had a decade to break this code and didn’t manage it. I’ve been hearing almost exclusively around why Apple fucked up, blew it, and why the Kindle and netbooks will continue to rule the roost. I won’t even go near the whole “Flash thing”.

I think they’re all dead fuckin’ wrong. Pardon the vuglarity, or not, as you please. It’s needed on this one. The iPad is a sign post. A marker of where we’re heading, and a sign of the change to come. I saw the preso, reading a few IRC channels and frantically refreshing web pages – and my thought was “Holy shit! I’m seeing something just like the first copy of NCSA Mosaic running on a Mac. This is going to change the world…”

And I found that I was completely unable to articulate this in any way that I could present to my coworkers. I didn’t bother demanding they listen, or that I was right, or any of that nonsense. I see it coming – they will too, eventually. In the past day or two, however, some very articulate fellows have done an amazing job putting down into text what I couldn’t. If you haven’t read these – do.

Thanks gents – I appreciate the words and thoughts – especially since I couldn’t seem to articulate them.


Jan 24 2010

Pinax cheat sheets

Tag: Geekstuff, Ranting and Reflections, djangoJoe @ 5:12 pm

I have a few friends that I’m bringing up to speed pretty quickly on Django. The basics are going well, and I’m providing the foundations for the effort. To take advantage of all the good stuff out there, I’ve started diving deeply into Pinax, and then wrapping some automation around it with Fabric to make it really easy to work on new apps and projects.

That’s the whole reason I posted gist 284927 yesterday on setting up a remote app server for a pinax project with Fabric.

The biggest hurdle that I have with the fellows I’m bringing up to speed is them understanding what’s IN the project that I’ve already slapped down. Even a basic pinax project has a huge amount of complexity for the newer django developer – it’s pretty overwhelming. To try and mitigate that complexity, I’ve started a side project making Pinax cheat sheets. (http://github.com/heckj/pinax_cheat_sheets).

This is not intended to replace Pinax documentation, and in fact I hope that I can eventually tweak these around and put them into the pinax project. I have a huge respect for it (and I use it), so here’s a little bit of detail for contributing back.

I am very happy to take on any changes, edits, updates, etc – from others. There’s a lot of folks who’ve worked very hard to build all these components, and I’m not writing from the perspective of the creator, but of the “code spelunker”. I’m sure I’ll get some of this stuff wrong – so if you see something, please let me know.

I’d ideally love to receive contributions in the form of pull requests from GitHub. Just fork that project, make your edits, and when you’ve pushed them back up – send me a pull request. I don’t promise that I’ll include everyone’s contributions, but to be honest I don’t expect to be too darn picky.

I’ve written the cheat sheets in markdown, mostly because I know it, and secondarily because it renders nicely as HTML when viewed through GitHub.

The start of the project has the following cheat sheets up:

I have a bunch more external apps to go before I hit the internal Pinax apps. I’m working through everything that’s included in a Pinax “basic_project”.

And then the internal apps:

  • basic_profiles
  • account
  • signup_codes
  • about
  • django.contrib.admin

Jan 23 2010

Using fabric to deploy a Pinax project

Tag: Geekstuff, Ranting and Reflections, djangoJoe @ 5:30 pm

I spent the better part of this morning screwing around with Fabric to get even a basic deployment working correctly with Pinax. I may be doing this horrifically backwards… Since I finally nailed something that worked for me and I couldn’t find much out there on the web, I wanted to post up a result so that other folks could use/riff etc.

http://gist.github.com/284927

Please feel free to replicate/clone/use/etc whatever to your heart’s content. It’s built around deploying a Pinax 0.71 project clone that also uses South for schema migrations, and the project is housed in BitBucket.

The other fabric file I found that’s referenced frequently was a part of the inspiration here: http://gist.github.com/212366. It’s a fabfile that’s intended to provide some simple rollback and expects to be used from GitHub – and has some really nice documentation associated with it. Maybe I’ll work on mine to add some of that doc… but mostly I’m just making it available as is.


Dec 30 2009

Contributing back

Tag: Geekstuff, Ranting and Reflections, railsJoe @ 9:25 pm

In my Redmine investigations that I’ve been writing about recently, I ran across an issue between a plugin and the latest version of Redmine. I really don’t know the first thing about about rails – I can read it, but I can’t always make sense of it, and I certainly don’t know the “expected” bits (some might call constraints, others I’ve heard call it “the magic”). So when I took the fix posted to the forums, slapped it up in a Github fork, and submitted a fork request – I had no idea if it would be wanted.

I’ve got to say that I’m incredibly gratified that it was accepted back into the main branch. All I really did was make it darned easy to pull in a patch someone else created, but even doing something simple like that I think made a difference.

I’m a bit more proud of the patches that I submitted to pyrrd (a real fix and some better doctests). Those were, honestly, harder – but really only because I found the Launchpad interface and Bzr to be harder to navigate and use than Git and Github. (I still assert that the best thing about Git is Github). Duncan (maintainer of pyrrd) prefers that system, so I created a branch there and submitted the patches. Didn’t quite do it 100% for him – I bundled two fixes into the same branch instead of a branch/fork per fix – but in the end he took them in and I think appreciated the help.

A little side light was helping out Ned with my writeup of using Hudson for python/django projects. Chris Heisel took it that one step farther and walked through using Hudson for Django projects as well. So I ended up contributing and seeding a bigger conversation with that too.

There have really been few projects that I’ve provided back to this year – it’s been a busy year at work, but much of it has been more people and process oriented rather than making code happen. Still, contributing back in whatever areas gives me a boost – and at the end of the year I like to look back and think that even in some small ways, I made something available for others.

What’s this coming year going to bring? Heh – who knows. I’ve got a few things rolling (at work and outside of work) that should prove to be really interesting. One is an open source monitoring project, although at the moment in the very, very early stages. The others I’ll have to leave off for talking about another time.


Dec 29 2009

Redmine and a scrum board

Tag: Geekstuff, Ranting and Reflections, railsJoe @ 11:11 am

After a few days of playing and working with Redmine and some plugins, here’s where I’ve ended up:

I tried the redmine scrumdashboard plugin (http://github.com/thus/redmine-scrumdashboard-plugin), but was never able to get it even functional. The whole thing stacktraced under 0.8.7 and I’m just too ill informed on rails to be able to effectively debug it. I did log it as an issue (http://github.com/thus/redmine-scrumdashboard-plugin/issues#issue/6) though.

While I was working with the backlog plugins, I found a few quirks. In one case, it wasn’t editing anything from the backlog tab in Redmine. That turned out to be an issue with a recent Redmine feature related to cross site forgery protection. There were a couple of posts in the plugin forum and some associated bugs at the bug tracker. On the forums,  Eric Doughty-Papassideris suggested a solution, so I forked up the github project and posted that fix for anyone to use. Even made a pull request back to the master project – don’t know if it’s 100% the right thing to do for the solution, but it does do the trick.

The backlog plugin, while working, did have a quirk that I never quite identified. I enabled the plugin and slapped in a bunch of issues, and one of them caused the plugin to render in a really odd way. I suspect it wasn’t defending well against stupid parameters, but I wasn’t ever able to figure out why the thing was rendering all whacked. I ended up deleting that example project, but on another it appeared to work correctly.

Of the two, the scrumdashboard plugin appears to be in a “quiet phase” – little commit activity and I suspect it’s running afoul of recent Redmine updates and features. Backlog seems to be keeping up better, so I expect that’s where we’ll focus our usage.

Update:

One thing that I found surprising – If you’re using Redmine with Mercurial, the redmine instance wants to have a mercurial repository *local* on that machine – you can’t point it at a remote mercurial repository and have it function correctly. It only wants to read off the local filesystem to do it’s work. That surprised me – as I was planning on having a separate machine for the repository originally to separate the concerns.


Dec 24 2009

integrated project management for development

Tag: Geekstuff, Ranting and Reflections, django, railsJoe @ 3:40 pm

Ironically, the choices for an in-house integrated project management toolchain are, to my mind, significantly more limited than the straight up open-source market. I have been looking and watching several projects over the past months for something that I could use for my development team at work (i.e. behind a corporate firewall and not publicly available) to support a more open, transparent view of what was happening.

Trac, of course, is one I’ve used and really enjoy. Trac, however, doesn’t really support multiple projects in any integrated way – and we’ve got way more than one project. From the activity I’ve seen, it’s not about to any time soon. Variations on that theme include DrProject, and more recently Basie. They’re all interesting, but I didn’t see either DrProject or Basie as really ready for prime time and I wanted to be able to quickly grow beyond the basics. Two others that are obviously available are Redmine and Retrospectiva.

Ultimately, I’m heading down the road with Redmine for the following reasons:

  1. It’s a decent and clean user interface that has several years of polish now around it
  2. The system support plugins, and there’s several plugins that I really want to take advantage of
  3. Redmine and Trac appear to have the most active communities around them and driving them

The story cards and burn-down charts from Retrospectiva’s AgilePM addition were darned compelling. But ultimately it has a more limited set of folks focusing on that project, and I think I can achieve the same effects with plugins that are available from the Redmine community. Many of these are hosted on GitHub, and even more are in development or some middlin’ shape at the same site. And finally, I’d much rather deal with a partially implemented plugin than a partially implemented core system.

If I could host our development outside of the corporate firewall, I’d likely be looking at Bitbucket or Firefly for the work. I like Bitbucket partially because it’s all mercurial based, and I need to support some Microsoft based development. Git will work with enough effort, but I don’t want to go down the road of trying to explain all the detail needed there. I love the functionality in GitHub, and frankly think it’s a slightly better and more aggressively updated solution that BitBucket, but the git thing – while I’m happy enough with it – just sinks me otherwise because I know I’ll end up spending hours attempting to support it on a windows environment, and I just don’t want that hit. Firefly is ActiveState’s “let’s take and commercialize Trac by hosting it” – and they look like they’ve done a nice job of it. The agile methodology plugins and burn-down charts are pretty darn compelling.

It should be noted that I also took a pretty deep look at Launchpad. Even though it’s open sourced, it’s a damned complex thing to potentially integrate and build up for internal use, and its integration/collaboration features just haven’t been as compelling to me as the machinery that GitHub or Bitbucket provide. The “branch and request a pull” feature set that supports the massive branching and merging for features, bugfixes, etc. is just so much easier in Github or Bitbucket – and the wiki support to the other components is also far superior.

If you’re looking for something yourself, definitely keep an eye on the market and projects though. RIght now it’s just December 2009, and it’s clear there is a lot of effort, momentum, and a ton of good ideas that people are just begging to implement in this space. If I go to make this same decision in 6 months, there’s no guarantee that the landscape won’t have changed dramatically and a different solution would be better.


Dec 24 2009

debugging Active Directory LDAP authentication in Redmine

Tag: Geekstuff, railsJoe @ 11:55 am

What else does a geek do on Christmas eve? How about some ruby on rails debugging, especially when I don’t really know anything other than the basics of Ruby on Rails. :-)

So here’s what I’ve done and what I’ve learned, for the great search engine in the sky and the next time I find myself in this pickle.

I’ve installed Redmine on a CentOS box, which worked out really well. I cribbed the install notes from http://blog.itsmine.co.uk/2009/01/22/howto-install-subversion-and-redmine-on-centos5-rhel5/, which is a fantastic walk-through to the process.

So first is getting authentication working with Redmine. It includes a nice LDAPS:// based built-in mechanism, but there’s little detail around configuring it. The best is the wiki page RedmineLDAP on the Redmine wiki. If you’re doing LDAP authentication, you probably want LDAPS – otherwise you’re shipping passwords in clear over the wire. The default port of LDAPS on Active Directory is 636.

The other key thing you need to know is that even though you configure an LDAP connection in the redmine application (under http://YourRedmineHost/auth_sources/list), when you test it – it’ll test positive even if it isn’t binding into Active Directory and returning a result. Why? Now that another story – and one I don’t have clearly nailed.

To start, I enabled debugging in Redmine by editing /var/www/rails/redmine/config/environments/production.rb and inserting the line:

1
config.log_level = :debug

(the default, if you’re curious, is config.log_level = :info)

Restarted the service and now I’m getting a lot more detail. Turns out the LDAP authentication pieces really only trigger useful logging if the search mechanism that looks for the ID is successful. I found the ruby code doing the lifting at redmine/app/models/auth_source_ldap.rb – and starting adding in additional debugging methods. What I found was that the system wasn’t throwing any exceptions, but the result of a call to ldap_con.search() wasn’t returning any values.

What I haven’t been able to solve is why that search wasn’t returning any values.

Since I’m not super conversant on hacking on ruby (yet – I think I’m about to learn the hard way), I switched to a different tactic to see what was happening: tcpdump.

The command line to watch the LDAP protocol stream in plain-text as it flows is:

1
tcpdump -l -s 1024 -A -vv port 389

(you’ll need to run that as root, and turn of LDAPS so you can actually see the darned protocol). Wireshark would be a hell of a lot easier, but I’m doing this on a remote RHEL server and didn’t have a GUI to wrap into the darn thing. What I saw from that was a string embedded in the protocol noise:

LdapErr: DSID-0C090334, comment: AcceptSecurityContext error, data 525, vece.

Why this wasn’t propagating an exception or error in Rails is not clear to me (which is why I think I’m about to learn more rails hacking, the hard way). I’ve tweaked things around to get different exceptions, but what it all amounts to is that I’m not yet getting a good/successful bind on LDAP from which I can do searches.

I’ve managed to get LDAP authentication working from python (and Django) within my environment, so I’m familiar with the proper base DN and some of the attributes that are available for use from our Active Directory – but so far, no love in the ruby world.

When you’re configuring the LDAP, the code is written so that Redmine has to have an account and password that will bind with LDAPS properly and be able to return search results. If you’re doing this against active directory, make sure you include the domain in the account you’re binding (i.e. YOURDOMAIN\youraccount). That made the difference in getting a successful bind to LDAP. Using the correct domain is what got me past the bind issue. The fact that it wasn’t successfully binding and not propogating an error seems like a bug – that’s been logged today as issue 4483

(by the way – the time when I want more screen real estate is when I have 5 terminal consoles and two different web browsers open debugging something like the redmine application)

More later… still debugging, but now I’m diving into using ruby script/console to interactively figure out this LDAP code in ruby.

UPDATE: So the final solution was all about having the right configuration entries in the fields to make it work. I ended up using ruby script/console to manually drive values until I had a success, and then the results were really clear as to what I needed to use.

For anyone else coming along and trying to same thing, here’s what worked for me (minus my password…) to learn what attributes were being passed back from LDAP:

1
ruby script/console
1
2
3
4
5
6
7
8
require 'net/ldap'
options = { :host => 'my.adhost.com', :port => 389, :encryption => nil, :method => :simple, :username => 'DOMAIN\jheck', :password => 'mypassword' }
ldap_conn = Net::LDAP.new options
ldap_conn.open { }
ldap_conn.auth('DOMAIN\jheck','mypassword')
ldap_conn.bind
filter = Net::LDAP::Filter.eq('sAMAccountName','jheck')
ldap_conn.search(:base => 'DC=MYDOMAIN1,DC=MYDOMAIN2', :filter => filter)

A related update/patch submitted to Redmine a few months ago is issue 4283 which solves a quandry I have about needing a separate account to authenticate through LDAP. I’ll be trying out that patch next monday.


Nov 15 2009

South – incredible easy migrations for Django

Tag: Geekstuff, Ranting and Reflections, djangoJoe @ 5:47 pm

I’ve been hacking away at a side project for the past three or four weeks – got myself to internal milestone #2 this weekend, for which I’m really pleased. The very tail end of this milestone was deploying the code somewhere and vetting that all the basic, mostly-crappy-still bits actually worked.

Since I’ve got it deployed now onto a little dev server, I was thinking about how I was going to make this work going forward. Database migrations being one of those “how do you upgrade things?” questions when you’re doing rapid development django applications where the database model can get twiddled a bit.

The result of scanning around this afternoon from my favorite coffee shop haunt led me to South. In about 10 minutes I’d enabled and moved to south and had my application up and rolling with it. My previous experience was with Django Evolution – which wasn’t bad, but it was more work to get it into place and running.

The migrations in place, I did some model twiddling and experimented a bit to see how it all worked. I can see how if you’re not being somewhat careful, you could get into some really horrible places that no program could figure out. But basic migrations – moving forward and backward – really do an excellent job of “just working” with this framework out of the box.

The one interesting quirk I ran into – I’ve been doing tests on my codebase with:

coverage manage.py test

which just caught and ran the tests for everything in the application list. Figured it didn’t hurt to test the admin and auth stuff as well. When I added south, which I installed using:

 pip install south

The directory that south’s tests expect to use suddenly becomes a bit less accessible on the build server. Not a bad thing to redirect the tests to just what I’m writing, but an interesting side effect.


Nov 04 2009

Setting up a python CI server with Hudson

Tag: Geekstuff, Ranting and Reflections, djangoJoe @ 9:17 pm

Installing Hudson

I start with a basic virtual machine – in this case, I’m using Ubuntu Server 9.10. Once you have a basic machine installed, I recommend you make sure everything’s up to date with patches.

sudo apt-get update
sudo apt-get dist-upgrade

If you haven’t already, consider installing an ssh server for remote login. You don’t need it for hudson, but I find it makes administration easier.

sudo apt-get install openssh-server

To make installing python packages and pieces a bit easier:

sudo apt-get install build-essential python-dev

Start off by getting a copy of hudson.

wget http://hudson-ci.org/latest/hudson.war

Hudson runs fine from that war directly – a darned handy way to make the whole system work. You can also install this in Tomcat, JBoss, or whatever other servlet container you like to run. I find it easiest to run directly from the war file.

If you’re going using Mercurial or Git, you’ll need to install the appropriate version control client onto your machine as well. The plugins use those systems through the command line interface.

sudo apt-get install mercurial
sudo apt-get install git-core
sudo apt-get install subversion

Since hudson is a java application, we need to have java installed… Ubuntu 9.10 comes with OpenJDK which works just fine. You can also download and install the Sun JDK if you want to, but it doesn’t really seem to be required. If you don’t have any JDK already installed, you can generally get OpenJDK using:

sudo apt-get install openjdk-6-jre-headless

To get rolling with Hudson, just fire it up:

java -jar hudson.war

I just run this as the base user – no special privileges. It creates all it’s working directories, workspaces, etc in a “.hudson” directory. You can do the extra work to make this a unix daemon too – I haven’t bothered because it’s been relatively stable. There are some good notes on doing this at http://weblogs.java.net/blog/2009/02/10/hudson-now-good-behaving-unix-daemon and http://wiki.hudson-ci.org/display/HUDSON/Installing+Hudson+as+a+Unix+daemon, so I won’t dive into those details here.

Once you’ve started it, bring up the UI in a browser to make sure it’s all working. My virtual machine is running at 192.168.0.2, so I open up http://192.168.0.2:8080/. I’ll use this same IP address through the course of this walk-through. Of course you can replace it with a hostname.

hudson1

I generally start off by making sure we have the latest Hudson installed and getting the various client plugins I want to use all installed – click on “Manage Hudson” (http://192.168.0.2:8080/manage)

If there’s a more recent version of Hudson available, it will show at the very top of this page and give you the option to download and install it. You’ll be able to upgrade plugins the same way – Hudson knows to look at it’s own site for the latest plugins and versions, so it’s very easy to maintain. If you’ve been following along with this, the “wget” statement up above will have likely brought down the latest version already, so you won’t see this sort of screen until a new update comes along.

hudson2

The upgrade automatically mechanism has worked great for me, but a couple of caveats are needed here – the process needs to be running with permissions to the directory in which it’s located to work. The other is once you’ve upgraded the system, you may need to restart the service from the command line to enable future downloads. I’m not sure if I ran into a bug with that, or if that’s expected behavior – but I haven’t run into it often.

hudson3

Now you should have the latest version – either directly or just upgraded. Lets get to the plugins – because that’s where a lot of the Hudson goodness really lives. You can get to the list of installed plugins so you can see what’s there by default. From the “Manage Hudson” page, click on the link to “Manage Plugins”. The URL for that page is http://192.168.0.2:8080/pluginManager/

There are four tabs here to help you see what’s available – the first tab Updates is the default, and shows any outdated plugins. The second is Available, that shows what’s linked up from the central Hudson plugin list, and Installed, which shows the bits that are already there. Click on the Available tab (url is http://192.168.0.2:8080/pluginManager/available) and you can see the plethora of interesting things ready to use. The ones I like to install for my python projects are:

  • Cobertura Plugin
  • Git Plugin
  • Mercurial Plugin
  • Monitoring Plugin
  • Python Plugin
  • Violations Plugin
Click on one of the plugins at a time and then go to the bottom of the page (lower right corner) and click Install. The screenshot below should look pretty familiar for this process. I’ve had trouble sometimes installing several plugins at once, although I expect that should be possible.

hudson4

All of these plugins will still require you to have whatever local libraries you need to make them work. That’s why we installed Mercurial, Subversion, Git, etc earlier – to make sure those tools were available. Hudson invokes them on the command line on your behalf to make it all work.

Below is a broad set of libraries that cover a lot of pieces – you may want to install more/different libraries to accomplish your aims with Hudson. I’ll be aiming to create some typical build reports with it all – unit test output, coverage, etc.

sudo apt-get install python-setuptools
sudo easy_install coverage
sudo easy_install pylint
sudo easy_install unittest-xml-reporting
sudo easy_install fabric
sudo easy_install nose

Setting up a new Job

Now we just need a project. Let’s start with an open-source project – Pygments is a great project, with lots of diverse things happening within it. And it’s got tests and will be a good general victim for this writeup.

Start out by clicking on “New Job” (http://192.168.0.2:8080/view/All/newJob). A Job in Hudson is a build process. I’m going to make a fairly simple one, but you can cascade multiple jobs together into a far more complex build process if you want to… I’m not going to delve into that here, focusing instead on getting a single python project rolling.

hudson5

In the new job form:

  • set the job name to “pygments”
  • choose “Build a free-style software project”
  • I also put in a description (it’s not mandatory)
  • then choose “Mercurial” from the Source Code management section

hudson6

  • put in “http://dev.pocoo.org/hg/pygments-main” for Repository URL
  • put in “trunk” for the Branch
  • click the “Save” button down at the bottom

Now you’ve got a job – we can come back and configure this at any time, and we’ll do more tweaking as we go through this. Let’s make sure we have the basics all working first though…

    At this point, you should be at the project pygments page in Hudson. If you’re not, you can navigate there from the front page, or go directly to the URL (http://192.168.0.2:8080/view/All/job/pygments/). The page should look something like this:

    hudson7

    On the left hand side of the page are the controls for the job, including Configure and Build Now among a list of other options.

    • click on “Build Now”

    You should see the build start processing with a little rolling progress bar on the left hand side of the window. You can click on that link that looks like #1 Nov 5, 2009 8:35:18 AM’ in the Build History box.

      hudson8

      Either immediately, or when the build reports complete, click on that link.

      hudson9

      You can see the console output from the build (which is just pulling down the source) with the link Console Output. The output of the build is exactly what happened on the command line. In this case, you’ll see something akin to:

      Started by user anonymous
      $ hg clone -r trunk http://dev.pocoo.org/hg/pygments-main /home/ubuntu/.hudson/jobs/pygments/workspace
      requesting all changes
      adding changesets
      adding manifests
      adding file changes
      added 903 changesets with 2247 changes to 269 files
      updating working directory
      249 files updated, 0 files merged, 0 files removed, 0 files unresolved
      [workspace] $ hg log -r . --template {node}
      Finished: SUCCESS

      Once you’ve done an initial build, the files will also be available for you to look at and download through the Hudson UI. If you click on the link Back to Project or just the project name at the top of the page, you should see a new reference in the project called Workspace. Clicking into that will show you all the files that were downloaded and any other results of the build process. Right now we’re just getting files from source control, but as we add build steps to the process, the results will be available to dig around in at the workspace.

      If you want to set up Hudson to check for updates and build when it finds them, you can go back to the project page and click on the Configure link. Once in there, scroll down in the configuration and enable the checkbox labelled “Poll SCM”. As soon as you do, another text field will come available that will let you specify a Cron-like string to identify when the builds should check source control. In the screenshot below, I’ve enabled Hudson to check the mercurial repository every 10 minutes.

      hudson10

      Any time you change the configuration, go to the bottom of the Configure page and click on “Save” to set the changes.

      Adding Build Steps – doing ‘work’

      Right now, the build isn’t doing too much – let’s see about getting it doing some more work for us. The Pygments source code is set up with a Makefile to make doing this a bit easier, so we’ll take advantage of that. If you’re not in the Job configuration page – get there. Go to the job an click on the Configure link. Now we’ll add a build step that simple invokes the shell command “make test”.

      Scroll down in the configuration page until you see the section labelled Build. Click on the button underneath there labelled Add build step, and choose Execute shell. When the text field for that script appears, put in the text make test.

      Scroll to the bottom of the page, save the configuration, and invoke “Build Now” to run the updated build. Looking at the console output for the build will now show the updated console log with the running tests, like the screen shot below.

      hudson11

      Should the built in unit tests fail, the system will show a red indicator on the hudson front page and next to the build results link.

      Displaying unit test results

      What this isn’t doing it making some pretty graphs and charts. Let’s see about getting some of that enabled.

      Pygments uses Nose tests for it’s unit tests. That’s pretty nice, because Nose includes a mechanism to output the format of the tests into Java-based JUnit format, and Hudson in turn knows how to make pretty pictures from that format. Since we installed the nose library earlier, we can take advantage of it. Probably the “right” way to do this would be to change the Makefile to invoke the tests that output XML for the unit tests. For right now, we’ll just shim it into place with new build steps.

      • Change the content of the Execute shell build step and replace it with
        python tests/run.py --with-xunit
      • save the configuration and invoke “Build Now”
      • now look in the workspace in you should find a new file called “nosetests.xml” in the tests subdirectory.

      Let’s get that graphed…

      • Go to the job configuration and enable “Publish JUnit test result report”. It will have a text field so that you can tell it where to find the results. It uses an Ant format for finding filenames in an existing directory structure.
      • In this case use **/tests/nosetests.xml
      • Save the config
      • invoke Build Now

      Now you’ll see a new element in the web user interface called “Latest Test Result” which you can dig into. If you invoke “Build Now” again, it will start graphing the results of the tests and making that trend available in the project view. Right now this graph is going to be really darned boring, because there aren’t any changes between builds. Once more code starts rolling in, you’ll see changes with the number of tests being invoked. You can also click on that link and see the tests that were invoked. For python folks, remember that we’re shimming Python unit tests into a JUnit conceptual framework, so there are going to be some “leaky abstractions here”. In particular, test names, classes, and such may not alway match up with expectations. I have more details on how to enable XML output for a Django based test runner that I’ll post in another write up… uh, later.

      hudson12

      Add cobertura style test coverage reporting:

      Now we get to use Ned Batchelder’s coverage library to see some cool stuff!

      (This whole write up is basically a thank you to Ned for writing Coverage)

      Go back to the configuration for the job

      • change the Execute Shell build step to read:

      coverage run tests/run.py --with-xunit
      coverage xml

      • scroll down and enable  the check box Publish Cobertura Coverage Report
      • use the pattern **/coverage.xml
      Ned gave me some feedback that I’d like to include about coverage, which is really great detail:
      Cobertura has a Java-centric view of the world, and coverage.py tries to squeeze Python-oriented measurement into Cobertura’s Java-oriented report, so the “classes” numbers really have nothing to do with classes, they are about files, as an example. Also coverage doesn’t (yet! it’s almost ready for alpha) measure branch coverage, so those numbers are always 100% 0/0.

      hudson14

      Add pylint reporting

      Head back to the job configuration

      • add a new Execute shell build step  to read:

      #!/bin/bash
      pylint --rcfile scripts/pylintrc -f parseable pygments > pylint.txt
      echo "pylint complete"

      • It’s important to start this with #!/bin/bash, and then end with the echo statement so that the return codes from pylint don’t get interpreted as a build failure (unless you want that… I don’t know about you, but I’m not pythonic enough to have a 100% pylint result.)
      • enable the checkbox Report Violations
      • under pylint, use XML filename pattern of **/pylint.txt

      hudson13

      • save the configuration and invoke “Build Now”

      So there you have it – a python project building under hudson with unit tests getting run, cobertura style coverage reports, and pylint style reporting.

        hudson15


        Oct 21 2009

        Hudson – a lot of things just done “right”

        Tag: Geekstuff, Ranting and ReflectionsJoe @ 8:02 am

        For the past nine months, I’ve been nowhere near thinking about build systems and processes. A week ago, I had the occasion to spin up a continuous integration server for some internal project work. It had been a while, so I did some quick page browsing to hear about the latest and greatest there, and the Hudson system floated to the top of the list.

        Installing a basic Hudson instance is about as easy as you could ever imagine. One war file, than you can run from a single command line if you want. Or slap it into a stock servlet container – all your choice. The default configuration is all sensible and obvious, and best of all the working configuration is all through the web interface.

        There’s a huge list of really positive things to say about Hudson – it’s plugin set is monstrous, and clearly growing under active development, it supports remote slaves and distributed builds on multiple platforms, it’s developed in a commonly known, platform neutral language (java – not my favorite, but well known). But the real win of Hudson is that it’s functional right out of the box and damned easy to use, with the entire interface *really* through the web browser. In any other “plugin” system, I’d expect to have to be downloading something and dropping it into a directory; with Hudson you can download and then upload the plugin through the web interface. The dev team and contributors have really made this system a stellar example of effective and focused user interface design, functionality, and good defaults.

        I’m not even building Java applications – this is all getting used for doing CI with python code actually. And there’s folks who are building all sorts of things including iPhone apps with Hudson.

        If you’re thinking “huh, maybe I should…”, check out Hudson. It’s a quick check – one download, one command-line, and you’re rolling.


        Next Page »