Ir al contenido

El reporter de Cypress en tu CI

El reporter se ejecuta dentro de npx cypress run: pasa el token al paso que ejecuta tus pruebas, y cada resultado se envía cuando termina la ejecución. No hay un paso de envío aparte. Todos los ejemplos suponen que el reporter, su plugin y su archivo de soporte están registrados como en Primeros pasos.

  • El token es un secreto, el ID del Proyecto no. Guarda el token de aplicación (de la tarjeta Cypress en Workspace › Integraciones) como un secreto llamado PROBARA_API_TOKEN. Pon el ID del Proyecto en cypress.config.js (projectId) o en el pipeline (PROBARA_PROJECT).
  • Node.js 22.12 o posterior para el Node.js que arranca cypress, que es donde se ejecuta el plugin, y los navegadores y las bibliotecas del sistema que Cypress necesita en el agente.
  • Las pruebas fallidas hacen fallar el paso, los problemas al reportar no: el código de salida de cypress run sigue siendo el número de sus pruebas fallidas.
  • cypress-io/github-action y npm test también funcionan: el reporter sale de la configuración, no del comando. Pasa a su paso el mismo entorno.
  • Fija la versión en package.json (o en el lockfile), para que una versión nueva nunca cambie un pipeline por sorpresa. La CLI no es una dependencia del reporter: los pasos de abajo que la usan fijan su versión en el propio comando (npx --yes @probara/cli@0.3). Con @probara/cli en tus devDependencies, npx @probara/cli después de npm ci ejecuta la versión del lockfile.
  • Los builds de forks no reportan nada: sin el secreto, el reporter no envía nada y las pruebas se ejecutan como siempre. La CLI termina con código 2 sin token, así que las recetas desactivan el envío (PROBARA_ENABLED=false) donde la ejecutaría el build de un fork: entonces termina con código 0. Cada sección de abajo explica cómo mantener el secreto fuera de los builds de forks en ese CI.
  • Los pipelines repartidos crean una ejecución por máquina salvo que compartan una. En GitHub Actions los jobs de un mismo workflow comparten una ejecución automáticamente (jobs en paralelo). Fuera de GitHub Actions, créala primero, pasa su ULID a cada máquina, y ciérrala al final (sharding).

Salvo que una opción o una variable PROBARA_* los defina, la ejecución toma su nombre y su origen del CI:

CISe detecta porNombre de la ejecución
GitHub ActionsGITHUB_ACTIONS=trueGITHUB_WORKFLOW #GITHUB_RUN_NUMBER
GitLab CIGITLAB_CI=trueCI_PROJECT_NAME #CI_PIPELINE_IID
JenkinsJENKINS_URLJOB_NAME #BUILD_NUMBER
CircleCICIRCLECI=trueCIRCLE_PROJECT_REPONAME #CIRCLE_BUILD_NUM
Azure PipelinesTF_BUILD=TrueBUILD_DEFINITIONNAME #BUILD_BUILDNUMBER
Bitbucket PipelinesBITBUCKET_BUILD_NUMBERBITBUCKET_REPO_SLUG #BITBUCKET_BUILD_NUMBER
BuildkiteBUILDKITE=trueBUILDKITE_PIPELINE_SLUG #BUILDKITE_BUILD_NUMBER

La rama, el commit y la URL del build de cada uno figuran en su sección, y en la detección del CI de @probara/core. Sustitúyelos con PROBARA_BRANCH, PROBARA_COMMIT y PROBARA_BUILD_URL.

En el repositorio (o en la organización): Settings → Secrets and variables → Actions → New repository secret, con el nombre PROBARA_API_TOKEN y el token de aplicación como valor.

name: Cypress
on:
push:
branches: [main]
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
with:
node-version: 22
- run: npm ci
- name: Run Cypress tests
run: npx cypress run
env:
PROBARA_API_TOKEN: ${{ secrets.PROBARA_API_TOKEN }}
PROBARA_PROJECT: SHOP

Jobs en paralelo: una ejecución, cerrada por el job final

Sección titulada «Jobs en paralelo: una ejecución, cerrada por el job final»

En GitHub Actions los jobs de un mismo workflow envían a una misma ejecución: el origen de la ejecución identifica la ejecución del workflow por su repositorio, su id y su intento, y el primer job que envía crea la ejecución. Por defecto, cada job cierra su ejecución al terminar, así que los jobs en paralelo definen PROBARA_CLOSE_RUN: false. Un job final cierra la ejecución con probara run close, que no necesita aquí el ULID: needs hace que espere a todos los jobs de pruebas, y if: always() lo ejecuta aunque fallen. Cypress no tiene un flag --shard: cada job ejecuta sus propias specs, aquí con --spec.

jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
spec: ['cypress/e2e/cart/**', 'cypress/e2e/login/**']
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
with:
node-version: 22
- run: npm ci
- run: npx cypress run --spec '${{ matrix.spec }}'
env:
PROBARA_API_TOKEN: ${{ secrets.PROBARA_API_TOKEN }}
PROBARA_PROJECT: SHOP
# A job leaves the run open for the others.
PROBARA_CLOSE_RUN: false
probara:
needs: test
if: always()
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v5
with:
node-version: 22
- run: npx --yes @probara/cli@0.6 run close
env:
PROBARA_API_TOKEN: ${{ secrets.PROBARA_API_TOKEN }}
PROBARA_PROJECT: SHOP
  • Un job tras el cierre recibe 409 ci_run_closed: el reporter registra el motivo, no envía nada más, y las pruebas conservan su código de salida (solución de problemas). Mantén cada job que envía en needs.
  • Una nueva ejecución del workflow (re-run) es otro intento: envía a una ejecución propia.
  • Un solo job no necesita nada de esto: su ejecución se cierra al terminar, como en cualquier otro caso.
CampoDe dónde sale
NombreGITHUB_WORKFLOW #GITHUB_RUN_NUMBER, por ejemplo Cypress #42
RamaGITHUB_HEAD_REF (la rama de la pull request), si no GITHUB_REF_NAME; ninguna para un tag
CommitGITHUB_SHA
URL del buildGITHUB_SERVER_URL/GITHUB_REPOSITORY/actions/runs/GITHUB_RUN_ID
RepositorioGITHUB_REPOSITORY
Autor del commitGITHUB_ACTOR
Pull request<n> de GITHUB_REF refs/pull/<n>/merge
WorkflowGITHUB_WORKFLOW
Ejecución de CIGITHUB_RUN_ID, intento GITHUB_RUN_ATTEMPT
Job de CIGITHUB_JOB

En los eventos pull_request, GITHUB_SHA es el commit de merge que creó GitHub, no el último commit de la rama. Para registrar este último, añade PROBARA_COMMIT: ${{ github.event.pull_request.head.sha }}. En GitHub Actions el commit debe ser un SHA hexadecimal de 7 a 40 caracteres: otro valor se descarta con una advertencia.

Los workflows que lanza una pull request desde un fork reciben los secretos vacíos. Sin token, el reporter queda desactivado, así que los builds de forks ejecutan sus pruebas y no reportan nada, sin ningún ajuste adicional. No uses pull_request_target para llevar el secreto a un build de un fork: ejecuta el código del fork con tus secretos.

Settings → CI/CD → Variables → Add variable: clave PROBARA_API_TOKEN, el token como valor, con Mask variable activado. Protect variable la limita a ramas y tags protegidos: actívalo solo si reportas únicamente desde ellos.

stages:
- test
cypress:
stage: test
image: cypress/browsers:latest
variables:
PROBARA_PROJECT: SHOP
script:
- npm ci
- npx cypress run
  • cypress/browsers incluye Node.js, los navegadores y las bibliotecas del sistema que Cypress necesita; fija una etiqueta cuyo Node.js sea 22.12 o posterior.
  • Un job sin la variable (el pipeline de un fork, una rama no protegida con una variable protegida) ejecuta sus pruebas y no reporta nada.
  • Para conservar lo que no se pudo enviar, define PROBARA_RESULTS_FILE y guarda el archivo y su carpeta de adjuntos como artefactos (archivo de resultados).
  • Los jobs parallel: que comparten una ejecución, con un job .pre que la crea y un job .post que la cierra, están en sharding.
CampoDe dónde sale
NombreCI_PROJECT_NAME #CI_PIPELINE_IID, por ejemplo shop #42
RamaCI_MERGE_REQUEST_SOURCE_BRANCH_NAME en un pipeline de merge request, si no CI_COMMIT_REF_NAME; ninguna en un pipeline de tag
CommitCI_COMMIT_SHA
URL del buildCI_PIPELINE_URL

Una merge request desde un fork ejecuta su pipeline en el proyecto del fork, que no tiene tus variables de CI/CD: el reporter queda desactivado ahí. Si los maintainers ejecutan pipelines de forks en el proyecto principal, esos pipelines sí reciben la variable, así que revisa el cambio antes de ejecutarlo.

Manage Jenkins → Credentials → (un dominio) → Add Credentials: tipo Secret text, ID probara-api-token, el token como secreto.

Un Jenkinsfile declarativo, con Node.js 22 y las bibliotecas del sistema que Cypress necesita en el agente, enlaza el token en la etapa de pruebas con withCredentials:

pipeline {
agent any
environment {
PROBARA_PROJECT = 'SHOP'
}
stages {
stage('Test') {
steps {
sh 'npm ci'
withCredentials([string(credentialsId: 'probara-api-token', variable: 'PROBARA_API_TOKEN')]) {
sh 'npx cypress run'
}
}
}
}
}

Jenkins enmascara el secreto enlazado en el log del build.

Las etapas en paralelo que ejecutan cada una una parte de las specs crean una ejecución cada una salvo que compartan una: créala en una primera etapa, pásala a cada una y ciérrala en un bloque post { always { ... } }:

pipeline {
agent any
environment {
PROBARA_PROJECT = 'SHOP'
}
stages {
stage('Create the Probara run') {
steps {
sh 'npm ci'
withCredentials([string(credentialsId: 'probara-api-token', variable: 'PROBARA_API_TOKEN')]) {
sh 'npx --yes @probara/cli@0.3 run create > probara-run-ulid'
}
script {
env.PROBARA_RUN_ULID = readFile('probara-run-ulid').trim()
}
}
}
stage('Test') {
parallel {
stage('Cart') {
steps {
withCredentials([string(credentialsId: 'probara-api-token', variable: 'PROBARA_API_TOKEN')]) {
sh "npx cypress run --spec 'cypress/e2e/cart/**' --config screenshotsFolder=cypress/screenshots-cart"
}
}
}
stage('Login') {
steps {
withCredentials([string(credentialsId: 'probara-api-token', variable: 'PROBARA_API_TOKEN')]) {
sh "npx cypress run --spec 'cypress/e2e/login/**' --config screenshotsFolder=cypress/screenshots-login"
}
}
}
}
}
}
post {
always {
withCredentials([string(credentialsId: 'probara-api-token', variable: 'PROBARA_API_TOKEN')]) {
sh 'npx --yes @probara/cli@0.3 run close'
}
}
}
}

Aquí ambas etapas comparten un workspace, instalado una sola vez antes de que empiecen (dos npm ci a la vez en una misma carpeta se estorbarían). Cada cypress run vacía su carpeta de capturas al arrancar, así que en un mismo agente cada etapa tiene su propio screenshotsFolder. En agentes separados, cada una hace su propio checkout e instalación.

Jenkins no oculta por sí solo las credenciales a los builds de pull requests: un job multibranch que construye forks puede entregar el token a su código. Configura Discover pull requests from forks → Trust para que una pull request de cualquier otra persona se construya con el Jenkinsfile de su rama destino: en el branch source de GitHub, From users with Admin or Write permission (o Nobody); en el branch source de Bitbucket, Nobody, o Forks in the same account a partir de la versión 871 del plugin (la corrección de CVE-2024-28152). Everyone construye un fork con su propio Jenkinsfile, que puede enlazar la credencial por sí mismo, y deja inútil la protección con env.CHANGE_FORK de abajo.

En el Jenkinsfile de la rama destino, enlaza la credencial solo cuando env.CHANGE_FORK no está definida (Jenkins la define para una pull request desde un fork), y desactiva el envío en un build de un fork:

pipeline {
agent any
environment {
PROBARA_PROJECT = 'SHOP'
}
stages {
stage('Test') {
steps {
sh 'npm ci'
script {
if (env.CHANGE_FORK) {
withEnv(['PROBARA_ENABLED=false']) {
sh 'npx cypress run'
}
} else {
withCredentials([string(credentialsId: 'probara-api-token', variable: 'PROBARA_API_TOKEN')]) {
sh 'npx cypress run'
}
}
}
}
}
}
}

En el pipeline en paralelo, envuelve cada withCredentials de la misma forma: con el envío desactivado, run create no escribe ningún ULID y run close termina con 0 sin token.

Con JENKINS_URL definida, la ejecución se llama JOB_NAME #BUILD_NUMBER, y su rama, su commit y la URL del build salen de BRANCH_NAME (o GIT_BRANCH), GIT_COMMIT y BUILD_URL.

Organization Settings → Contexts → Create Context (por ejemplo probara-reporting), y después añade la variable de entorno PROBARA_API_TOKEN. Una variable de entorno de proyecto (Project Settings → Environment Variables) también sirve; en ese caso quita context: del ejemplo.

Un .circleci/config.yml cuyas specs reparte circleci tests split entre las máquinas de parallelism, en una ejecución creada al principio. Sin parallelism, deja solo el job test y ejecuta npx cypress run:

version: 2.1
jobs:
create-run:
docker:
- image: cimg/node:22.12
environment:
PROBARA_PROJECT: SHOP
steps:
- run: |
# Without the token (a fork's build), turn reporting off: run create prints nothing.
[ -n "$PROBARA_API_TOKEN" ] || export PROBARA_ENABLED=false
PROBARA_RUN_ULID=$(npx --yes @probara/cli@0.3 run create)
echo "PROBARA_RUN_ULID=$PROBARA_RUN_ULID" > probara.env
- persist_to_workspace:
root: .
paths: [probara.env]
test:
docker:
- image: cimg/node:22.12-browsers
parallelism: 4
environment:
PROBARA_PROJECT: SHOP
steps:
- checkout
- attach_workspace:
at: .
- run: npm ci
- run: |
export $(cat probara.env)
SPECS=$(circleci tests glob 'cypress/e2e/**/*.cy.js' | circleci tests split | paste -sd, -)
npx cypress run --spec "$SPECS"
close-run:
docker:
- image: cimg/node:22.12
environment:
PROBARA_PROJECT: SHOP
steps:
- attach_workspace:
at: .
- run:
when: always
command: |
export $(cat probara.env)
[ -n "$PROBARA_API_TOKEN" ] || export PROBARA_ENABLED=false
npx --yes @probara/cli@0.3 run close
workflows:
cypress:
jobs:
- create-run:
context: probara-reporting
- test:
context: probara-reporting
requires: [create-run]
- close-run:
context: probara-reporting
requires:
- test: [success, failed]

circleci tests split da a cada máquina su parte de los archivos de spec, y --spec los recibe como una lista separada por comas. La imagen -browsers incluye los navegadores y las bibliotecas del sistema que Cypress necesita.

CircleCI no pasa contextos ni variables de proyecto a los builds de pull requests desde forks, salvo que Pass secrets to builds from forked pull requests esté activado: déjalo desactivado. Los jobs de un fork que usan un contexto no llegan a ejecutarse (CircleCI muestra un error de autorización). Con variables del proyecto se ejecutan sin el token: el reporter no envía nada, y la línea PROBARA_ENABLED=false de create-run y close-run hace que run create no imprima nada y que ambos terminen con código 0.

Con CIRCLECI=true, la ejecución se llama CIRCLE_PROJECT_REPONAME #CIRCLE_BUILD_NUM, con la rama CIRCLE_BRANCH, el commit CIRCLE_SHA1 y la URL del build CIRCLE_BUILD_URL.

Pipelines → tu pipeline → Edit → Variables → New variable: nombre PROBARA_API_TOKEN, el token como valor, con Keep this value secret activado. Un grupo de variables de la biblioteca también sirve. Las variables secretas nunca llegan solas a los scripts: asigna la variable en el env del paso, como abajo.

variables:
# Off in a fork's build, which gets no secrets (see forks below).
PROBARA_ENABLED: $[ ne(variables['System.PullRequest.IsFork'], 'True') ]
pool:
vmImage: ubuntu-latest
steps:
- task: NodeTool@0
inputs:
versionSpec: '22.x'
- script: npm ci
- script: npx cypress run
env:
PROBARA_API_TOKEN: $(PROBARA_API_TOKEN)
PROBARA_PROJECT: SHOP

ubuntu-latest incluye los navegadores y las bibliotecas del sistema que Cypress necesita.

Una matrix de jobs que ejecutan cada uno una parte de las specs, en una ejecución que crea un primer job y cierra un último job que se ejecuta incluso después de pruebas fallidas:

variables:
PROBARA_ENABLED: $[ ne(variables['System.PullRequest.IsFork'], 'True') ]
jobs:
- job: create_run
pool:
vmImage: ubuntu-latest
steps:
- task: NodeTool@0
inputs:
versionSpec: '22.x'
- script: |
set -e
ulid=$(npx --yes @probara/cli@0.3 run create)
echo "##vso[task.setvariable variable=ulid;isOutput=true]$ulid"
name: probara
env:
PROBARA_API_TOKEN: $(PROBARA_API_TOKEN)
PROBARA_PROJECT: SHOP
- job: test
dependsOn: create_run
strategy:
matrix:
cart:
SPEC: 'cypress/e2e/cart/**'
login:
SPEC: 'cypress/e2e/login/**'
variables:
PROBARA_RUN_ULID: $[ dependencies.create_run.outputs['probara.ulid'] ]
pool:
vmImage: ubuntu-latest
steps:
- task: NodeTool@0
inputs:
versionSpec: '22.x'
- script: npm ci
- script: npx cypress run --spec '$(SPEC)'
env:
PROBARA_API_TOKEN: $(PROBARA_API_TOKEN)
PROBARA_PROJECT: SHOP
PROBARA_RUN_ULID: $(PROBARA_RUN_ULID)
- job: close_run
dependsOn: [create_run, test]
condition: always()
variables:
PROBARA_RUN_ULID: $[ dependencies.create_run.outputs['probara.ulid'] ]
pool:
vmImage: ubuntu-latest
steps:
- task: NodeTool@0
inputs:
versionSpec: '22.x'
- script: npx --yes @probara/cli@0.3 run close
env:
PROBARA_API_TOKEN: $(PROBARA_API_TOKEN)
PROBARA_PROJECT: SHOP
PROBARA_RUN_ULID: $(PROBARA_RUN_ULID)

Los builds de pull requests desde forks no reciben variables secretas salvo que Make secrets available to builds of forks esté activado: déjalo desactivado. Azure deja tal cual una macro que no puede resolver, así que en el build de un fork $(PROBARA_API_TOKEN) llega al paso como ese texto literal, un token que Probara rechaza con 401. La variable PROBARA_ENABLED del pipeline vale False cuando System.PullRequest.IsFork es True, así que el build de un fork ejecuta sus pruebas con el envío desactivado, y run create y run close terminan con código 0.

Con TF_BUILD=True, la ejecución se llama BUILD_DEFINITIONNAME #BUILD_BUILDNUMBER, y su rama, su commit y la URL del build salen de las variables del pipeline.

Repository settings → Pipelines → Repository variables: nombre PROBARA_API_TOKEN, el token como valor, con Secured activado. Bitbucket pasa las variables del repositorio a cada paso, así que el reporter la encuentra en npx cypress run.

image: cypress/browsers:latest
pipelines:
default:
- step:
name: Cypress
script:
- npm ci
- export PROBARA_PROJECT=SHOP
- npx cypress run

Los pasos en paralelo que ejecutan cada uno una parte de las specs reportan en una ejecución que crea un primer paso y cierra un último paso:

image: cypress/browsers:latest
pipelines:
default:
- step:
name: Create the Probara run
script:
- export PROBARA_PROJECT=SHOP
# Without the token (a fork's build), turn reporting off: run create prints nothing.
- test -n "$PROBARA_API_TOKEN" || export PROBARA_ENABLED=false
- PROBARA_RUN_ULID=$(npx --yes @probara/cli@0.3 run create)
- echo "PROBARA_RUN_ULID=$PROBARA_RUN_ULID" > probara.env
artifacts:
- probara.env
- parallel:
- step:
name: Cart
script:
- npm ci
- export PROBARA_PROJECT=SHOP $(cat probara.env)
- npx cypress run --spec 'cypress/e2e/cart/**' || touch cart.failed
artifacts:
- '*.failed'
- step:
name: Login
script:
- npm ci
- export PROBARA_PROJECT=SHOP $(cat probara.env)
- npx cypress run --spec 'cypress/e2e/login/**' || touch login.failed
artifacts:
- '*.failed'
- step:
name: Close the Probara run
script:
- export PROBARA_PROJECT=SHOP $(cat probara.env)
- test -n "$PROBARA_API_TOKEN" || export PROBARA_ENABLED=false
- npx --yes @probara/cli@0.3 run close
- if ls *.failed >/dev/null 2>&1; then echo "Tests failed in a parallel step" >&2; exit 1; fi

Bitbucket no ejecuta ningún paso después de uno fallido, así que un paso en paralelo que fallara dejaría la ejecución abierta. En su lugar, cada paso deja constancia de las pruebas fallidas en un artefacto <nombre>.failed, y el último paso cierra la ejecución y luego hace fallar el pipeline si algún paso dejó uno: los pasos en paralelo aparecen como correctos, y el fallo lo muestra el último paso. Si aun así el cierre nunca se ejecutó, cierra la ejecución en Probara, o a mano.

Las pull requests desde forks no reciben variables protegidas (Secured): el reporter no envía nada ahí. Con BITBUCKET_BUILD_NUMBER definida, la ejecución se llama BITBUCKET_REPO_SLUG #BITBUCKET_BUILD_NUMBER, con la rama BITBUCKET_BRANCH, el commit BITBUCKET_COMMIT y un enlace al pipeline.

Expón PROBARA_API_TOKEN a los pasos desde un almacén de secretos: un hook environment del agente que lo lea de tu gestor de secretos, o Buildkite secrets.

Un pipeline.yml cuyos jobs en paralelo reportan en una ejecución que crea un primer paso y que se cierra después de ellos, aunque hayan fallado. Sin parallelism, basta con un paso que ejecute npx cypress run:

env:
PROBARA_PROJECT: SHOP
steps:
- label: Create the Probara run
key: create-run
command: |
PROBARA_RUN_ULID="$(npx --yes @probara/cli@0.3 run create)"
if [ -n "$$PROBARA_RUN_ULID" ]; then buildkite-agent meta-data set probara-run "$$PROBARA_RUN_ULID"; fi
- label: Cypress
depends_on: create-run
parallelism: 4
command: |
npm ci
export PROBARA_RUN_ULID="$(buildkite-agent meta-data get probara-run --default '')"
SPECS=$(ls cypress/e2e/*.cy.js | awk -v i="$$BUILDKITE_PARALLEL_JOB" -v n="$$BUILDKITE_PARALLEL_JOB_COUNT" 'NR % n == i' | paste -sd, -)
npx cypress run --spec "$$SPECS"
- wait: ~
continue_on_failure: true
- label: Close the Probara run
command: PROBARA_RUN_ULID="$(buildkite-agent meta-data get probara-run --default '')" npx --yes @probara/cli@0.3 run close
  • buildkite-agent pipeline upload sustituye $NAME y ${NAME} al subir el pipeline, y una variable que en ese momento no conoce, como BUILDKITE_PARALLEL_JOB_COUNT, que solo reciben los jobs en paralelo, queda vacía; un $$ se deja como un $ para la shell del job, mientras que $(...) y $((...)) se dejan tal cual.
  • La ejecución se crea en una línea propia, así que un run create fallido hace fallar el primer paso en lugar de guardar un ULID vacío. Con el envío desactivado (un build de un fork en un agente que define PROBARA_ENABLED=false, como se explica abajo), run create no imprime ningún ULID y termina con 0: no se guarda nada, meta-data get --default '' da a los demás pasos un ULID vacío en lugar de un error, y también se ejecutan con el envío desactivado.
  • Cada job en paralelo toma uno de cada n archivos de spec (BUILDKITE_PARALLEL_JOB empieza en 0), y --spec los recibe como una lista separada por comas. Los agentes necesitan los navegadores y las bibliotecas del sistema que Cypress necesita.

Con BUILDKITE=true, la ejecución se llama BUILDKITE_PIPELINE_SLUG #BUILDKITE_BUILD_NUMBER, con la rama BUILDKITE_BRANCH, el commit BUILDKITE_COMMIT y la URL del build BUILDKITE_BUILD_URL.

Buildkite construye pull requests desde forks solo si el pipeline lo permite (desactivado por defecto). Esos builds se ejecutan en tus agentes, y pipeline upload lee el propio pipeline.yml del fork, que también elige la cola de los agentes. El código del fork se ejecuta en la shell del job como el usuario del agente, así que en un agente que puede leer el token de tu almacén de secretos, el código del fork también puede leerlo: ningún hook ni paso lo impide.

Mantén desactivados los builds de forks, o mantenlos lejos de esos agentes: su hook environment rechaza un build de un fork (BUILDKITE_PULL_REQUEST_REPO lo identifica), y los forks solo se construyen en una cola o un cluster aparte cuyos agentes no pueden leer el almacén de secretos:

Ventana de terminal
# The environment hook of the agents that can read the token: no build of a fork runs there.
if [ -n "$BUILDKITE_PULL_REQUEST_REPO" ]; then
case "${BUILDKITE_PULL_REQUEST_REPO#*://}" in
github.com/acme/shop.git) ;;
*)
echo "Refusing a build of a fork: $BUILDKITE_PULL_REQUEST_REPO" >&2
exit 1
;;
esac
fi
export PROBARA_API_TOKEN="$(your-secrets-manager get probara-api-token)"

BUILDKITE_PULL_REQUEST_REPO está vacía fuera de las pull requests, y es una URL https:// desde 2022 (antes, una git://), así que el hook la compara sin el esquema: pon tu repositorio en lugar de github.com/acme/shop.git. Si no coincide, tus propias pull requests también fallan en estos agentes, lo que la primera de ellas pondrá de manifiesto. En los agentes que construyen forks, define PROBARA_ENABLED=false en su hook environment: las pruebas del fork se ejecutan y npx cypress run no reporta nada, y run create y run close terminan con 0 sin token.

Relacionado: Sharding y proyectos · Archivo de resultados · Solución de problemas · Fuente: docs/ci