Ejecuta tus pruebas desde CI/CD
La pantalla CI/CD del Studio escribe el archivo del pipeline para GitHub Actions o GitLab CI. Esta guía cubre lo que ejecuta ese archivo, los tres lugares donde puede correr el job, los secretos, el JUnit XML y la evidencia que deja, y los errores que encuentra una máquina de CI.
El archivo del pipeline
En la pantalla CI/CD, elige GitHub Actions o GitLab CI, los navegadores, las comprobaciones y dónde corre el job, y luego genera. El Studio valida primero el archivo en local, y puede hacer commit y push desde la misma pantalla. Desde una terminal, nexus init --ci github o nexus init --ci gitlab escribe el mismo archivo.
| Parte | GitHub Actions | GitLab CI |
|---|---|---|
| Archivo | .github/workflows/nexus-ci.yml | .gitlab-ci.yml |
| Disparadores | Pull requests, pushes a main o master, y una ejecución manual (workflow_dispatch) con una entrada tc_ids. Con la regresión nocturna activada, un cron schedule en UTC, por defecto 0 6 * * *. | Las reglas de pipeline de tu proyecto. El archivo no tiene programación: para una ejecución nocturna, agrega un Pipeline Schedule en GitLab. |
| Runner | runs-on: ubuntu-latest para un runner alojado en la nube, runs-on: [self-hosted] para uno propio | La imagen mcr.microsoft.com/playwright:v1.62.1-noble; tags: [self-hosted] para tu propio runner |
| Pasos | actions/checkout@v4; actions/setup-node@v4 con Node.js 22, salvo en el destino Docker; npm ci; npx playwright install --with-deps; node bin/nexus.js ci --all, o los IDs de prueba que elegiste | npm ci; node bin/nexus.js ci con la variable TC_IDS, o --all. La imagen ya trae los navegadores. |
| Artefactos | actions/upload-artifact@v4, if: always(), nombre nexus-evidence, ruta evidence/ | artifacts: when: always, reports: junit: evidence/ci/junit.xml, paths: evidence/ |
Con más de un navegador, GitHub ejecuta un job por navegador, con fail-fast: false, y cada uno agrega --project=<browser>. Las comprobaciones que eliges agregan --visual, --a11y, --chaos=, --loop= o --no-retry.
Códigos de salida y JUnit XML
nexus ci ejecuta las pruebas que nombras (TC1,TC2) o --all, y sale con 0 cuando pasan, 1 si hay una falla y 2 cuando no se ejecutó nada o el comando era incorrecto. Escribe el JUnit XML en evidence/ci/junit.xml; --junit=<path> lo escribe en otro lugar.
Dónde corre el job: tres opciones
Cada opción necesita una máquina con una activación: el motor no ejecuta suites en una máquina que no tiene ninguna, y cada máquina activada cuenta para tu plan (planes y máquinas). Un runner alojado en la nube, runs-on: ubuntu-latest, inicia una máquina virtual nueva para cada job, así que nunca conserva una activación; usa un runner persistente propio.
Opción A: un runner autoalojado en la máquina del Studio
- En la PC o mini PC con Windows 11 donde Nexus Studio está instalado y activado, registra un runner: en GitHub, en el repositorio, en Settings, Actions, Runners, New self-hosted runner; en GitLab, en Settings, CI/CD, Runners.
- En la pantalla CI/CD, elige My machine. El archivo queda entonces con
runs-on: [self-hosted]en GitHub otags: [self-hosted]en GitLab. - Ejecuta el runner con el usuario de Windows que activó el Studio. El motor lee la activación del perfil de ese usuario, en
.sentinel-studio\license.json, así que un servicio de runner bajo otra cuenta no encuentra ninguna.
El job usa la activación de esta máquina: una activación por máquina, ya contada en tu plan, y sin clave en el pipeline. Usa un runner autoalojado solo con un repositorio privado, como advierte el Studio: en uno público, cualquiera que abra un pull request puede ejecutar código en tu máquina.
Opción B: un runner en un VPS, en un contenedor
Un VPS con Ubuntu 24.04 LTS x86_64, Docker Engine y Compose v2, al que se accede con autenticación por clave SSH. Cuenta como una máquina de tu plan.
- En la pantalla CI/CD, elige My machine + Docker. Además del archivo del pipeline, el Studio escribe en el espacio de trabajo
docker-compose.sentinel-runner.yml,Dockerfile.runnery los dos scripts de entrada (entrypoint) del runner.Dockerfile.runnerparte demcr.microsoft.com/playwright:v1.62.1-noble. - La pantalla muestra los comandos que debes pegar en una sesión SSH en el VPS, no en la terminal del propio Studio. Para GitHub obtiene un token de registro, válido por 1 hora, y define
REPO_URL,RUNNER_TOKENyRUNNER_NAME; para GitLab,GITLAB_URLyGITLAB_RUNNER_TOKEN. Luego:
docker compose -f docker-compose.sentinel-runner.yml up -d --build sentinel-runner
docker compose -f docker-compose.sentinel-runner.yml up -d sentinel-runner-gitlab
La primera línea es para GitHub, la segunda para GitLab. Dentro de un contenedor Linux, la licencia identifica la máquina por /etc/machine-id: monta el del host en solo lectura, /etc/machine-id:/etc/machine-id:ro, y mantén la carpeta .sentinel-studio del home del runner en un volumen, para que la activación sobreviva a una reconstrucción. Activa una sola vez, a mano, con nexus license activate y tu clave, nunca desde el archivo del pipeline.
Hoy la imagen del runner se construye en el VPS a partir de Dockerfile.runner. El repositorio todavía no tiene un registro de contenedores: una imagen publicada en GitHub Container Registry, la que ejecuta el runtime de VPS del Studio, llegará con la próxima versión.
Opción C: el job de CI inicia una ejecución en un host por SSH
El job se mantiene pequeño, en cualquier runner, y las suites corren en un host que es tuyo, con el espacio de trabajo y el motor en una ruta de ese host, como espera el runtime SSH del Studio. La pantalla CI/CD no genera este job; estas son las opciones que usa el propio runtime SSH del Studio:
ssh -o BatchMode=yes -o StrictHostKeyChecking=yes -o ConnectTimeout=8 <user>@<host> "cd <path> && node bin/nexus.js ci --all"
scp -r -o BatchMode=yes -o StrictHostKeyChecking=yes <user>@<host>:<path>/evidence ./evidence
- Solo autenticación por clave.
BatchMode=yesnunca pide una contraseña. Escribe la clave privada desde un secreto de CI en un archivo que solo pueda leer el job, y bórrala cuando el job termine. StrictHostKeyChecking=yes. La clave del host ya debe estar en elknown_hostsdel runner: guarda la línea de la clave pública del host en una variable de CI y escríbela ahí antes del primerssh. Nunca lo pongas enno.- El código de salida regresa.
sshsale con el código del comando remoto, así que el paso falla cuando la suite falla, yscptrae de vuelta la evidencia, JUnit XML incluido, para el paso de artefactos. - El host verifica su propia licencia y cuenta como una máquina de tu plan.
Secretos
- Guarda los tokens, las URL de webhook y las claves privadas SSH como secretos de CI: en GitHub, en Settings, Secrets and variables, Actions, o con
gh secret set <KEY>; en GitLab, como variables enmascaradas en Settings, CI/CD, Variables. Nunca en el repositorio, el archivo del pipeline ni un log. - El workflow de GitHub generado lee solo las claves de integración, desde
secrets.<KEY>, y solo en los pasos de Nexus:TELEGRAM_*,SLACK_ENABLED,SLACK_WEBHOOK_URL,JIRA_*y los interruptores de notificación. La pantalla CI/CD lista un comandogh secret setpara cada una;ghpide el valor, y no se imprime nada. - La clave de licencia no pertenece a CI. Activa un runner persistente una sola vez, a mano: la clave se envía una vez y no se guarda. Si tu proceso exige la clave en el sistema de CI de todos modos, guárdala solo como un secreto enmascarado; nada del pipeline generado la lee.
- Nunca muestres un secreto en un paso. El motor borra los secretos del texto que archiva como evidencia, como los mensajes de fallo de JUnit y los logs; no borra la salida de consola del propio job, y el servicio de CI solo enmascara los valores guardados como secretos.
XML JUnit y evidencia como artefactos
- GitHub sube
evidence/comonexus-evidence, y unnexus-evidence-<browser>por navegador cuando hay una matriz, sin importar si la ejecución pasó o falló. El XML JUnit está dentro, enevidence/ci/junit.xml. - GitLab conserva
evidence/y reportaevidence/ci/junit.xmlcomo un reporte JUnit, así que las pruebas fallidas aparecen en el merge request. - Desde el Studio, la pantalla CI/CD puede iniciar una ejecución de un workflow de GitHub y descargar su evidencia en
evidence/ci-remote/run-<id>dentro del espacio de trabajo. - Dónde vive la copia. Un artefacto es una copia de la evidencia, con capturas de pantalla y logs incluidos, en el almacenamiento de tu servicio de CI; en un servicio alojado, ese es el hardware de otra persona. Define la retención de artefactos que permita tu política, o conserva la evidencia en tu runner y sube solo
evidence/ci/junit.xml.
Solución de problemas
SEAT_LIMIT en un runner alojado en la nube o efímero
Cada máquina virtual nueva es una máquina nueva para la licencia, así que un runner efímero necesitaría una activación por cada job. Cuando todas las máquinas de tu plan están activas, la activación se rechaza con SEAT_LIMIT: “Todas las máquinas de tu plan están en uso. Desactiva una en tu cuenta.” Usa un runner autoalojado persistente (opción A o B) y desactiva las máquinas que ya no uses en License & machines en tu cuenta (más sobre SEAT_LIMIT).
El runner estuvo sin conexión durante días
La licencia de una máquina debe validarse al menos cada 7 días. Pasado ese plazo tiene 4 días más con un aviso, y luego pasa a solo lectura: las suites no se ejecutan hasta que una verificación tenga éxito, y la evidencia sigue siendo legible. En un runner que vuelve a tener conexión, nexus license renew verifica de nuevo (trabajar sin conexión).
“no /etc/machine-id” en un contenedor
El contenedor no tiene un identificador de máquina que la licencia pueda leer. Monta el del host: -v /etc/machine-id:/etc/machine-id:ro, o la misma línea bajo volumes: en el archivo de compose.
El job termina con el código 2
No se ejecutó nada: ninguna prueba coincidió con los IDs, o el comando era incorrecto. Revisa los IDs que le pasas a nexus ci, en tc_ids en GitHub o en TC_IDS en GitLab.
Falló la verificación de la clave del host (Host key verification failed)
StrictHostKeyChecking=yes rechazó un host que no está en known_hosts, o cuya clave cambió. Agrega la clave del host desde una fuente de confianza, después de comprobar su huella en el propio host. No desactives la verificación.