Skip to main content

Evaluación de expresiones en flujos de trabajo y acciones

Puedes evaluar las expresiones en los flujos de trabajo y acciones.

Nota: Actualmente los ejecutores hospedados en GitHub no se admiten en GitHub Enterprise Server. Puede ver más información sobre la compatibilidad futura planeada en GitHub public roadmap.

Acerca de las expresiones

Puedes utilizar expresiones para configurar variables de ambiente con programación en los archivos de flujo de trabajo y contextos de acceso. Una expresión puede ser cualquier combinación de valores literales, referencias a un contexto o funciones. Puedes combinar valores literales, referencias de contexto y funciones usando operadores. Para obtener más información sobre los contextos, consulta "Acceso a información contextual sobre ejecuciones de flujo de trabajo".

Las expresiones se utilizan comúnmente con la palabra clave condicional if en un archivo de flujo de trabajo para determinar si un paso debe ejecutarse. Cuando un condicional if es true, el paso se ejecutará.

Debes usar una sintaxis específica para decirle a GitHub que evalúe una expresión en lugar de tratarla como una cadena.

${{ <expression> }}

Nota: La excepción a esta regla es cuando se usan expresiones en una cláusula if donde, opcionalmente, puede omitir ${{ y }}. Para más información sobre los condicionales if, consulte "Sintaxis del flujo de trabajo para Acciones de GitHub".

Advertencia: Cuando cree flujos de trabajo y acciones, siempre debe considerar si el código podría ejecutar entradas no confiables de atacantes potenciales. Se tratará a algunos contextos como una entrada no confiable, ya que un atacante podrían insertar su propio contenido malintencionado. Para obtener más información, vea «Fortalecimiento de seguridad para GitHub Actions».

Ejemplo de parámetros en una variable de entorno

env:
  MY_ENV_VAR: ${{ <expression> }}

Literales

Como parte de una expresión, puedes usar los tipos de datos boolean, null, number o string.

Tipo de datosValor literal
booleantrue o false
nullnull
numberCualquier formato de número compatible con JSON.
stringNo es necesario incluir las cadenas en ${{ y }}. Sin embargo, en caso de que lo hagas, debes utilizar comillas simples (') alrededor de la cadena. Para utilizar una comilla simple literal, escápala utilizando una comilla simple adicional (''). El ajuste con comillas dobles (") producirá un error.

Ten en cuenta que en los condicionales, los valores falsificados (false, 0, -0, "", '', null) se convierten a false y los verdaderos (true y otros valores no falsificados) se convierten a true.

Ejemplo de literales

env:
  myNull: ${{ null }}
  myBoolean: ${{ false }}
  myIntegerNumber: ${{ 711 }}
  myFloatNumber: ${{ -9.2 }}
  myHexNumber: ${{ 0xff }}
  myExponentialNumber: ${{ -2.99e-2 }}
  myString: Mona the Octocat
  myStringInBraces: ${{ 'It''s open source!' }}

Operadores

OperadorDescripción
( )Agrupación lógica
[ ]Índice
.Desreferencia de propiedad
!Not
<Menor que
<=Menor o igual que
>Mayor que
>=Mayor o igual que
==Igual
!=No igual a
&&Y
||Or

Notas:

  • GitHub ignora las mayúsculas y minúsculas al comparar cadenas.
  • steps.<step_id>.outputs.<output_name> se evalúa como una cadena. Debes usar una sintaxis específica para decirle a GitHub que evalúe una expresión en lugar de tratarla como una cadena. Para más información, consulta "Acceso a información contextual sobre ejecuciones de flujo de trabajo".
  • Para la comparación numérica, la función fromJSON() se puede usar para convertir una cadena en un número. Para más información sobre la función fromJSON(), consulta "fromJSON".

GitHub realiza comparaciones de igualdad flexible.

  • Si los tipos no coinciden, GitHub fuerza el tipo a un número. GitHub fusiona los tipos de datos con un número usando estas conversiones:

    TipoResultado
    Null0
    Booleantrue devuelve 1.
    false devuelve 0.
    StringSe analiza desde cualquier formato de número JSON legal; de lo contrario, NaN.
    Nota: La cadena vacía devuelve 0.
    ArrayNaN
    ObjectNaN
  • Cuando NaN es uno de los operandos de cualquier comparación relacional (>, <, >=, <=), el resultado siempre es false. Para obtener más información, consulta la "documentación de NaN Mozilla".

  • GitHub ignora las mayúsculas y minúsculas al comparar cadenas.

  • Los objetos y matrices solo se consideran iguales cuando son la misma instancia.

GitHub ofrece un operador ternario como comportamiento que puede usar en expresiones. Mediante el uso de un operador ternario de esta manera, puede establecer dinámicamente el valor de una variable de entorno en función de una condición, sin tener que escribir bloques if-else independientes para cada opción posible.

Ejemplo

env:
  MY_ENV_VAR: ${{ github.ref == 'refs/heads/main' && 'value_for_main_branch' || 'value_for_other_branches' }}

En este ejemplo, se usa un operador ternario para establecer el valor de la variable de entorno MY_ENV_VAR en función de si la referencia de GitHub está establecida en refs/heads/main o no. Si es así, la variable se establece en value_for_main_branch. En caso contrario, se establece en value_for_other_branches. Es importante tener en cuenta que el primer valor después de && debe ser verdadero. De lo contrario, siempre se devolverá el valor después de ||.

Functions

GitHub ofrece un conjunto de funciones integradas que puedes usar en expresiones. Algunas funciones fusionan valores en una cadena para realizar las comparaciones. GitHub fusiona los tipos de datos con una cadena usando estas conversiones:

TipoResultado
Null''
Boolean'true' o 'false'
NumberFormato decimal, exponencial para números grandes
ArrayLas matrices no se convierten en cadenas
ObjectLos objetos no se convierten en cadenas

contains

contains( search, item )

Devuelve true si search contiene item. Si search es una matriz, esta función devuelve true si item es un elemento de la matriz. Si search es una cadena, esta función devuelve true si item es una subcadena de search. Esta función no distingue mayúsculas de minúsculas. Fusiona valores en una cadena.

Ejemplo usando una cadena

contains('Hello world', 'llo') devuelve true.

Ejemplo de uso de un filtro de objetos

contains(github.event.issue.labels.*.name, 'bug') devuelve true si el problema relacionado con el evento tiene una etiqueta "bug".

Para más información, consulta "Filtros de objetos".

Ejemplo que coincide con una matriz de cadenas

En lugar de escribir github.event_name == "push" || github.event_name == "pull_request", puedes usar contains() con fromJSON() para comprobar si una matriz de cadenas contiene un item.

Por ejemplo, contains(fromJSON('["push", "pull_request"]'), github.event_name) devuelve true si github.event_name es "push" o "pull_request".

startsWith

startsWith( searchString, searchValue )

Devuelve true cuando searchString empieza por searchValue. Esta función no distingue mayúsculas de minúsculas. Fusiona valores en una cadena.

Ejemplo de startsWith

startsWith('Hello world', 'He') devuelve true.

endsWith

endsWith( searchString, searchValue )

Devuelve true si la cadena searchString está situada al final de la cadena searchValue. Esta función no distingue mayúsculas de minúsculas. Fusiona valores en una cadena.

Ejemplo de endsWith

endsWith('Hello world', 'ld') devuelve true.

format

format( string, replaceValue0, replaceValue1, ..., replaceValueN)

Reemplaza los valores de string, con la variable replaceValueN. Las variables de string se especifican mediante la sintaxis {N}, donde N es un entero. Debes especificar al menos un replaceValue y string. No hay un máximo para el número de variables (replaceValueN) que puedes usar. Escapar las llaves utilizando llaves dobles.

Ejemplo de format

format('Hello {0} {1} {2}', 'Mona', 'the', 'Octocat')

Devuelve 'Hello Mona the Octocat'.

Ejemplo de evasión de llaves

format('{{Hello {0} {1} {2}!}}', 'Mona', 'the', 'Octocat')

Devuelve '{Hello Mona the Octocat!}'.

join

join( array, optionalSeparator )

El valor de array puede ser una matriz o una cadena. Todos los valores de array se concatenan en una cadena. Si proporcionas optionalSeparator, se inserta entre los valores concatenados. De lo contrario, se usa el separador predeterminado ,. Fusiona valores en una cadena.

Ejemplo de join

join(github.event.issue.labels.*.name, ', ') puede devolver "bug, help wanted"

toJSON

toJSON(value)

Devuelve una representación JSON con formato mejorado de value. Puedes usar esta función para depurar la información suministrada en contextos.

Ejemplo de toJSON

toJSON(job) puede devolver { "status": "success" }

fromJSON

fromJSON(value)

Devuelve un objeto JSON o un tipo de datos JSON para value. Puedes usar esta función para proporcionar un objeto JSON como una expresión evaluada o convertir cualquier tipo de datos que se pueda representar en JSON o JavaScript, como cadenas, valores booleanos, valores NULL, matrices y objetos.

Ejemplo de devolver un objeto JSON

Este flujo de trabajo configura una matriz de JSON en un trabajo, y lo pasa al siguiente trabajo utilizando una salida y fromJSON.

YAML
name: build
on: push
jobs:
  job1:
    runs-on: ubuntu-latest
    outputs:
      matrix: ${{ steps.set-matrix.outputs.matrix }}
    steps:
      - id: set-matrix
        run: echo "matrix={\"include\":[{\"project\":\"foo\",\"config\":\"Debug\"},{\"project\":\"bar\",\"config\":\"Release\"}]}" >> $GITHUB_OUTPUT
  job2:
    needs: job1
    runs-on: ubuntu-latest
    strategy:
      matrix: ${{ fromJSON(needs.job1.outputs.matrix) }}
    steps:
      - run: echo "Matrix - Project ${{ matrix.project }}, Config ${{ matrix.config }}"

Ejemplo de devolver un tipo de datos JSON

Este flujo de trabajo usa fromJSON para convertir variables de entorno de una cadena a un valor booleano o entero.

YAML
name: print
on: push
env:
  continue: true
  time: 3
jobs:
  job1:
    runs-on: ubuntu-latest
    steps:
      - continue-on-error: ${{ fromJSON(env.continue) }}
        timeout-minutes: ${{ fromJSON(env.time) }}
        run: echo ...

El flujo de trabajo usa la función fromJSON() para convertir la variable de entorno continue de una cadena en un valor booleano, lo que le permite determinar si desea continuar con el error o no. Del mismo modo, convierte la variable de entorno time de una cadena en un entero y establece el tiempo de espera del trabajo en minutos.

hashFiles

hashFiles(path)

Devuelve un hash único para el conjunto de archivos que coincide con el patrón path. Puede proporcionar un único patrón path o varios patrones path separados por comas. path es relativo al directorio GITHUB_WORKSPACE y solo puede incluir archivos dentro de GITHUB_WORKSPACE. Esta función calcula un hash SHA-256 individual para cada archivo coincidente, y luego usa esos hashes para calcular un hash SHA-256 final para el conjunto de archivos. Si el patrón path no coincide con ningún archivo, devuelve una cadena vacía. Para obtener más información sobre SHA-256, consulta "SHA-2".

Puedes usar caracteres de coincidencia de patrones para encontrar nombres de archivos. La coincidencia de patrones de hashFiles se ajusta a la coincidencia de patrones globales y no distingue mayúsculas de minúsculas en Windows. Para obtener más información sobre los caracteres de coincidencia de patrones admitidos, consulte la sección Patrones de la documentación de @actions/glob.

Ejemplo con un solo patrón

Coincide con cualquier archivo package-lock.json del repositorio.

hashFiles('**/package-lock.json')

Ejemplo con patrones múltiples

Crea un hash para todos los archivos package-lock.json y Gemfile.lock del repositorio.

hashFiles('**/package-lock.json', '**/Gemfile.lock')

Funciones de verificación del estado

Puedes usar las siguientes funciones de comprobación de estado como expresiones en condicionales if. Se aplica una comprobación de estado predeterminada de success() a menos que incluyas una de estas funciones. Para más información sobre los condicionales if, consulte "Sintaxis del flujo de trabajo para Acciones de GitHub" y "Sintaxis de metadatos para Acciones de GitHub".

success

Devuelve true cuando todos los pasos anteriores se han realizado correctamente.

Ejemplo de success

steps:
  ...
  - name: The job has succeeded
    if: ${{ success() }}

Siempre

Hace que el paso siempre se ejecute y devuelve true, incluso cuando se cancela. La expresión always se usa mejor en el nivel de paso o en las tareas que se espera ejecutar incluso cuando se cancela un trabajo. Por ejemplo, puedes usar always para enviar registros incluso cuando se cancela un trabajo.

Advertencia: Evita el uso de always para cualquier tarea que pueda sufrir un error crítico, como obtener orígenes; de lo contrario, el flujo de trabajo podría bloquearse hasta que se agote el tiempo de espera. Si quieres ejecutar un trabajo o un paso independientemente de si se ha ejecutado correctamente o no, usa la alternativa recomendada: if: ${{ !cancelled() }}.

Ejemplo de always

if: ${{ always() }}

cancelled

Devuelve true si el flujo de trabajo se ha cancelado.

Ejemplo de cancelled

if: ${{ cancelled() }}

failure

Devuelve true cuando se produce un error en cualquier paso anterior de un trabajo. Si tienes una cadena de trabajos dependientes, failure() devuelve true si se produce un error en algún trabajo antecesor.

Ejemplo de failure

steps:
  ...
  - name: The job has failed
    if: ${{ failure() }}

error con condiciones

Puedes incluir condiciones adicionales para que un paso se ejecute después de un error, pero todavía debes incluir failure() para invalidar la comprobación de estado predeterminada de success() que se aplica automáticamente a las condiciones if que no contienen una función de comprobación de estado.

Ejemplo de failure con condiciones
steps:
  ...
  - name: Failing step
    id: demo
    run: exit 1
  - name: The demo step has failed
    if: ${{ failure() && steps.demo.conclusion == 'failure' }}

Filtros de objetos

Puedes usar la sintaxis * para aplicar un filtro y seleccionar los elementos coincidentes en una colección.

Por ejemplo, considera una matriz de objetos denominada fruits.

[
  { "name": "apple", "quantity": 1 },
  { "name": "orange", "quantity": 2 },
  { "name": "pear", "quantity": 1 }
]

El filtro fruits.*.name devuelve la matriz [ "apple", "orange", "pear" ].

También puedes usar la sintaxis * en un objeto. Por ejemplo, supongamos que tienes un objeto denominado vegetables.


{
  "scallions":
  {
    "colors": ["green", "white", "red"],
    "ediblePortions": ["roots", "stalks"],
  },
  "beets":
  {
    "colors": ["purple", "red", "gold", "white", "pink"],
    "ediblePortions": ["roots", "stems", "leaves"],
  },
  "artichokes":
  {
    "colors": ["green", "purple", "red", "black"],
    "ediblePortions": ["hearts", "stems", "leaves"],
  },
}

El filtro vegetables.*.ediblePortions podría evaluarse como:


[
  ["roots", "stalks"],
  ["hearts", "stems", "leaves"],
  ["roots", "stems", "leaves"],
]

Dado que los objetos no conservan el orden, no se puede garantizar el orden de la salida.