Pullbot is a responder for GitLab update notifications.
Pullbot opens an HTTP listener at a port (*:8666
by default). It
waits for HTTP POSTs from Gitlab, which look akin to the following JSON
document:
{
"ref": "refs/heads/prod",
"total": 0,
"fail": 0,
"success": 1,
"status": [],
"repo": "ssh://[email protected]:2222/connect-web/apache-config.git"
}
This notification tells Pullbot that an update was pushed to the
repository at
ssh://[email protected]:2222/connect-web/apache-config.git
, at the
ref refs/heads/prod
. We can respond to that notification.
The pullbot.ini
file lists repository locations (in the [repos]
section) and subscriptions (in a [subscriptions:hostname]
section).
To start, let's look at a [subscriptions:hostname]
section.
[subscriptions:my.example.net]
apache.url = ssh://[email protected]:2222/connect-web/apache-config.git
apache.subs = apache/example+refs/heads/prod
A [subscriptions:hostname]
section may contain many of these pairs,
so long as each pair has a .url
parameter and a .subs
parameter. Pullbot begins by matching the repo
key from the JSON
postdata to each of the .url
parameters in turn[1]. If a match
occurs, the corresponding .subs
parameter is used to determine what
local repository goes with this event, and which refs it cares about.
In this example, we care about the refs/heads/prod
ref (the head of
the prod
branch) and we will act in the apache/example
local repo.
If no match is found, nothing happens.
If a match is found, we look up the repo matched by the .subs
parameter -- the repo is the left side of the +
symbol -- in the
[repos]
section. First we find reponame.path
for the location
of the repo on disk. Then we find reponame.cmd
to decide how to
respond. (If there is no reponame.cmd
parameter, we will fall back
on *.cmd
.)
Consider this [repos]
section:
[repos]
apache/example.path = /etc/httpd
*.cmd = git pull origin %(ref)s
This tells pullbot that when the previous matching POST comes in, it
should move to the /etc/httpd
directory and run
git pull origin refs/heads/prod
.
We can't very well show an Apache configuration example and not show how to restart Apache. The fact is, if there is more than one matching subscription for a notification, then each one will run -- again, in alphanumeric sort order. So let's consider a more complete configuration:
[repos]
httpd.path = /
httpd.cmd = sh -c '( /etc/init.d/httpd restart </dev/null & )'
apache/example.path = /etc/httpd
*.cmd = git pull origin %(ref)s
[subscriptions:my.example.net]
00apache.url = ssh://[email protected]:2222/connect-web/apache-config.git
00apache.subs = apache/example+refs/heads/prod
# Restart httpd last, for any repo with connect-web in the url
99httpd.url = *connect-web*
99httpd.subs = httpd
Under this configuration, the same POST would trigger the same git pull
operation -- but would additionally restart Apache when done. That would
happen because the 99httpd.url
parameter matches the URL of the affected
upstream repo (using shell style globs, not regular expressions), and because
we subscribe the httpd
"virtual repo" to matching POSTs. (Note that
there is no +ref
pattern here. That means all refs match.)
[1] parameters can go into a Python configuration object in one order, and come back out in another. However, keys are sorted before matching begins. If matching order is significant, set the prefixes so that they sort in alphanumeric order. An easy way is to prepend a two-digit number to each pair, to put them into the correct order.