GitHub App Bot 🤖 with Python
GitHub has a nice feature called “GitHub Apps”, in a nutshell, it let you automate and streamline your workflow by building your own apps.
We will make a simple bot that sends random MEMES every time a Pull Request has been open.
A HUGE thanks to “Meme_Api” for the random meme generator free API at https://github.com/D3vd/Meme_Api
Prerequisites
- GitHub Account
- npm
- Python 3.9.X
— Flask: as our Python webserver
— PyGitHub: to talk with GitHub
— cryptography: For decrypt our Github App certificates
Create a GitHub Repo for our Python Webserver
Log in to your GitHub account, click on the “New” button on the top left bar, give a name to your new repository, I will call mine “meme-bot”, and click on “Create repository”.
You can add a README.md, .gitignore, and a license
Nice, now we have a repository to store our GitHub App meme bot.
Creating a Webhook Payload Delivery
So, we need to create a webhook payload delivery to pass the event payloads that are being sent by GitHub to our local Python webserver, we will pipe does messages through the smee.io channel to our local machine.
Go to smee.io click on “Start new channel”
Copy the channel’s URL and save it for later use, my smee URL is https://smee.io/QocKc9AC7wLk7vgK
That's it! we created a channel for our app’s payloads, now we need to install smee client on our machine.
npm install --global smee-client
After installing, validate the installation by running:
smee --version
If the smee version popped up, you are good to go!
Creating GitHub App
Log in to your GitHub account, click on your icon → Settings → Developer settings.
You will find 3 different options:
- GitHub Apps
- OAuth Apps
- Personal access token
Go to GitHub Apps, and click on the New GitHub App button to the top right.
Give your app a name, I will use pr-meme-bot-777,
under “Homepage URL” you can enter the URL to our new repository, for my Homepage URL I will insert my meme-bot repository URL “https://github.com/OmriGilhar/meme-bot”.
go to the “Webhook” section, in the “Webhook URL” copy and paste the URL that we got from smee.io mine is “https://smee.io/QocKc9AC7wLk7vgK”.
Now, we got to the most important section “Repository permissions”, here we will define what permission our bot will need when someone installs it on its repository.
In a nutshell, our bot will listen to Pull Request events, and when a PR is opened it will post a new comment with a meme. So, our bot needs permission to read & write a comment on a PR, so we need to add “Access: Read & Write” under the “Pull requests” section.
Go to “Subscribe to events” and check the “Pull request” checkbox, it will tell the bot to send us an event payload when a PR event is created.
The last thing, in the “Where can this GitHub App be installed?” choose “Any account” if you want other GitHubbers to use your bot (you can always change it to private and vice versa).
Then click on the “Create GitHub App”.
After you create the GitHub App please save the “App ID” for later use (it's a 6 digit number).
Create a Private Key
In order for our Python webserver to send comments as our GitHub bot, We need to create a private key to authenticate with the GitHub, it will enable our Python code to act in the name of our bot.
Go to the bottom of our app page, you will find the “Private keys” section, click on the “Generate a private key”, it will create and download a .pem file with the private key inside.
This .pem file is very important, save it in a well-known folder, we will need it later.
I wil recommend to move and rename the .pem file to
~/.certs/github/bot_key.pom
folder
Install Our GitHub App on our Bot Repository
Go to your bot page and on the top, you will find the App Public URL
Copy and paste it in your browser, it will open the app installation page, install it on your bot repo, in fact, you can install it on any repo you own.
After you install the app, you can see the installation on your smee channel =)
Create a Python Bot
Clone your new repository from GitHub
MINGW64 ~/Desktop/Projects
$ git clone git@github.com:OmriGilhar/meme-bot.git
Cloning into 'meme-bot'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Compressing objects: 100% (2/2), done.
Receiving objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Create a app.py
file in the repository root
app.py
OK, this is a lot, but, you only need to change 1 line and it will work for you =)
Remember the GitHub App ID, well, you need to change line 10 with your App ID (As Integer).
Second thing, in line 13 we read the certificate for the bot, please make sure to change the location to your .pem file from the “Create a Private Key” section earlier, or change the code to match your .pem file location.
Redirect Payload to our Python Bot
Remember the smee.io channel that we opened? good. Now let’s redirect the payload from smee to our Python app, please run the following command:
smee -U https://smee.io/<Your Channel ID> --port 5000
Just remember to change the blank to your channel ID.
If you got it right, this will be your output:
smee -u https://smee.io/QocKc9AC7wLk7vK --port 5000
Forwarding https://smee.io/QocKc9AC7wLk7vK to http://127.0.0.1:5000/
Connected https://smee.io/QocKc9AC7wLk7vK
Now your Python bot can be activated and listen to smee payload
Run it All Together
Python:
Run app.py
smee.io:
Create a simple PR:
It worked!! our GitHub app that we installed on the meme bot repository POST a PR event to smee.io channel, smee channel then forward the event payload to our Python webserver, then the Python webserver adds a comment to the new PR with the ID of the GitHub App.
smee.io got a POST when the PR event created
Python got the POST from the smee channel and created a comment
That’s it! a simple GitHub App using Python webserver, from this point, the sky is the limit, you can create any flow that you want with this basic bot.
Here is the GitHub repository with the basic bot, feel free to copy and use it as you wish.
You can read more about GitHub API and events in the GitHub REST Documentation.
See you next article =)