/ django

Integración continua en django con Drone


Vamos a ver un ejemplo de como configurar Drone con un proyecto hecho en Django.

Drone permite integrar nuestros builds con diferentes servicios a través de plugins, por ejemplo podemos enviar el resultado del build a un canal de Slack y hacer el despliegue en nuestro servidor una vez que el build se complete satisfactoriamente.

La lista completa de los plugins disponibles la podemos encontrar aquí.

Para instalar Drone en tu propio servidor puedes seguir esta guia

Drone es una plataforma de CI basada en Docker, por lo que hace uso de imágenes Docker para hacer los builds.

Vamos a generar un proyecto en django, para lo cual ejecutamos django-admin.py startproject drone_example.

Una vez creado nuestro proyecto agregaremos una aplicación llamada blog con el comando python manage.py startapp blog y en esta crearemos un solo modelo, en blog/models.py, esto lo hacemos con el fin de probar el proyecto usando una base de datos.

from __future__ import unicode_literals

from django.db import models


class Post(models.Model):

    title = models.CharField(max_length=100)
    body = models.TextField()

    published_at = models.DateTimeField(null=True)

Ahora tenemos que hacer algunas pequeñas modificaciones en nuestro archivo settings.py

Primero debemos agregar nuestra aplicación a la variable INSTALLED_APPS

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'blog',
]

Luego de esto debemos ejecutar python manage.py makemigrations para crear las migraciones.

Ahora vamos a cambiar la configuración de la base de datos para usar PostgreSQL

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': os.environ.get('DB_NAME'),
        'USER': os.environ.get('DB_USER'),
        'PASSWORD': os.environ.get('DB_PASSWORD'),
        'HOST': os.environ.get('DB_HOST', '127.0.0.1'),
        'PORT': os.environ.get('DB_PORT', 5432),
    }
}

Usando os.environ.get estamos asignando nuestras credenciales desde variables de entorno, así no estarán dentro del código fuente.

Hacemos lo mismo con la variable SECRET_KEY

Por parte de django ya tenemos todo listo, Drone require de un archivo de configuración llamado .drone.yml, el cual esta hecho en notación YAML, en este debemos configurar el entorno bajo el cual se ejecutará nuestro proyecto asi como los comandos que se deberán ejecutar para hacer diferentes tareas como correr los tests, crear artefactos, etc.

Vamos a crear un archivo de configuración básico llamado .drone.yml con la siguiente información:

build:
  image: python:2.7
  environment:
    - SECRET_KEY=secret
    - DB_HOST=127.0.0.1
    - DB_NAME=postgres
    - DB_USER=postgres
    - DB_PASSWORD=postgres
    - DB_PORT=5432
  commands:
    - pip install -r requirements.txt
    - python manage.py test
compose:
  database:
    image: postgres
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
      - POSTGRES_DB=postgres

Ahora vamos a ver los bloques de los que consta nuestro archivo .drone.yml

  • build: Es el bloque de construcción, es lo que se ejecutará cada vez que se haga un push a nuestro repositorio.
    • image: Es la imagen de Docker usada para el build, se creará un contenedor basado en esta imagen.
    • environment: Aquí se declaran nuestras variables de entorno las cuales serán usadas dentro de nuestro proyecto.
    • commands: Son los comandos que se ejecután dentro del contenedor para realizar el build, en nuestro ejemplo primero debemos instalar los requerimientos y luego ejecutaremos el comando de django para correr todos los tests.
  • compose: Es el bloque de composición, aquí definimos los diferentes componentes con los que va a interactuar nuestro proyecto, cada uno se ejecutará en un contenedor y se enlazará automaticamente a nuestro contenedor principal donde se ejecuta el build. La estructura es similar a usada en el bloque build solo que aquí no definimos comandos, solo la imágen a usar y las variables de entorno.

Las variables de entorno de postgres son las usadas para crear la base de datos y el usuario, para mas información podemos revisar la documentación de la imágen de postgreSQL en DockerHub.

Las credenciales que definimos para postgres son las mismas que debemos usar para acceder desde nuestro contenedor en el bloque build las cuales serán leidas desde las variables de entorno del sistema en nuestro código python.

Para agilizar los builds podemos guardar en cache los archivos que descarga pip cuando se instalan las dependencias.

Modificamos el comando que instala las dependencias por:

pip install -r requirements.txt --cache-dir pip_cache

y agregamos al final del archivo .drone.yml:

cache:
  mount:
    - pip_cache

También se puede agregar el directorio .git para que se guarde en cache y así solo descargar los cambios recientes y no todo el repositorio en cada build.

Para ver mas opciones de configuración podemos revisar la documentación oficial de Drone.

El código completo del ejemplo esta en este repositorio.