How?

We use GitHub webhooks to tell our application that it has been updated so it does a pull and then reloads itself.

I’ll take the example of my application SwagLyrics whose backend is hosted on PythonAnywhere. I’m using Flask so you might want to adjust accordingly if you’re not. This is my repo so you can use it as a reference:

First off, make sure your repository on GitHub and PythonAnywhere are in sync, the GitHub one should be the origin and if you haven’t made a repo on PythonAnywhere yet, you could initialise one or clone into PythonAnywhere from GitHub.

Something like

git init

git remote add origin https://github.com/yourusername/yourreponame.git

Now go to your repository on GitHub → Settings → Webhooks → Add webhook.

This is what you see:

In the Payload URL add https://your_domain/route_to_update

Eg. my repo has the webhook sent to https://aadibajpai.pythonanywhere.com/update_server

Then change the Content type from application/x-www-form-urlencoded to application/json (I’ll tell you why a bit later).

We’ll come to the secret part a bit later as well.

Make sure it’s the push event that triggers the webhook and click on Add webhook.

Now, open up your flask app and we’ll configure a route which receives the information from GitHub whenever there’s a push event. This route will be the same as the one we used in the Payload URL. We do not explicitly checkout master since I assume that’s the only branch here.

A barebones simple setup would look something like this:

from flask import Flask, request

import git app = Flask(__name__) @app.route('/update_server', methods=['POST'])

def webhook():

if request.method == 'POST':

repo = git.Repo('path/to/git_repo')

origin = repo.remotes.origin origin.pull() return 'Updated PythonAnywhere successfully', 200

else:

return 'Wrong event type', 400

This is a very rudimentary version and there’s a more complete version below.

Now whenever there’s a push event, this route will receive the info and update itself by doing a pull.

Hopefully, this is what it looks like when you make a commit

fingers crossed

Before I tell you how to secure your webhook, I’ll tell you how to make sure your app reloads after a pull so you don’t have to manually do that.

Auto-reloading your webapp

We’re going to use git hooks to do it. These are shell commands executed after a git event takes place. There’s no post-pull hook, but…

We take advantage of the fact that a git pull is nothing but a git fetch → git merge and there is a post-merge hook. It executes if the pull completed successfully.

In your git repo over at PythonAnywhere go to .git/hooks/

There will be a bunch of pre-existing ones but make a new file called post-merge.

Put the following code there:

#!/bin/sh

touch /path/to/username_pythonanywhere_com_wsgi.py

Use the path to your wsgi file which when touched, reloads your webapp.

Now to make this executable, open a bash console there and run

chmod +x post-merge

That’s it, now you can test that it works by making a sample commit.

Most importantly, now we move on to securing your webhook.