Lanzando GitHub Actions entre distintos repositorios


Introducción

En este post veremos cómo desde un workflow de GitHub Actions en un repositorio podemos invocar otro workflow de un repositorio distinto. La primera parte muestra los distintos tipos de eventos que pueden desencadenar un workflow, centrándose en el evento repository_dispatch. La segunda parte es un ejemplo práctico mostrando cómo dos repositorios diferentes pueden desencadenar/iniciar sus workflows mutuamente.

Eventos que desencadenan workflows

Como probablemente sepas, hay diferentes tipos de eventos que pueden iniciar la ejecución de un workflow de GitHub Actions. Los eventos más conocidos para desencadenar esta ejecución son push, pull_requestschedule.  Estos eventos cubren la mayoría de casos de uso, ya que normalmente queremos que los workflows se ejecuten cuando ciertos eventos se producen dentro del propio repositorio. Sin embargo, en ocasiones esto no es suficiente y es necesario que un workflow se desencadene a raíz de un evento externo (chatbot, CI externo, despliegue manual en producción tras QA, etc.).

Es aquí dónde el evento repository_dispatch es útil (en esta publicación se empleará para lanzar workflows entre distintos repositorios).

Para lanzar este evento, es preciso hacer una petición HTTP POST a este endpoint https://api.github.com/repos/:owner/:repo/dispatches.

Este endpoint espera 2 parámetros de entrada:

  • event_type: El contenido de este parámetro se recibirá en el payload del evento del workflow como el campo action.
  • client_payload: Objecto JSON con la información que queremos propagar al workflow, el valor de este parámetro estará disponible en el campo client_payload del payload del evento.

Para poder utilizar este endpoint será necesario estar autenticado y autorizado para acceder al repositorio. Con ese propósito se puede crear un token de acceso personal.

El endpoint puede ser invocado utilizando cURL:

Es importante resaltar que la cabecera Accept tiene valor application/vnd.github.everest-preview+json que no se corresponde con un media type estándar. A fecha de hoy este endpoint está en periodo de prueba y la API puede cambiar sin previo aviso.

Desencadenando eventos entre workflows de distintos repositorios

Para poder mostrar como podemos utilizar el evento repository_dispatch para lanzar ejecuciones de un workflow desde un repositorio hacia otro, he diseñado dos “pipelines” distintos de nombre AB:

Actions Remote Dispatch Sequence Diagram

Hay dos repositorios, A y B: El repositorio A comenzará la ejecución de su workflow cuando reciba un evento de tipo push o repository_dispatch. El respositorio B únicamente comenzará la ejecución de su workflow cuando reciba un evento de tipo repository_dispatch.

La secuencia comienza con un push al repositorio A (también hay una ejecución programada de modo que la secuencia se lance al menos una vez al día). Este primer evento desencadenará la ejecución inicial del workflow del repositorio A. Éste workflow hará una petición al endpoint para el dispatch del repositorio B con una acción de tipo ping y finalizará su ejecución.

El repositorio B comenzará una nueva ejecución de su workflow al recibir esta petición. Para el evento recibido de tipo ping, el workflow está configurado para responder con una petición al repositorio A con una acción de tipo pong y finalizar su ejecución.

El repositorio A comenzará una nueva ejecución de su workflow. Para el evento recibido de tipo pong, el workflow enviará una petición al repositorio B con una acción de tipo ack (acknowledge) y finalizará su ejecución. Esta será la última ejecución de workflows en el repositorio A para la secuencia.

Por último, el repositorio B comenzará la ejecución definitiva de su workflow. Para el evento de tipo ack, el workflow esta configurado para imprimir un mensaje informativo con el nombre del repositorio que invocó la acción. El workflow finaliza su ejecución y la secuencia concluye.

Access token

Uno de los principales requisitos para poder realizar peticiones al endpoint del repositorio cuyo workflow queremos arrancar es utilizar autenticación.

Lo primero es crear un token de acceso personal (PAT) siguiendo la guía de GitHub.

A continuación, necesitamos establecer las credenciales que hemos generado en un secreto en cada uno de los repositorios (A & B). Para cada uno de ellos, accederemos a settings->secrets page y añadiremos un nuevo secreto con el nombre ACCESS_TOKEN. El valor del token será nuestro usuario dos puntos y el token de acceso personal obtenido en el paso anterior (username:token).

GitHub Secrets - Access Token

Workflow del Repositorio A (ping)

Este repositorio contiene el workflow “iniciador”. Se iniciará cuando reciba un evento de tipo repository_dispatch, pero también cuando reciba eventos de tipo push y schedule. Los eventos push y schedule se emplearán para arrancar la acción “iniciadora” ping. Por otro lado, los eventos de tipo dispatch se utilizarán para arrancar la acción “acknowledge” (confirmación). Ambas acciones se pueden ver en la sección jobs del workflow.

Este workflow contiene únicamente un job (tarea) con dos pasos. El primer paso se invocará únicamente cuando se cumpla la siguiente condición github.event.action != 'pong'.  Para este ejemplo, eso significa que este paso se iniciará para todos los eventos push y schedule y para cualquier evento repository_dispatch que no sea de tipo pong. De este modo, cada vez que un usuario suba un commit al repositorio, o cada día a las 12:00, este paso se ejecutará. La acción run ejecuta el commando curl descrito previamente. En este caso, el tipo para event_type es ping y tiene como destino el repositorio B, en el payload se incluye el nombre del repositorio actual (disponible en la variable de entorno $GITHUB_REPOSITORY). Es importante resaltar como se utilizan las credenciales definidas en el paso anterior empleando la expresión ${{ secrets.ACCESS_TOKEN }}.

El segundo paso en el job se arrancará únicamente cuando se cumpla la siguiente condición github.event.action == 'pong', lo que ocurrirá únicamente cuando se reciba un evento respository_dispatch de tipo pong. Este paso enviará (también usando curl) una petición de confirmación al repositorio B.

Workflow del Repository B (pong)

Este repositorio contiene un workflow que únicamente podrá ser arrancado por control remoto, i.e. sólo se iniciará a partir de eventos repository_dispatch.

El workflow contiene una única tarea (job) con 2 pasos. El primer paso (Event Information) se ejecutará siempre, lo que hace es sencillamente imprimir información acerca del evento que desencadenó la ejecución. El segundo paso (PONG) se ejecutará únicamente cuando se reciba un evento cuya acción sea ping. En este paso se envia una petición (empleando el comando curl ya descrito) al repositorio A con un event_type pong.

Conclusión

En esta publicación hemos visto cómo podemos utilizar el evento repository_dispatch de GitHub Actions para iniciar ejecuciones de workflows entre distintos repositorios de GitHub. El mismo procedimiento podría emplearse para lanzar ejecuciones manuales mediante control remoto desde otros entornos, otras herramientas de integración continua, chatbots, etc.

El código fuente completo de este artículo puede encontrarse en GitHub (A & B).

Fuentes

GitHub Actions

Dejar un Comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *