Integración Continua y Despliegue Continuo 21-22
Página_Principal -> 2021/2022 -> Prácticas - 21/22
Contenido
Prerrequisitos
- Vídeo con los prerrequisitos
- El archivo django.yml ha de situarse en la carpeta .github/worklflows y ha de tener este contenido:
name: Python application
on: [push]
jobs:
build:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:10.8
env:
POSTGRES_USER: decide
POSTGRES_PASSWORD: decide
POSTGRES_DB: decide
ports:
- 5432:5432
# needed because the postgres container does not provide a healthcheck
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
steps:
- uses: actions/checkout@v1
- name: Set up Python 3.8
uses: actions/setup-python@v1
with:
python-version: 3.8
- name: psycopg2 prerequisites
run: sudo apt-get install libpq-dev
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install codacy-coverage
- name: Run migrations
run: cd decide;python manage.py migrate
- name: Run tests
run: cd decide;coverage run --branch --source=. ./manage.py test census --keepdb; coverage xml;
- name: Codacy Coverage Reporter
uses: codacy/codacy-coverage-reporter-action@v1.1.0
with:
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
coverage-reports: decide/coverage.xml
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: akhileshns/heroku-deploy@v3.12.12 # This is the action
with:
heroku_api_key: ${{secrets.HEROKU_API_KEY}}
heroku_app_name: " <<your app name>>"
heroku_email: " <<your email>>"
GitHub Actions
Nociones básicas sobre GitHub Actions
Dentro de cada .yml de la carpeta .github/worflows se define un:
- workflow el cuál se dispara al recibir un evento de GitHub.
- Estos eventos puede ser desde un push hasta la creación de una issue. Cada workflow permite correr jobs.
- Los 'jobs son secuencias de pasos. Cada uno de estos jobs se ejecutan dentro de un entorno llamado runner.
- Los runners son máquinas virtuales que se levantan para cada job. Todos los pasos de un job se ejecutan dentro del mismo runner, por lo que comparten recursos como los archivos y las carpetas.
- Los pasos de un job pueden ser simples instrucciones de shell, o utilizar funciones más concretas llamadas actions como, por ejemplo, hacer un clone.
El siguiente workflow tiene como nombre 'GitHub Actions Demo' y se dispara al hacer un push. Únicamente define un job llamado 'Explore-GitHub-Actions' dentro de un runner de tipo ubuntu-latest. Casi todos los pasos son de tipo shell salvo uno que utiliza la acción actions/checkout@v1.
name: GitHub Actions Demo
on: [push]
jobs:
Explore-GitHub-Actions:
runs-on: ubuntu-latest
steps:
- run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
- run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
- run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
- name: Check out repository code
uses: actions/checkout@v1
- run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
- run: echo "🖥️ The workflow is now ready to test your code on the runner."
- name: List files in the repository
run: |
ls ${{ github.workspace }}
- run: echo "🍏 This job's status is ${{ job.status }}."
- name: Contains expresion in a step
run: echo "Is this branch master or develop? ${{ contains('refs/heads/master refs/heads/develop',github.ref)}}"
Añade un archivo con este contenido a tu proyecto en GitHub y comprueba su estado en la pestaña Actions:
- ¿Cuántos Worflows, jobs, steps se lanzan?
- ¿Entiendes todo lo que hacen las expresiones ${{ <expresion> }}?
Para consultar la lista completa de expressiones, visita este [link].
Para consultar la lista completa de contextos (e.g., github.<>, job.<> o runner.<>), visita este otro [link].
Para consultar la lista completa de acciones, visita el [link].
Ejercicios de build
- Ejercicio 1: CI/CD de decide
- Ejercicio 2: Matriz con diferentes versiones de python
- Ejercicio 3: Badges de workflows
Ejercicios de deploy
- Ejercicio 4: Automatizar creación de superuser
- Ejercicio 5: Condiciones de despligue
- Ejercicio 6. Reutilización de workflows y creación de releases
Ejercicio de gestión de incidencias
- Al probar la app desplega en Heroku vemos un comportamiento anómalo.
- Crear una incidencia según las recomendaciones vistas en clase para el error que obtenemos al votar en heroku.
- Asegurarse que la incidencia creada incluye, al menos, un título descriptivo, información de qué es lo que ocurre y cómo puede reproducirse el error.
EJE1------------------------------------------------
Página_Principal -> 2021/2022 -> Prácticas - 21/22 -> Integración_Continua_y_Despliegue_Continuo_21-22
Decide con GitHub Actions
El archivo django.yml ofrecido prepara el entorno, prueba decide, reporta a Codacy y despliega en Heroku. Está compuesto por dos jobs.
En el job "build" se especifica que el servicio de base de datos tendrá que estar disponible en el runner de este job. Se le especifica información de healthchek para verificar que el servicio está correctamente levantado antes de continuar con los pasos del job. Para que este job funcione se tendrá que comprobar que:
- La configuración completa ha de estar en el settings.py. Esto, normalmente, si hemos hecho la práctica de heroku lo tendremos bien.
- Como no se está haciendo uso de local_settings, la configuración de la base de datos escrita en el django.yml deberá coincidir con la que esté puesta en el settings.py.
- Hay un test que puede fallar llamado "test_multiple_auths_mock" dentro del módulo Mixnet. Si falla, debería anularse ese test.
El job "deploy" se lanza sin esperar a que termine build. Para que solo se lance si el job anterior acaba satisfactoriamente añadamos la clausula "need":
deploy:
needs: build
Haz un push y observa la ejecución del workflow.
- ¿Se lanzan los dos jobs?
- ¿Está correctamente desplegada la aplicación en Heroku?
EJE2------------------------------------------------
Página_Principal -> 2021/2022 -> Prácticas - 21/22 -> Integración_Continua_y_Despliegue_Continuo_21-22
Build matrix en GitHub Actions
Al igual que hicimos en travis, podemos indicarle a GitHub que ciertos steps se ejecuten en paralelo. Para ello, hemos de hacer definir una "estrategria" a nivel de job. Para indicar varias versiones de python a utilizar en el step de "setup-python", incluiremos lo siguiente:
build:
strategy:
matrix:
pyversion: ['3.5','3.8']
Una vez hecho eso, podremos usar el contexto "matrix" en cualquiera de los steps de este job. En este caso lo usaremos en en el siguiente step:
- name: Set up Python ${{matrix.pyversion}}
uses: actions/setup-python@v1
with:
python-version: ${{matrix.pyversion}}
Haz un push y observa la ejecución del workflow.
- ¿Cuántos jobs se ejecutan?
- ¿Qué tendríamos que hacer para probar ampliar el build matrix con las versiones de postress 12 y 10.8? ¿Cuántos jobs se ejecutarían?
EJE3------------------------------------------------
Página_Principal -> 2021/2022 -> Prácticas - 21/22 -> [Integración_Continua_y_Despliegue_Continuo_21-22]
Badge de worflows de GitHub Actions
Al igual que hicimos en travis, podemos añadir badges a nuestro README.md relacionados con el estado de un worflow. Para ello:
- Accede a la pestaña Actions.
- Accede a uno de los Workflows.
- Pulsa el botón ... y genera el badge.
- Incluye el contenido de dicho badge en tu README.MD
Si tienes varios workflows:
- ¿Puede generarse un badge general o tiene que generarse un badge para cada workflow?
EJE4 ----------------------------------
Página_Principal -> 2021/2022 -> Prácticas - 21/22 -> Integración_Continua_y_Despliegue_Continuo_21-22
Creación de superusuario de Django desde Action
Al acceder a nuestra aplicación desplegada en Heroku no tendremos ningún usuario creado. Para automáticamente crear uno en nuestros despliegues añadamos un step nuevo a nuestro job "deploy".
- run: heroku run -a <Heroku app name> sh -c "python decide/manage.py shell -c \"from django.contrib.auth.models import User; User.objects.filter(username='admin') or User.objects.create_superuser('admin', 'admin@example.com', 'admin')\""
Haz push y, tras finalizar el workflow, accede a tu aplicación en heroku <app>.herokuapp.com/admin:
- ¿Puede acceder con admin/admin?
EJE5-------------------------------------
Página_Principal -> 2021/2022 -> Prácticas - 21/22 -> Integración_Continua_y_Despliegue_Continuo_21-22
Condiciones de jobs/steps en GitHub Actions
En GitHub Actions, los workflows tienen la capacidad de definir el/los evento/s que los disparan con la clausua "on:". Puedes ver [aquí] más detalles de dicha cláusula. Sin embargo eso no se puede especificar a nivel de job o de step. A esos niveles pueden expresarse sentencias "if" que permiten ejecutarlas condicionalmente. Puedes ver [aquí] más detalles de dicha cláusula.
Para hacer que solo se lance el job "deploy" cuando estemos en una rama concreta, por ejemplo, "master", incluiríamos lo siguiente:
deploy:
if: ${{github.ref == 'refs/heads/master' }}
Despues de hacer un push del django.yml, haz un push a otra rama.
- ¿Se lanza el workflow?
- ¿Se lanza el job "deploy"? ¿En que estado se queda?
Modifica la clausula "on:" para que se lance el workflow solo cuando se hiciera push a la rama master.
Despues de hacer un push del django.yml, haz un push a otra rama.
- ¿Se lanza el workflow?
EJE6 ----------------------------
Página_Principal -> 2021/2022 -> Prácticas - 21/22 -> Integración_Continua_y_Despliegue_Continuo_21-22
Reutilización de workflows y creación de releases
En GitHub puede hacerse crearse una Release de un repositorio en https://github.com/<tu org>/<tu repo>/releases. Para automatizar el proceso de generación de una release a partir de un tag (siempre y cuando dicho código haya pasado las pruebas) podemos combinar el workflow django.yml con un pasos posterior de release. Para ello:
- Cree un nuevo workflow en la carpeta de los workflows con el siguiente contenido:
name: release
on:
push:
tags:
- '*'
jobs:
buildTest:
uses: <tu org>/<tu repo>/.github/workflows/django.yml@master
secrets:
CODACY_PROJECT_TOKEN: ${{secrets.CODACY_PROJECT_TOKEN}}
HEROKU_API_KEY: ${{secrets.HEROKU_API_KEY}}
release:
needs: buildTest
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Release
uses: softprops/action-gh-release@v1
- Dado que las variables de entorno y secrets no se comparten entre workflows, hay que pasarlos explicitamente de un worflow al workflow reutilizable. Para convertir el workflow django.yml en reutilizable tenemos que modifcarlo añadiendo:
...
on:
push:
branches:
- master
workflow_call:
secrets:
CODACY_PROJECT_TOKEN:
required: true
HEROKU_API_KEY:
...
Hagamos un push de los cambios.
- ¿Cuántos workflows se dispara?
- ¿Se observa algún comportamiento diferente en el workflow django.yml?
Para crear un nuevo tag hagamos:
git tag -a v1.0.0 -m “mensaje para añadir al tag que también aparecerá en la release”
git push origin v1.0.
- ¿Cuántos workflows se lanzan?
- ¿Cuántos jobs se ejecutan del nuevo worflow?
- ¿Se crea correctamente la release?