Al igual que en los lenguajes de programación, el uso de variables para almacenar datos es muy útil en GitHub Actions. Gracias a ellas, podemos definir datos de configuración que podemos utilizar en el flujo de trabajo. Como algunos datos pueden contener datos reservados o privados como, por ejemplo, contraseñas, tokens, claves de API, etc., utilizaremos variables especiales conocidas como secretos.

Al finalizar, sabrá:

  • Qué es y cómo se definen variables específicas de un flujo de trabajo, un trabajo o un paso.

  • Cuáles son las variables predefinidas que vienen con GitHub Actions.

  • Qué es y cómo se definen los secretos.

  • Para qué sirve el secreto GITHUB_TOKEN.

Introducción

Son muchas las ocasiones en las que tenemos que almacenar datos para su posterior uso en el flujo de trabajo, ya sea en el propio flujo, en uno de sus trabajos o incluso en un paso de un trabajo. Por suerte, esto es posible y podemos hacerlo mediante el uso de variables y secretos. Es muy importante distinguir el ámbito y el tipo de dato para su ubicación en la sección correspondiente.

Variables

Una variable es un elemento para almacenar un dato como en cualquier lenguaje de programación. El ámbito (scope) de una variable delimita dónde se puede utilizar. Distinguimos tres ámbitos: a nivel de flujo de trabajo, de trabajo o de paso. En los tres casos, se definen mediante una propiedad de tipo objeto env, donde cada una de sus propiedades representa una variable. El nombre de la propiedad es el nombre de la variable; y su valor, como es de esperar, el valor de la variable. Así pues, si definimos una variable en la propiedad env del flujo de trabajo, su ámbito será todo el flujo; en cambio, si lo hacemos en un trabajo, sólo ese trabajo.

Ejemplo:

env:
  version: ${{ inputs.version }}
  os: ${{ inputs.os }}

Acceso a variables

Si necesitamos acceder al valor de una variable en un valor textual de una propiedad, podemos hacerlo mediante el siguiente formato $nombreVariable. Ejemplo:

run: npm i $global $paquete

Contexto env

Si necesitamos acceder al valor de una variable en una expresión, usaremos el contexto env (env context), que consiste en un objeto con una propiedad para cada variable disponible en el punto en el que nos encontramos. Si estamos ante un paso, contendrá las específicas del paso, pero también las de su trabajo y las del flujo de trabajo. De ahí, lo de en el punto en el que nos encontramos.

Actualización de variables

Podemos actualizar el valor de una variable mediante un trabajo, usando un paso de shell similar a:

- run: echo "variable=valor" >> $GITHUB_ENV

He aquí un ejemplo ilustrativo que actualiza el valor de una variable version cuyo valor contiene un texto como “1.2.3”, incluidas las comillas dobles, una vez convertida a v1.2.3:

- run: echo "version=v${version:1:-1}" >> $GITHUB_ENV

No olvide hacer el cambio como se muestra. $GITHUB_ENV es una variable del flujo de trabajo que referencia a un archivo especial usado, internamente por GitHub, para fijar valores de variables de entorno.

Variables predefinidas

Una variable predefinida (default variable) es aquella que viene de fábrica con GitHub Actions. He aquí algunas de ellas:

Variable Descripción
CI Siempre vale true.
GITHUB_ACTIONS Indica si está siendo ejecutado por GitHub Actions. Siempre a true.
GITHUB_ACTOR Nombre de la cuenta del usuario que provocó la ejecución del flujo de trabajo.
GITHUB_EVENT_NAME Nombre del evento que disparó la ejecución del flujo de trabajo.
GITHUB_REPOSITORY Nombre del repositorio en formato propietario/repositorio.
GITHUB_REPOSITORY_OWNER Nombre del propietario del repositorio.
GITHUB_RETENTION_DAYS Número de días que se retienen los logs y los artefactos.
RUNNER_OS Nombre del sistema operativo: Linux, Windows o macOS.

Secretos

Un secreto (secret) es un dato cuyo valor debe mantenerse a buen recaudo como, por ejemplo, un token, una contraseña, una clave, etc. Así, por ejemplo, si necesitamos un token para publicar en un registro como, por ejemplo, el de NPM, primero, tendremos que obtenerlo de https://www.npmjs.com y, a continuación, guardarlo como secreto para que nadie tenga acceso a él, salvo el flujo de trabajo.

Los secretos no son más que variables cifradas cuyo contenido se accede descifrado, pero se mantiene cifrado siempre que sea necesario para mantener así su privacidad. GitHub Actions garantiza que nunca se expongan en los logs y se encarga de mantenerlos cifrados y de descifrarlos cuando los usamos.

Atendiendo a dónde se almacenan, se distingue entre secretos de repositorio y de organización. Un secreto de repositorio (repository-level secret) es aquel que se almacena a nivel de repositorio y sólo se puede utilizar con flujos de trabajo definidos en ese mismo repositorio. Mientras que un secreto de organización (organization-level secret) se define a nivel de cuenta y se puede utilizar en varios repositorios de esa cuenta.

Creación de secretos de repositorio

Los secretos de repositorio se crean en GitHub, mediante la pestaña Settings del propio repositorio. Bajo General > Security > Secrets > Actions, encontramos los secretos ya dados de alta y mediante el botón New repository secret podemos crear uno nuevo:

Secretos de repositorio

Contexto secrets

Para acceder a un secreto, se usa el contexto secrets (secrets context), el cual no es más que un objeto con una propiedad para cada secreto disponible. Por ejemplo, si hemos definido el secreto NPM_TOKEN para que almacene el token que debemos utilizar para interactuar con el registro de NPM, podremos solicitar su valor mediante una expresión como la siguiente:

${{ secrets.NPM_TOKEN }}

Secreto predefinido GITHUB_TOKEN

Cuando se necesita acceder al repositorio Git actual, se necesita un token. Este token lo genera automáticamente GitHub Actions y lo pone a nuestra disposición mediante el secreto GITHUB_TOKEN. Más concretamente, este token es específico y se autogenera para cada trabajo, es decir, se crea para ejecutar un determinado trabajo. Pero como se genera automáticamente para cada uno de ellos, en principio, esto no debería ser un problema para nosotros. Como es un secreto, accederemos a él como a cualquier otro, mediante el contexto secrets:

${{ secrets.GITHUB_TOKEN }}

Es importante que no olvide que este token es específico del repositorio Git actual. No permitirá el acceso a otros repositorios, ni aun si son públicos.

Gracias a este token, podemos acceder y hacer cambios en un repositorio mediante sus flujos de trabajo.

Propiedad permissions de un trabajo o flujo de trabajo

En ocasiones, necesitamos que el token emitido para un trabajo disponga de determinados permisos. La propiedad permissions nos permite fijar determinados permisos necesarios. Se puede indicar a nivel de flujo, lo que hará que se apliquen a todos sus trabajos; o bien, a nivel de un trabajo concreto, fijándolos para ese trabajo en cuestión.

Esta propiedad es un objeto donde cada una de sus propiedades representa un permiso cuyo valor puede ser read, write o none. Su esquema es como sigue:

permissions:
  actions: read|write|none
  checks: read|write|none
  contents: read|write|none
  deployments: read|write|none
  id-token: read|write|none
  issues: read|write|none
  discussions: read|write|none
  packages: read|write|none
  pages: read|write|none
  pull-requests: read|write|none
  repository-projects: read|write|none
  security-events: read|write|none
  statuses: read|write|none

Cuando se desea tener permiso de lectura a todo, se puede indicar permissions: read-all. Para escritura, permissions: write-all.

Por buenas prácticas, se recomienda seguir el principio de menor privilegio (principle of least privilege), norma o idea fundamental que dice que hay que indicar sólo aquellos permisos necesarios, ni más ni menos, para poder llevar a cabo lo que se necesita. Por lo tanto, si solo necesita leer, fijaremos:

# lectura de todo
permissions: read-all

# lectura de sólo el contenido
permissions:
  contents: read