Actions
GitHub Actions¶
GitHub Actions es una herramienta que nos permite automatizar tareas. Se pueden crear workflows que se ejecutan cuando se produce un evento, como un push a una rama, un pull request o un issue. Los workflows se pueden crear en un fichero de texto plano, en YAML, que se almacena en el repositorio. Los podemos ejecutar en un entorno de ejecución, que puede ser un contenedor de Docker o una máquina virtual.
Ejemplo de un workflow¶
name: CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run a one-line script
run: echo Hello, world!
- name: Run a multi-line script
run: |
echo Add other actions to build,
echo test, and deploy your project.
En este repositorio vamos a tener varias actions distintas, que vamos a ver a continuación.
GitHub Pages¶
GitHub Pages es una herramienta que nos permite alojar páginas web estáticas en GitHub. Esto se puede hacer de dos formas, mediante una GitHub Action o mediante una rama de un repositorio. En este caso, vamos a ver cómo se puede hacer mediante el uso de una GitHub Action.
Para poder utilizar GitHub Pages en nuestro repositorio mediante el uso de una action, tendremos que habilitar la opción de GitHub Pages en el apartado de Settings del repositorio. Look:

Una vez habilitada la opción de GitHub Pages, tendremos que crear un fichero de configuración en el directorio .github/workflows del repositorio. Este fichero de configuración se va a llamar pages.yml y va a tener el siguiente contenido:
name: Publish to GitHub Pages
on:
# Esta acción se ejecuta cuando se hace un push a la rama main
push:
branches: ["main"]
permissions:
# Esta acción necesita permisos para escribir en el repositorio
contents: read
pages: write
id-token: write
jobs:
# Tarea para hacer un build de la página web
create-docs:
environment: Deploy docs
runs-on: ubuntu-latest
steps:
# Empezamos clonando el repositorio en la máquina virtual que se encargará de todo
# y luego instalamos las dependencias necesarias para hacer el build.
- name: Checkout
uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.9
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r mkdocs-requirements.txt
# Una vez instaladas las dependencias, hacemos el build de la página web y la subimos
- name: Build docs
run: mkdocs build
- name: Setup Pages
uses: actions/configure-pages@v2
- name: Upload artifact
uses: actions/upload-pages-artifact@v1
with:
path: './site'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v1
Cabe destacar que este fichero de configuración publicará una web que tengamos escrita con ficheros Markdown en el directorio docs. Si queremos publicar una web escrita con otro lenguaje, tendremos que modificar el fichero de configuración. A parte, vamos a utilizar una herramienta llamada mkdocs para generar la web a partir de los ficheros Markdown, además de utilizar un tema llamado Material for MkDocs.
Para poder utilizar mkdocs y Material for MkDocs, tendremos que crear un fichero de configuración llamado mkdocs.yml en el directorio principal del repositorio. Este fichero de configuración tendrá el siguiente contenido:
# mkdocs.yml - https://realpython.com/python-project-documentation-with-mkdocs
site_name: Formación en GitHub
theme:
name: material
features:
- content.code.annotate
palette:
primary: blue
accent: orange
font:
text: Exo 2
code: Hack
language: es
favicon: images/Isotipo-DEEPSUA_SinFondo.png
logo: images/Isologo-DEEPSUA_SinFondo.png
plugins:
- mkdocstrings:
handlers:
python:
options:
show_source: true
show_root_heading: true
heading_level: 3
markdown_extensions:
- pymdownx.highlight:
anchor_linenums:
true
- pymdownx.superfences
- pymdownx.inlinehilite
- pymdownx.snippets
- toc:
permalink: true
toc_depth: 6
baselevel: 2
- tables
nav:
- Home: index.md
- Introducción: intro.md
- Projects: projects.md
- Actions: actions.md
extra:
generator: false
Además, tendremos que crear un fichero llamado mkdocs-requirements.txt en el directorio principal del repositorio. Este fichero de configuración tendrá el siguiente contenido:
Simplemente, cuando llegue un push a la rama main, se ejecutará la action que hemos creado y se publicará la web en GitHub Pages.
Code Testing¶
En este apartado vamos a ver cómo podemos utilizar GitHub Actions para ejecutar tests en nuestro repositorio. Para ello, vamos a utilizar la herramienta unittest.
En la raiz del repositorio tenemos una carpeta llamada src que contiene la clase Triangulo. Esta clase tiene un método llamado tipoTriangulo que nos dice el tipo de triángulo que es, en función de la longitud de los lados que le enviemos por parámetros. Por otra parte, tenemos una carpeta llamada tests que contiene los tests que vamos a ejecutar para comprobar que el método tipoTriangulo funciona correctamente.
Si nos situamos en la raiz del repositorio, podemos ejecutar los tests con el siguiente comando:
Este comando nos va a ejecutar todos los tests que estén en el directorio tests y que empiecen por test. Si queremos ejecutar un test en concreto, podemos ejecutar el siguiente comando:
Para poder ejecutar los tests con GitHub Actions, tendremos que crear un fichero de configuración en el directorio .github/workflows del repositorio. Este fichero de configuración se va a llamar tests.yml y va a tener el siguiente contenido:
name: Tests
on:
push:
branches: ["main"]
pull_request:
branches: ["main"]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.9
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Run tests
run: python -m unittest discover -s tests -p "test*.py"
Este fichero de configuración va a ejecutar los tests cada vez que se haga un push a la rama main o cuando se haga un pull request a la rama main. Además, va a ejecutar los tests en una máquina virtual con Ubuntu.
Estiquetado de versiones¶
Cuando tumbamos código de la rama de desarrollo a la rama principal, es muy importante etiquetar la versión del código que estamos subiendo. Esto nos va a permitir tener un control de las versiones que vamos subiendo a la rama principal.
Para realizar esto, utilizamos los tags de Git. Para crear un tag en Git, podemos ejecutar el siguiente comando:
Este comando va a crear un tag llamado v1.0.0 en el repositorio. Si queremos ver todos los tags que tenemos en el repositorio, podemos ejecutar el siguiente comando:
Si queremos subir el tag a GitHub, podemos ejecutar el siguiente comando:
En este repositorio vamos a tener un fichero YAML llamado 'auto-prerelease.yml' en el directorio '.github/workflows'. Este fichero de configuración va a crear un tag cada vez que se haga un push a la rama main.
Este tag siempre será una pre-release. Esto significa que no será una versión estable, sino que será una versión de desarrollo que tiene pendiente alguna mejora o corrección antes de ser etiquetada como una versión estable.
El fichero de configuración tendrá el siguiente contenido:
name: "pre-release"
on:
push:
branches:
- "main"
- "develop"
permissions:
id-token: "write"
contents: "write"
packages: "write"
pull-requests: "read"
jobs:
pre-release:
name: "Pre Release"
runs-on: "ubuntu-latest"
steps:
- name: "Build & test"
run: |
echo "done!"
- uses: "marvinpinto/action-automatic-releases@latest"
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
automatic_release_tag: "latest"
prerelease: true
title: "Development Build"
En el caso de que queramos etiquetar una versión estable, se subirá un tag a la rama main y se creará una nueva release en GitHub. Para ello vamos a utilizar el fichero de configuración auto-release.yml que se encuentra en el directorio de los workflows.
Este fichero de configuración tendrá el siguiente contenido:
name: "auto-release"
on:
push:
tags:
- "v*"
permissions:
id-token: "write"
contents: "write"
packages: "write"
pull-requests: "read"
jobs:
tagged-release:
name: "Tagged Release"
runs-on: "ubuntu-latest"
steps:
- name: "Build & test"
run: |
echo "done!"
- uses: "marvinpinto/action-automatic-releases@latest"
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
prerelease: false
Easter egg: Avisos por Telegram¶
Mediante el uso de las GitHub Actions podemos enviar avisos por un chat de Telegram cada vez que se monte una nueva release. Para ello, vamos a utlizar el fichero de configuración telegram.yml que se encuentra en el directorio de los workflows.
También se podría configurar para otros menesteres como avisar cuando se abre una nueva issue o cuando se hace un pull request, entre otras cosas.
Este fichero de configuración tendrá el siguiente contenido:
name: notify-on-telegram
on:
workflow_run:
workflows: ["auto-release"]
types:
- completed
permissions:
id-token: "write"
contents: "write"
packages: "write"
pull-requests: "read"
jobs:
send_message:
name: "Notify on Telegram"
runs-on: "ubuntu-latest"
steps:
- name: "Send Telegram message"
uses: "appleboy/telegram-action@master"
with:
to: "${{ secrets.TELEGRAM_TO }}"
token: "${{ secrets.TELEGRAM_TOKEN }}"
format: "html"
dissable_web_page_preview: true
message: |
"¡Actualizaciones en <strong>${{ github.event.repository.name }}</strong>!
Se ha publicado una versión nueva: <code>${{ github.ref_name }}</code>.
Puedes ver los cambios en el <a href="https://github.com/${{ github.repository }}/releases/latest">changeLog</a>.
Además, no te olvides de consultar la <a href="https://deepsua.github.io/formacion_github/">documentación</a>."
De este fichero de configuración cabe destacar el uso de dos variables de entorno que se encuentran en el apartado de Settings de nuestro repositorio. Estas variables son: - TELEGRAM_TO: Es el identificador del chat de Telegram al que queremos enviar los mensajes. - TELEGRAM_TOKEN: Es el token de nuestro bot de Telegram.
Estas variables se crean en el apartado de Settings de nuestro repositorio. Para crearlas, vamos a Settings > Security > Secrets and variables > Actions y le damos click al botón New repository secret.
Para obtener el token de nuestro bot de Telegram, vamos a BotFather y le damos click al botón New bot. Le damos un nombre al bot y le damos click al botón Create bot. Una vez creado el bot, le damos click al botón API Token y copiamos el token que aparece en la pantalla.
Para obtener el identificador del chat de Telegram al que queremos enviar los mensajes, podemos utilizar el siguiente script con Python:
# Instalar la librería python-telegram-bot: pip3 install python-telegram-bot
# Guardar el script en un fichero llamado telegram.py
from telegram.ext import Updater, CommandHandler, CallbackContext
from telegram import Update
updater = Updater(token='TOKEN', use_context=True) # TOKEN es el token de nuestro bot de Telegram
dp = updater.dispatcher
jq = updater.job_queue
def currentChatInfo(update: Update, context: CallbackContext):
update.effective_message.reply_text(update.effective_chat.to_json())
dp.add_handler(CommandHandler('currentChatInfo', currentChatInfo))
updater.start_polling()
updater.idle()
# Ejecutar el script: python3 telegram.py
# Escribir al bot de Telegram: /currentChatInfo
Una vez ejecutado el script, escribimos al bot de Telegram el comando /currentChatInfo y nos devolverá un JSON con la información del chat. En este JSON, el campo id es el identificador del chat de Telegram al que queremos enviar los mensajes.
Tenemos el script de Python en el directorio src del repositorio.
Ahora ya sabes como crear un bot de Telegram y tienes un modelo muy básico para hacer pruebas. ¡Te animo a que juegues con Python y Telegram para crear tus propios bots!
Una vez añadimos las variables de entorno, ya podemos hacer etiquetar una nueva versión en el repositorio y ver como se envía un mensaje al chat de Telegram.