debian/rake: Ruby DH Sequencing?

In my previous post I looked at the possibility of using rake, a Ruby build tool, instead of make to write debian/rules files. While that turned out to not be entirely impossible as far as the core dpkg-* utilities used to build Debian packages are concerned, wiring it up with the debhelper ‘dh’ command sequencer appears unfortunately impossible without changes to dh itself.

Clearly the solution here is to write our own sequencer in Ruby! To do that we will first have to understand what a sequencer does though.
Continue reading

debian/rake: A Tale of Rubies

A while ago Rohan and I talked about the possibility of writing debian/rules in ruby rather than make. Even though this is not exactly policy compliant I was reasonably certain that this is possible, I just was not quite sure how much resistance the existing tools would give a rules file that is not written in make. So, I set out to hack up a debian/rules file using rake (a make-like build tool using ruby). Continue reading

A Launchpad Module for Ruby

At some point last year I started to write a Launchpad API client in Ruby, for the very simple reason that Kubuntu CI tooling is almost entirely written in Ruby and I wanted to avoid round tripping into Python to use launchpadlib for trivial things such as querying the version of a package in a PPA. Not only would that be slightly slower it also raises the ever so unfortunate problem of how to exchange data between Ruby and Python.

Perhaps someone else also can find it useful.

It is intentionally minimalistic in it’s design and validation. All JSON return data is parsed into an glorified OpenStruct with special method_missing handling which depending on how you call a non-existent method would either attempt an HTTP GET or HTTP POST on the Launchpad API. Since the underlying data is never actually wrapped into literal classes on the Ruby side it has surprisingly few lines of code.

Unfortunately this also means that there is absolutely no hand holding for anything. For the most part method calls result in exactly the same methods being called on the API endpoint. So, correctly reading and using the API documentation is pretty much a necessity. Otherwise something is most likely going to raise a supremely cryptic exception ;)

Calling a method on an object results in an HTTP GET on the self_link of that object. If the method is suffixed with a ! it will do a HTTP POST instead.

So, if I want to list all my Bazaar branches on Launchpad I’d first create a wrapper object for my user endpoint and then call:


Which as you would expect returns an Array of ‘branch‘ type objects to use. Alternatively, if I wanted to change my account status I’d again use my user endpoint object and would need to do a POST operation on it (according the API):

me.setAccountStatus!(comment: 'Best be off then', status: 'Deactivated')

Notable difference being the exclamation point indicating that we want to POST the method call.

And that is pretty much all there is to know about the entire module.

Finally a short example:

require_relative 'lp'

url = ''

ppa = Launchpad::Rubber.from_url(url)
sources = ppa.getPublishedSources(status: 'Published', source_name: 'solid')
sources.each { |s| puts s.display_name }
  1. creates a Rubber object from a PPA url
  2. gets all published solid sources from that PPA
  3. ouputs the display_name of all returned source