Writing Brokers

(If you haven't read the introduction, "Service Integration", we suggest you do so now.)

Broker architecture

A broker is a small Python script. It receives a payload in form of a dictionary, containing at least 3 top-level keys; repository, commits, and service.

  • The repository key contains information about the repository, including the name, slug, and the absolute URL.
  • commits is a list, containing information about each commit in the push, including the author, commit message, files affected, and timestamp.
  • service is a dictionary containing service specific information, e.g. for the twitter broker, there will be a username and a password.

Here's a higher level chart of the flow:

Oberon flow

Lets go through the steps:

  1. User initiates a push.
  2. Bitbucket dispatches a message to Oberon, which is the service integration daemon.
  3. Oberon checks if the repository has any services enabled, and if so, constructs a payload, and sends it off to the broker.
  4. The broker receives the payload, analyzes it, and does its work.
  5. The broker takes action and pings a URL, sends an email, ...

The Payload

The payload, as shortly described above, is a uniform dictionary, containing information on the repository, the commits and the service specific values.

Here's an example payload for the twitter broker:

{'broker': u'twitter',
 'commits': [{ 'author': u'jespern',
               'files': [{'file': u'media/css/layout.css',
                           'type': u'modified'},
                          {'file': u'apps/bb/views.py',
                           'type': u'modified'},
                          {'file': u'templates/issues/issue.html',
                           'type': u'modified'}],
               'message': u'adding bump button, issue #206 fixed',
               'node': u'e71c63bcc05e',
               'revision': 1650,
               'size': 684}],
 'repository': { 'absolute_url': u'/jespern/bitbucket/',
                 'name': u'bitbucket',
                 'owner': u'jespern',
                 'slug': u'bitbucket',
                 'website': u'http://bitbucket.org/'},
 'service': {'password': u'bar', u'username': u'foo'}}

This particular payload contains only a single changeset. If more were present, they would look the same, and be in the same list.

The service key contains service specific information for the service (twitter). If your broker defines a field, e.g. URL, you will receive an url argument in the service key (all field-names are lower-cased.)

Writing a broker

We encourage contributing more brokers, as they are extremely simple to write. For example, this is the POST broker:

import urllib
from brokers import BaseBroker
from django.utils import simplejson as sj

class URLOpener(urllib.FancyURLopener):
    version = 'Bitbucket.org'

class Post(BaseBroker):
    def handle(self, payload):
        url = payload['service']['url']

        del payload['service']
        del payload['broker']

        post_load = { 'payload': sj.dumps(payload) }

        opener = self.get_local('opener', URLOpener)
        opener.open(url, urllib.urlencode(post_load))

That's all there's to it!

All brokers must subclass BaseBroker from the brokers module. This class is a metaclass that keeps track of which brokers are registered, and their version, so we can reload them without restarting oberon. It also makes a method available to you, namely get_local, which is a thread-safe way of instantiating. This is important for urllib for example, as we don't want authentication or caching to be jumbled among the threads.

Your broker must implement one method that we will call, handle. This function will receive a single argument, the payload.

Notice that we also delete the service and broker keys from our payload, as there is no reason to expose those to the endpoint.

Testing your broker

We ask you to kindly test your brokers before you submit them to us for certification. An easy way to do this is to use the example payload earlier described, and send it off to your brokers handle method.

Once you've written your broker and you're satisfied with it, send it off to jesper@bitbucket.org, advertise it on the mailinglist, or come on IRC!