Fedmsg is a perfect system for automating things. I mostly use it to integrate Pagure with Jenkins, which works rather well.
One hiccup is that when a pull request is updated (by pushing more commits to the branch or rebasing it), Pagure will not notice that until someone visits the pull request page. At that point a comment with the notice is generated and the message sent.
My first instinct to automate this was to use a git hook. It’s easy to automate hitting each pull request page.
curl -s https://pagure.io/api/0/pungi/pull-requests | \
jq '.requests[] | select(.user.name == "lsedlar") | .id' | \
while read PR_ID; do
echo "https://pagure.io/pungi/pull-request/$PR_ID"
curl -s "https://pagure.io/pungi/pull-request/$PR_ID" >/dev/null
done
However, there is no post-push
hook, so one would have to run the
script manually. That’s too much work.
Fedmsg to the rescue
How about getting notified about the push from the server? Pagure will send a message announcing a push immediately.
What we need is a very simple consumer that waits for pushes, finds where the pull requests would likely be going to, tries to find one from this branch and hits the web page.
If the push is to a fork, we can assume the pull request would be filed against the original repo. If it’s not a fork, then the pull request would probably be against the same repo.
= 'https://pagure.io'
BASE_URL
class Poker(fedmsg.consumers.FedmsgConsumer):
= ['io.pagure.prod.pagure.git.receive']
topic = 'poker.enabled'
config_key
def consume(self, msg):
= msg['body']['msg']
msg = msg['branch'].split('/')[-1]
branch = msg['repo']['name']
repo if msg['repo']['parent']:
= msg['repo']['parent']['name']
repo
= '%s/api/0/%s/pull-requests' % (BASE_URL, repo)
url = requests.get(url)
response if response.status_code != 200:
self.log.warning('Failed to get %s ...', url)
return
for pr in response.json()['requests']:
if pr['repo_from']['id'] != msg['repo']['id']:
continue
if pr['branch_from'] != branch:
continue
= '%s/%s/pull-request/%s' % (BASE_URL, repo, pr['id'])
url self.log.info('Poking %s', url)
requests.get(url)return
A file with this class should be installed with setup.py
somewhere under
site-packages
. For fedmgs-hub
to pick the consumer up, there must be a
special section in the setup()
function call:
="""
entry_points[moksha.consumer]
pokeapagure = poke_a_pagure:Poker
"""
The name on the left of the equals sign does not really matter. The string on
the right should be a package name and a class name of the consumer. In this
case the file will be poke_a_pagure/__init__.py
.
How to make it work
This consumer will run as part of fedmsg-hub
(provided in similarly named
package). All that is needed to get it working is to install the hub and the
python package with the class.
There also needs to be a config file in /etc/fedmsg.d/poke_a_pagure.py
. The
name is completely arbitrary, nothing depends on it.
= {
config 'poker.enabled': True
}
Note the matching config key with the consumer above. There can be more configuration, such as custom rules for logging.
Once that exists, just restart the hub and observe its logs. It will tell you which consumers were loaded.
It’s this easy to write a consumer of messages. Now, would it be easier to fix Pagure to send the message immediately? Maybe. But is working with fedmsg fun? Definitely!