Plantillas de flujo de trabajo


Este documento explica cómo configurar flujos de trabajo de Integración Continua (CI) para un track de lenguaje de Exercism usando GitHub Actions (GHA). Proporciona buenas prácticas y ejemplos que puedes usar para crear tus propios flujos de trabajo de CI, rápidos, confiables y robustos. Los flujos de trabajo de GHA que están en esta carpeta se pueden adaptar para que funcionen con cualquier CI, porque la estructura base seguirá siendo la misma.

Este documento:

  • Describe el flujo de trabajo de CI ideal
  • Analiza consideraciones y recomendaciones
  • Te ofrece algunas plantillas para usar
  • Te deja una guía para migrar desde Travis

Puedes encontrar un ejemplo de implementación de estos archivos de flujo de trabajo en exercism/javascript.

AYUDA: esto parece mucho trabajo 😓

El resto del documento está pensado para explicar cómo funcionan los flujos de trabajo. Si tienes prisa y solo quieres cambiar de Travis o Circle a GHA sin optimizar los scripts de PR, revisa nuestra guía de ~10 minutos sobre Migrar desde Travis.

Acciones de CI del track

Las acciones recomendadas para verificar que el contenido de tu repositorio tenga integridad son las siguientes:

  1. Linting con configlet para verificar config.json
  2. Verificar que no haya stubs
  3. Verificar la documentación (v3 requiere archivos nuevos; esto podría pasar a configlet)
  4. Hacer linting de los ejercicios usando una configuración de «mantenedores»
  5. Probar los ejercicios usando los archivos de ejemplo/exemplar (puede incluir un paso de compilación)

También puede haber acciones específicas del track. Por ejemplo:

  1. Verificar la integridad de las configuraciones de los ejercicios
  2. Verificar el formato de los archivos de los ejercicios

Y quizás quieras más verificaciones de calidad de vida, como:

  1. Asegurarte de que exista CONTRIBUTING
  2. Asegurarte de que haya un lockfile razonable para las dependencias
  3. Asegurarte de que los enlaces dentro de los archivos markdown sean válidos
  4. ...

Recomendaciones

Frecuencia de las verificaciones

Para cada acción, piensa con qué frecuencia debería ejecutarse.

  • El linting con configlet es tan importante (porque un track puede romperse si se rompe el config.json) que probablemente debería ejecutarse siempre, pero solo necesita ejecutarse una vez por commit.
  • La verificación de la existencia o la integridad de los archivos solo necesita ejecutarse una vez por commit.
  • Si se supone que un track debe ejecutarse con múltiples versiones de runtime o versiones del compilador, la compilación y las pruebas de los ejercicios deberían ejecutarse contra cada versión compatible
  • Probablemente los PR solo necesiten ejecutar acciones sobre los archivos agregados o modificados, pero como un archivo puede influir en un ejercicio, es más seguro ejecutar las acciones para el ejercicio si uno de sus archivos cambia.

Puede ser muy útil hacer que las acciones que deben ejecutarse también estén disponibles localmente. Esto significa que los scripts que hacen el trabajo real también se puedan ejecutar manualmente. Para lograrlo, no pongas la acción en línea dentro de los archivos de flujo de trabajo, sino que debes crear un script independiente. Por ejemplo, la verificación de stubs se puede escribir por completo en bash dentro del archivo de flujo de trabajo, pero la recomendación aquí es crear en su lugar un nuevo script ejecutable, scripts/ci-check.

«Pero el comando es muy corto, por ejemplo eslint . --ext ts --ext tsx».

Cuando este comando necesita actualizarse, ahora hay que actualizarlo en todos los lugares: la documentación, los archivos de flujo de trabajo y la mente de los mantenedores. Extraerlo a un script resuelve todo eso. Además, leer un archivo de flujo de trabajo puede ser muy abrumador.

Verificaciones en PR donde cambian los ejercicios

Los scripts scripts/pr y scripts/pr-check (consulta las plantillas) se ejecutan con varios argumentos, uno por cada archivo que se ha cambiado o agregado en este PR. Por ejemplo, si se actualizó two-fer, una llamada podría verse así:

scripts/pr exercises/two-fer/README.md exercises/two-fer/.meta/example.ext

Se recomienda ejecutar cualquier acción contra el ejercicio modificado y no contra el archivo modificado. Esto se debe a que cambiar un archivo probablemente genere cambios en todo el ejercicio (piensa en: la configuración, los paquetes).

¿Aún no estás listo? / ¿Es muy complejo?

Antes de implementar esta optimización, ¡puedes ignorarla sin problema! La guía de migración sugiere agregarla en una etapa posterior. Si se ignoran los argumentos de entrada, todas las verificaciones se ejecutarán sobre todos los ejercicios. No hay ningún problema con eso. Solo tardará más.

Verificaciones de integridad

Si el track tiene un único archivo de dependencias «de nivel superior» u otros archivos de configuración, agrega un paso de integridad (que exista junto a un scripts/sync o bin/sync, el cual copiaría todos los archivos de configuración a todos los ejercicios) que garantice que los archivos de nivel superior o base sean iguales al que se copió en los directorios de los ejercicios. Así, las dependencias se pueden actualizar, sincronizar en todo el repositorio y podemos garantizar que todos los ejercicios tengan la misma configuración.

Una forma común de lograr esto es usar una suma de verificación. Ubuntu (y varias otras distribuciones de Linux) incluye una herramienta llamada sha1sum, pero serviría usar cualquier método para aplicar un hash o reducir el archivo de configuración (md5, sha1, crc32) a un valor de suma de verificación:

$ sha1sum README.md
cd58091c5043bf21f00d39ff1740d8b2976deeff *README.md

Verificaciones de seguridad

Si el track usa flujos de trabajo adicionales que requieren acceso al token de GitHub u otros secretos, la buena práctica es fijar todas las acciones usadas en el flujo de trabajo a un commit específico. Consulta la guía de endurecimiento de seguridad de GitHub para más detalles.

Por ejemplo:

- uses: julia-actions/setup-julia@v1
+ uses: julia-actions/setup-julia@d26d1111976eae5f00db04f0515ab744ec9cd79e # 1.3.1

Si las herramientas tienen lockfiles para la gestión de dependencias, considera agregarlos al repositorio y usar un «lockfile congelado» dentro de los archivos de flujo de trabajo. Por ejemplo: npm ci, yarn install --frozen-lockfile y bundle install --frozen. Esto garantiza que el lockfile esté actualizado al cambiar dependencias y evita que entren paquetes maliciosos.

Plantillas

En este directorio hay, como mínimo, las siguientes plantillas:

  • configlet.yml: Este flujo de trabajo descarga el binario más reciente de configlet y le hace linting a este repositorio. Se ejecuta en cada commit. Para los PR, se ejecuta sobre el commit actual y sobre un árbol «después del merge».
  • ci.yml: Este flujo de trabajo solo se ejecuta en la rama principal, una vez por cada commit.
    1. Ejecuta un comando de «pre-check» (verificación de stubs, linting, documentación, etc.) para todos los ejercicios
    2. Ejecuta un comando de «ci» (compilar y probar) para varias versiones, para todos los ejercicios
  • pr.ci.yml: Este flujo de trabajo solo se ejecuta en los PR, una vez por cada commit.
    1. Ejecuta un comando de «pre-check» (verificación de stubs, linting, documentación, etc.) para los archivos modificados
    2. Ejecuta un comando de «ci» (compilar y probar) para varias versiones, para los ejercicios modificados

Los flujos de trabajo que no son de PR también se pueden activar mediante workflow_dispatch.

Cada archivo tiene indicado en la parte superior qué «scripts» deberían estar disponibles. Si quieres que sean binarios, reemplaza scripts/xxx por bin/xxx. Algunas herramientas requerirán que los binarios estén dentro de una carpeta bin.

  • scripts/ci: un script que debe compilar y probar todos los ejercicios, usando las soluciones de ejemplo contra las pruebas
  • scripts/ci-check: un script que debe hacer linting de todos los ejercicios y, opcionalmente, verificar los stubs, la integridad de la configuración y más
  • scripts/pr: igual que scripts/ci, pero solo debe ejecutarse para los ejercicios resueltos a partir de las rutas dadas como entrada
  • scripts/pr-check: igual que scripts/ci-check, pero solo debe ejecutarse para los archivos o ejercicios resueltos a partir de las rutas dadas como entrada

Solución de problemas

Si tienes algún problema o quieres que alguien revise tus flujos de trabajo, avisa al equipo @exercism/github-actions.

Cambiaste un archivo de nivel superior que debería activar una ejecución de CI en todos los ejercicios

Al momento de escribir esto, pr.ci.yml solo permite pruebas por «extensión». Lo ideal sería actualizarlo para que se active siempre que se cambien ciertos archivos (por ejemplo, el binario para ejecutar las pruebas). Sin embargo, estos cambios suelen ser poco frecuentes y los hacen los mantenedores, así que probablemente sea suficientemente seguro que ci.yml se ejecute en main, siempre, para todo.

Creaste un archivo scripts/xxx en Windows y ahora no funciona en {other OS}

De forma predeterminada, los archivos creados en Windows no tienen metadatos incrustados en el índice de git sobre si son ejecutables, porque el modelo de permisos en Windows es diferente. De forma predeterminada, Git usa los metadatos del índice de git para determinar si el archivo debería ser ejecutable en sistemas basados en POSIX y, por lo tanto, hace que el archivo scripts/xxx NO sea ejecutable.

git update-index --chmod=+x scripts/xxx
git commit -m "Make scripts/xxx executable"