Building a Flask App with CI/CD using Travis CI and Heroku

Flask is a very popular Python micro-framework used for building web applications. CI/CD or Continous Integration and Continous Deployment is a way to ship code in small parts while always checking to ensure that the code works properly. We will do this through Github, Travis CI and Heroku.

Here, we’ll be making a simple web application that rolls a virtual dice with the number of sides defined by the user.

In this tutorial, we will go through:
1. Initialising the repo and environment
2. Building a Simple Flask Application
3. Writing tests for the app
4. Integrating Travis CI
5. Deploying on Heroku (without Docker)

Step 1: Initializing the repository and environment

Choose python in the options for the .gitignore file. This will help us in preventing unwanted files from going onto github.

Clone the repo to your computer using the command. Replace the url with your repository’s url.

git clone https://github.com/srujandeshpande/dice-on-demand.git

Navigate into the directory with the command

cd dice-on-demand

Now, let’s create a virtual environment. Virtual Environments are useful as they isolate our python packages from the rest of the operating system.

Download the virtualenv package using the command

pip3 install virtualenv

Now create a new virtual environment in your directory using the command

virtualenv venv

Now activate your newly created virtual environment using the command

source bin/venv/activate

Create a file named ‘requirements.txt’. Add the following lines to it. This will lists out all the dependencies we need.

Add this to requirements.txt

Download the dependencies using the command

pip install -r requirements.txt

Step 2: Building a Simple Flask Application

The code for app.py

There are 2 routes in this application.
/ is the website root and will return the actual application page
/test will be used to test if our app is properly deployed

Add the file name to the flask environment variable.

export FLASK_APP=app

Now you can run the app with the command

flask run

Test it out by going to http://localhost:5000/test
Going to http://localhost:5000 won’t work just yet because we haven’t added the ‘dice_page.html’ code.

Create a new folder called ‘templates’. Create a file named ‘dice_page.html’ in that folder.

The directory should now look like this

dice-on-demand/
requirements.txt
app.py
templates/
dice_page.html

Add the following code to ‘dice_page.html’

The code for templates/dice_page.html

Terminate the flask server with Ctrl+C and run it again. Navigating to http://localhost:5000 should let you roll a dice!

Step 3: Writing Tests for the app

Create a folder named ‘tests’ and a file in it named ‘test_dice.py’. Add the following code to ‘test_dice.py’. We’re calling the test function to see if it returns the correct output.

The code for test_dice.py

To test the application, run the command

python -m pytest -v tests/test_dice.py

The output should look something like:

============================================================================================ test session starts =============================================================================================
platform linux -- Python 3.7.5, pytest-5.4.1, py-1.8.1, pluggy-0.13.1 -- /home/srujan/Projects/venv/bin/python
cachedir: .pytest_cache
rootdir: /home/srujan/Projects/dice-on-demand
collected 1 item
tests/test_dice.py::test_test PASSED [100%]============================================================================================= 1 passed in 0.09s ==============================================================================================

Step 4: Integrating Travis CI

Create a new file called ‘.travis.yml’
This will contain whatever we want Travis CI to check and perform

The code for .travis.yml

Now add, commit and push your code. Head to the travis-ci dashboard and you should see your test passing. Make some changes to the test function in app.py and check if the test passes!

Step 5: Deploying on Heroku (without Docker)

We’re using Gunicorn as our production server here and the great thing is it can easily be deployed on Heroku. Using only Gunicorn isn’t recommended though as it’s not great at handling DOS attacks and serving static files. That’s where Nginx comes it. Nginx acts as a reverse proxy and HTTP load balancer for our application. It serves static files faster to clients and can prevent DOS attacks leaving only the dynamic python stuff to Gunicorn.

When using Nginx as well, we’ll have to package them together in a Docker container, but that not what we’ll do here. Here, we’re going to only use Gunicorn and directly deploy to Heroku. Deploying to other cloud service providers such as AWS, GCP, Azure or even on premises servers may have a different procedure and that’s why Docker is preferred. It’s scalable and reusable.

Create a file named ‘Procfile’. This file will contain the command that Heroku will use to run our app.

The code for Procfile

We will be using Gunicorn as our production server. The web keyword tells Heroku to deploy the app on the web.

Next, head to https://heroku.com and create a new app

Heroku — Create a new app

Then, on your app’s dashboard, head to the deploy tab. Choose Github as the deployement method.

Heroku — Connect to Github

Link your Github account and search for your repository. Then, click on connect.

Then, scroll down to the Automatic Deployments section. Check the box for ‘Wait for CI to pass before Deploy’. This will ensure that after a push, our app only gets deployed after the tests in Travis CI pass.

You can leave the branch at master or change it according to your needs.

Heroku — Automatic Deploys

Finally, click on the ‘Enable Automatic Deploys’ button. Our app is now running!

Click on the ‘Open app’ button at the top of the Heroku dashboard, or navigate to your app’s url to see it working!

Change up a few lines of code and check the Travis CI dashboard to see the test status. Only if they passs, it’ll get deployed onto Heroku.

Hey, I’m Srujan. A Student, Developer and Perpetual Learner!

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store