GitHub Actions: buenas prácticas


Este documento de trabajo es una recopilación de buenas prácticas para usar GitHub Actions. Si tienes alguna sugerencia o algo que añadir, abre una pull request en GitHub.

Recopilación de buenas prácticas

Establece tiempos de espera para los flujos de trabajo

De forma predeterminada, GitHub Actions detiene los flujos de trabajo al cabo de 6 horas si para entonces no han terminado. Muchos flujos de trabajo no necesitan ni de lejos tanto tiempo para terminar, pero a veces se producen errores inesperados o una tarea se queda colgada hasta que la ejecución del flujo de trabajo se cancela 6 horas después de haber comenzado. Por eso se recomienda especificar un tiempo de espera más corto.

El tiempo de espera ideal depende de cada flujo de trabajo, pero 30 minutos suelen ser más que suficientes para los flujos de trabajo que se usan en los repositorios de Exercism.

Esto tiene las siguientes ventajas:

  • Las PR no se quedarán medio día pendientes de la CI, los problemas se pueden detectar a tiempo o las ejecuciones del flujo de trabajo se pueden reiniciar.
  • El número de compilaciones paralelas totales es limitado; las tareas que se quedan colgadas no causarán problemas a otras PR si se cancelan a tiempo.

Ejemplo

jobs:
  configlet:
    timeout-minutes: 30
    runs-on: ubuntu-latest
    steps:
      - [...]

Plantéate si las acciones (de terceros) son realmente necesarias

Las acciones deberían tratarse como las dependencias de tu lenguaje de programación favorito1: son código escrito por terceros, fuera del control de Exercism. Aunque confíes en los autores de la acción, puede producirse una toma de control hostil del repositorio que, indirectamente, dé a esas personas acceso a los repositorios de Exercism, incluido acceso de escritura.

Por lo tanto, deberías plantearte con cuidado si de verdad merece la pena introducir una acción nueva o si es mejor trasladar el código a una acción (nueva) bajo el control de Exercism.

También conviene comprobar si la acción recibe mantenimiento activo, por ejemplo revisando la actividad reciente del repositorio o asegurándote de que la acción pertenece a una organización en lugar de a una cuenta individual.

Las acciones publicadas por GitHub o por la organización de Exercism se pueden considerar, por lo general, más o menos seguras para incluirlas sin necesidad de un análisis especial.

Limita el alcance del token del flujo de trabajo

De forma predeterminada, el token de acceso que se da al flujo de trabajo tiene permisos muy amplios, tanto de lectura como de escritura.

El principio de menor privilegio también debería aplicarse a los flujos de trabajo.

Puedes especificar qué permisos necesita un flujo de trabajo de forma individual para cada flujo de trabajo.

Ejemplo

Si un flujo de trabajo solo necesita leer el contenido de un repositorio pero no escribir en él, por ejemplo porque es una comprobación normal de la CI, puedes restringir el token de la siguiente manera:

permissions:
  contents: read

Consulta la documentación de GitHub para ver la lista completa de permisos.

Fija las acciones a SHAs

Cuando uses otras acciones, fíjalas a un commit (mediante su SHA), no a una rama o a una etiqueta. Así te aseguras de que se ejecute siempre el mismo código, algo que no está garantizado cuando fijas una rama o una etiqueta.

Esto tiene dos ventajas:

  1. Hace que tu compilación sea estable
  2. Impide que un atacante cambie una rama o una etiqueta para que apunte a código malicioso

La única excepción a esta regla podrían ser las acciones que hayamos creado nosotros mismos (Exercism).

Cómo encontrar el SHA del commit

Normalmente querrás fijarte al SHA del commit de una versión concreta. Para encontrar el SHA del commit de una versión, ve a la página de versiones del repositorio de la acción (por ejemplo, https://github.com/actions/checkout/releases). Busca la versión que quieras usar y haz clic en el SHA abreviado (por ejemplo, a12a394) que aparece en la sección de resumen a la izquierda de la versión. Entonces se te redirigirá a la página de detalles de la versión, donde se indica el SHA completo del commit que puedes usar.

Ejemplo

- name: Checkout code
  uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846

Fija los ejecutores de pruebas a una versión

La mayoría de los flujos de trabajo se ejecutarán en los ejecutores compatibles de GitHub. Cuando uses uno de estos ejecutores, usa una versión concreta en lugar de la última versión.

Así te aseguras de que el flujo de trabajo se ejecute siempre en el mismo ejecutor, lo que hace que tu compilación sea estable.

Ejemplo

Usa:

runs-on: ubuntu-22.04

en lugar de:

runs-on: ubuntu-latest

Plantéate configurar una estrategia de concurrencia

A menudo no es necesario ni útil ejecutar la CI en commits intermedios si mientras tanto se ha subido un commit más reciente.

Puedes configurar una estrategia de concurrencia para cancelar automáticamente los flujos de trabajo que estén en ejecución en el mismo contexto.

Ejemplo

Para cancelar las compilaciones intermedias en una PR, puedes usar esta configuración de concurrencia:

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
Aviso de terceros

El ejemplo anterior se basa en el flujo de trabajo de CI de PkgTemplates.jl, publicado bajo la licencia MIT:

MIT License

Copyright (c) 2017-2020 Chris de Graaf, Invenia Technical Computing Corporation

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Plantéate qué desencadenadores se necesitan de verdad

Lee la guía «Fortalecimiento de la seguridad para GitHub Actions»

Las prácticas mencionadas arriba no son ni mucho menos exhaustivas. Para una guía completa sobre buenas prácticas de seguridad que te permitan usar GitHub Actions de forma segura, consulta la guía de seguridad de GitHub.

Lista de comprobación de flujos de trabajo

Puedes usar la siguiente lista de comprobación para verificar que un flujo de trabajo sigue las buenas prácticas. La lista no pretende ser completa, sino que se centra en los puntos más importantes.

Versión para copiar y pegar, por ejemplo para PR

  1. salvo que el lenguaje use el ecosistema npm. ↩