CD ? Github Actions ??
¿Qué es un pipeline? ¿Continuous deployment (CD) Podríamos decir que basicamente es el flujo de procesos o acciones que se gatillan desde el teclado del programador hasta el ambiente de producción.
Aquí brevemente veremos un pipeline realizado utilizando los Github Actions. Basicamente se debe agregar un archivo en la carpeta `.github/workflows/` el cual contiene todos los pasos. Veamos un ejemplo, y luego podrás ver el funcionamiento completo en un video (al final) del post.
Condiciones, acciones
Se utiliza un archivo YAML para declarar el flujo. En el ejemplo se definió que se gatillará el flujo para las ramas de staging y master cuando el mensaje del commit tenga al inicio el texto "[Deploy]":
name: ci
on:
push:
branches:
- 'master'
- 'staging'
jobs:
ci-build-job:
runs-on: ubuntu-latest
if: contains(github.event.head_commit.message, '[Deploy]')
Construcción
- En el primer paso (Checkout) utiliza la módulo de acciones "actions/checkout@v2" (¿Ya mencioné que existe un sin fin de acciones que puedes utilizar? Mirá el Marketplace de acciones.). El "Checkout" básicamente hace un "git checkout" del último commit.
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set outputs
id: vars
run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
- name: Extract branch name
shell: bash
run: echo "::set-output name=branch::$(echo ${GITHUB_REF#refs/heads/})"
id: extract_branch
- name: Extract namespace name
run: echo "::set-output name=namespace::$([ ${GITHUB_REF#refs/heads/} = "master" ] && echo level1)"
id: extract_namespace
- name: Extract helm values file
run: echo "::set-output name=helm_values_file::$([ ${GITHUB_REF#refs/heads/} = "master" ] && echo values-prod || echo values-staging)"
id: extract_helm_values_file
Build and Push to DockerHub
Luego se gatilla un "docker build" al repositorio y se sube el contenedor a DockerHub:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v2
with:
context: .
push: true
build-args: |
GITHUB_USER=${{ secrets.DEPLOY_GITHUB_USER }}
GITHUB_TOKEN=${{ secrets.DEPLOY_GITHUB_TOKEN }}
tags: marketshop/sharetribe_level1:${{ steps.extract_branch.outputs.branch }}-latest
Helm upgrade
Finalmente, se instala el commando Helm, se copia el token del Kubeconfig, y luego se hace el "helm upgrade" para gatillar la actualización de la aplicación con la nueva versión del navegador.
- uses: azure/setup-helm@v1
with:
version: 'v3.2.4'
name: install helm
- name: configure Kubernetes
run: echo "${{ secrets.KUBECONFIG_CONTENT }}" > /tmp/kubeconfig
- name: upgrade helm release
working-directory: .helm
run: helm upgrade $HELM_RELEASE_NAME . -f values.yaml -f $VALUES_FILE.yaml -n $NAMESPACE
env:
HELM_RELEASE_NAME: sharetribe-level1
NAMESPACE: ${{ steps.extract_namespace.outputs.namespace }}
KUBECONFIG: /tmp/kubeconfig
VALUES_FILE: ${{ steps.extract_helm_values_file.outputs.helm_values_file }}
En la imange de abajo vemos como hay 2 contenedores. Uno está "Running" o activo has más de 44 minutos, y el nuevo contendor está "Pending" pero tiene recién 15 segundos de existencia:
Cuando el nuevo contenedor esté listo (en estado "Running"), Kubernetes automáticamente dará de baja el contenidor antiguo ("Terminating") así:
Así, Kubernetes mantiene el servicio 100% operativo.
Flujo completo
Veamos como funciona en la "realidad". Aquí les mostramos el flujo completo: