Continuous integration and deployment are two of the most important things to have in any modern web application, alongside a lean and production-ready development environment. At SourceLair, we try our best to give you the latter, while at the same time we integrate as well as possible with services covering the other steps of your code delivery chain.
In this tutorial, we'll describe how you can create a nice integration between SourceLair for developing, Codeship Pro for testing and Heroku for deployment.
Setting the stage
For this tutorial, you'll need:
For the sake of this tutorial, we'll create a Django application, backed by a PostgreSQL database, which we'll code in SourceLair, set up CI/CD in Codeship and then deploy to Heroku.
Getting started
The repository we'll use throughout the tutorial can be found at https://github.com/sourcelair-blueprints/django-postgres-ci-cd as base. Since we'll also need a PostgreSQL database, we have prepared a complete Blueprint which will:
- create a new SourceLair project from the above repo
- attach a PostgreSQL database
- run
pip install -r requirements.txt
so that you have all the dependencies installed
After you've created your project, you will need to make sure your database contains any needed migrations by opening the Command Palette with Ctrl + Shift + P (Cmd on a Mac) and using the "Migrate" command
Now that you have added the needed migrations for your database, it's time to test that everything is working nicely. Open your server's Public URL from the eye-like icon in the sidebar, or by using the "Public URL" Command Palette command.
As you can see, you can add new posts, like them and then the likes are calculated and displayed under each post.
Setting up testing
Your application works nicely and correctly displays the correct number of likes, but are you sure they are always calculated correctly? Let's dive in the code to see how this works and make sure with a test that it will keep working 😀
Getting the testing code ready
Open the models.py
file from the file explorer, or by using the Quick open functionality of SourceLair with Ctrl + Shift + O (or Cmd on a Mac). There, you'll see that we have two models defined, Article
andLike
. The interesting part though is that for performance reasons, the like_count
value is saved in the Article
model and not queried every time from the database. This is done with Django signals - open the signals.py
file if you like to see how this works.
What we would like to make sure now is that every time we create a new Like
entry, the like_count
of the related model is incremented. For that reason, open the tests.py
file and add the following code:
# blog/tests.py
from django.test import TestCase
from blog import models
class ModelsCase(TestCase):
def setUp(self):
self.article = models.Article.objects.create(
title='New article', text='Demo text', author='42')
def test_like_increment(self):
"""
Test that creating a like, correctly increments the counter of the
article.
"""
models.Like.objects.create(article=self.article)
self.article.refresh_from_db()
self.assertEqual(self.article.like_count, 1)
This will make sure our condition is met. In order to test this locally, run the following command in your SourceLair terminal:
./manage.py test
This will run the test you just created and - hopefully - report that it worked!
Setting up GitHub and Codeship integration
Before you set up your project's CI integration, you'll need to:
- create a new GitHub repository
- create a new Codeship project and configure the connection with GitHub
- add your GitHub remote to your SourceLair project
- To do this, use the "Add remote" Command Palette command, add "origin" as the name and your SSH URL from your GitHub repository
Creating the needed files for Codeship
Codeship Pro is based on Docker, as is SourceLair. That's why it's super easy to describe your SourceLair project in a way that Codeship understands.
First, you'll need to create a Dockerfile.codeship
file, which describes your main application:
# Dockerfile.codeship
FROM python:2.7.11-onbuild
MAINTAINER Antonis Kalipetis <[email protected]>
RUN apt-get update && \
apt-get install -y netcat
Then, you'll need to create a file named codeship-services.yml
, which describes the exact same stack you have on SourceLair - a Python application and a PostgreSQL database:
# codeship-services.yml
web:
build:
image: akalipetis/codeship
dockerfile_path: Dockerfile.codeship
links:
- postgres
environment:
DATABASE_URL: "postgres://postgres:[email protected]/codeship"
postgres:
image: "postgres:9.4"
environment:
POSTGRES_DB: codeship
POSTGRES_PASSWORD: mysecretpassword
Finally, you'll need to describe the steps that Codeship needs to run in order to test your application in a codeship-steps.yml
file:
# codeship-steps.yml
- service: web
command: bash check_n_run.sh ./manage.py migrate
- service: web
command: bash check_n_run.sh ./manage.py test
As you can see, we're using a file named check_n_run.sh
to wrap our commands. This is used so that we make sure the PostgreSQL database is in place when the tests run. The check is pretty simple and straight-forward:
# check_n_run.sh
#!/bin/bash
set -e
function check_port() {
local host=${1} && shift
local port=${1} && shift
local retries=5
local wait=1
until( $(nc -zv ${host} ${port}) ); do
((retries--))
if [ $retries -lt 0 ]; then
echo "Service ${host} didn't become ready in time."
exit 1
fi
sleep "${wait}"
done
}
check_port "postgres" "5432"
exec "[email protected]"
Shoot! 🚀
Everything should be ready now, so the only thing you need to do is commit and push your code to GitHub, using the "Commit" and "Push" Command Palette commands. After you have pushed your code, all you need to do is open Codeship and you'll see your build there.
🎉 Congratulations, you have just set up your project's continuous integration!
Deploying your code
First we'll deploy the application to Heroku and then we'll set up continuous deployment
Deploying to Heroku from SourceLair
In order to deploy your code, you just need to run the following commands:
- run the "Heroku: Create" Command Pallete command to create a new Heroku project
- run the "Heroku: Deploy" Command Pallete command to deploy your Django application to Heroku
- run
heroku run ./manage.py migrate
in your SourceLair terminal, in order to set up your Heroku database
That's it! Visit your Heroku URL - the one printed when you deployed your application - and you'll see it running live.
Setting up continuous deployment
Heroku integrates nicely with GitHub, so all you have to do is:
- open your Heroku dashboard
- select the application you just created
- switch to the "Deploy" tab
- select GitHub
- enter your repository's name and press "Search"
- select your repository from the list
- click on "Enable Automatic Deployment"
- 🎩 enjoy!
You can read more on Heroku's GitHub integration here.
Wrapping up
That was it. Now, each time you push to any branch, Codeship will kick in and start your automated testing suite, while every time you push to master
, Heroku will make sure your code will be delivered to production. Easy and nice, wasn't it?