Or how to become the most loved (hated) person in the office
Lately I've been playing around with Slack service intergrations and I was impressed to find the JIRA integration had subtle style differences when a user completed a sprint ticket and marked it as 'Done'.
I thought it would be cool if we could have a song play in our office every time a ticket was marked as Done within Atlassian's JIRA agile tool. The concept was simple enough, have a POST webhook setup on JIRA and a small application sitting on an internal server listening for 'issue update' calls from JIRA. If the change included the issue being marked as Done, play an audio file through the server's speakers. Easy.
Because JIRA passes through the username of whoever updated the ticket, I quickly realised we could change the audio file being played based on who moved the ticket. I got everyone in the team to create their own 10 second theme song that they wanted to play when they finished a ticket. The results range from 'The Hunters and Collectors' to sound clips from NBA Jam arcade.
The end result was a Python Flask app that runs on a mac mini, it uses ngrok for tunnelling and uses applescript to call iTunes directly. You can view it at the github project below, or read on for the technical nuts and bolts of how it all comes together.
The app is written in Python and uses Flask to provide an endpoint for the JIRA webhooks to post to. It runs locally listening on port 5000.
I only set up one endpoint route at /play all webhooks are routed through this and then evaluated to see who initiated the ticket update.
@app.route('/play', methods = ['GET', 'POST', 'PATCH']) def play():
Once you fire up the application you'll see it sitting in a terminal window running.
JIRA webhooks can only post to URLs on port 80 or 443. So we use ngrok to create a tunnel from port 5000 to port 80.
When you generate a ngrok tunnel you'll receive a randomly generated unique URL such as dsf567.ngrok.com. However, if you sign up for a free account you will get an authtoken that you can provide via command line options to select a preferred subdomain such as mypreferredsubdomain.ngrok.com. If you donate to the project you can even reserve a preferred subdomain for yourself.
Usage details and additional command line options for ngrok are on their site.
Next you'll need to define the JIRA webhook to hit the Flask endpoint.
You can access the webhooks menu in JIRA from Cog Menu > System > Webhooks
You will need to set the URL to http://<yourngroksubdomain>.ngrok.com/play
You can setup filters to only look at certain projects or tickets types using JQL. Lastly, choose which events you would like the webhook to trigger on.
The webhook post will return JSON.
Right, lets' go back in the Python Flask app.
We first determine whether the hook was a POST call
if request.method == 'POST':
Then we parse the JSON so we can query it.
jsondata = request.data data = json.loads(jsondata)
Now we're really interested in two key pieces of information from the JSON.
1. What is the new status of the ticket (so we can determine if it's done)
new_status = data['changelog']['items']['toString'] if (new_status == 'Done'):
2. Who moved it to done
if (request.values.get('user_id', None)): u = request.values.get('user_id', None)
If the ticket wasn't moved to Done on this transition, we just ignore it and don't go on to evaluate who performed the update.
If it was moved to done, we capture who moved it and then check to see which of our team members it was.
I know there has to be a more elegant way to do this, but this was a hack job at the time.
if (u == 'user.name'): try: applescript.launch_script(teammember_script) return "playing first teammember's song" except applescript.AppleScriptError: return "Something has gone wrong with Applescript" elif (u == 'another.username'): try: applescript.launch_script(teammember2_script) return "playing teammember2's song" except applescript.AppleScriptError: return "Something has gone wrong with Applescript"
If the username from the JSON matches one of the if statements, it will execute an applescript that is hardcoded at the top of the script. This apply script tells iTunes to launch and play a specific song from a specific playlist.
teammember_script = """tell application "iTunes" play track "Dont Stop Believing" of playlist "Done" end tell """
Adding more team members is clumsy, but simple enough. You create applescripts for each of your team members and then add more elif blocks to compare against their username.
If you wanted to have a custom applescript for say a bug. You could simple add a comparison to look for the ticket type returned in the JSON. Alternatively, just create a different endpoint route, perhaps /bug. And then create a new JIRA webhook which uses JQL to only filter on bug type tickets.
And that's it! Simple, hacky & fun. It's released under MIT license so if you think this is a cool idea, but kind of inefficient, please submit a PR and let's make this better.Project on Github