Execute seus testes a partir do CI/CD
A tela CI/CD do Studio escreve o arquivo de pipeline para GitHub Actions ou GitLab CI. Este guia cobre o que esse arquivo executa, os três lugares onde o job pode rodar, os segredos, o JUnit XML e as evidências que ele deixa, e os erros que uma máquina de CI encontra.
O arquivo do pipeline
Na tela CI/CD, escolha GitHub Actions ou GitLab CI, os navegadores, as verificações e onde o job é executado; depois, gere. O Studio valida o arquivo localmente primeiro e pode fazer commit e push dele a partir da mesma tela. Em um terminal, nexus init --ci github ou nexus init --ci gitlab escreve o mesmo arquivo.
| Parte | GitHub Actions | GitLab CI |
|---|---|---|
| Arquivo | .github/workflows/nexus-ci.yml | .gitlab-ci.yml |
| Gatilhos | Pull requests, pushes para main ou master e uma execução manual (workflow_dispatch) com uma entrada tc_ids. Com a regressão noturna ativada, um cron schedule em UTC, por padrão 0 6 * * *. | As regras de pipeline do seu projeto. O arquivo não tem agendamento: para uma execução noturna, adicione um Pipeline Schedule no GitLab. |
| Runner | runs-on: ubuntu-latest para um runner hospedado na nuvem, runs-on: [self-hosted] para o seu próprio | A imagem mcr.microsoft.com/playwright:v1.62.1-noble; tags: [self-hosted] para o seu próprio runner |
| Etapas | actions/checkout@v4; actions/setup-node@v4 com Node.js 22, exceto no alvo Docker; npm ci; npx playwright install --with-deps; node bin/nexus.js ci --all, ou os IDs de teste que você escolheu | npm ci; node bin/nexus.js ci com a variável TC_IDS, ou --all. A imagem já tem os navegadores. |
| Artefatos | actions/upload-artifact@v4, if: always(), nome nexus-evidence, caminho evidence/ | artifacts: when: always, reports: junit: evidence/ci/junit.xml, paths: evidence/ |
Com mais de um navegador, o GitHub executa um job por navegador, com fail-fast: false, e cada um adiciona --project=<browser>. As verificações que você escolhe adicionam --visual, --a11y, --chaos=, --loop= ou --no-retry.
Códigos de saída e JUnit XML
nexus ci executa os testes que você nomeia (TC1,TC2) ou --all, e termina com 0 quando eles passam, 1 em caso de falha e 2 quando nada foi executado ou o comando estava errado. Ele grava o JUnit XML em evidence/ci/junit.xml; --junit=<path> o grava em outro lugar.
Onde o job é executado: três opções
Toda opção precisa de uma máquina com ativação: o mecanismo não executa suítes em uma máquina que não tenha uma, e cada máquina ativada conta para o seu plano (plans and machines). Um runner hospedado na nuvem, runs-on: ubuntu-latest, inicia uma nova máquina virtual a cada job, então nunca mantém uma; use um runner persistente seu.
Opção A: um runner self-hosted na máquina do Studio
- No PC com Windows 11 ou mini PC em que o Nexus Studio está instalado e ativado, registre um runner: no GitHub, em Settings, Actions, Runners, New self-hosted runner do repositório; no GitLab, em Settings, CI/CD, Runners.
- Na tela CI/CD, escolha My machine. O arquivo passa a conter
runs-on: [self-hosted]no GitHub outags: [self-hosted]no GitLab. - Execute o runner como o usuário do Windows que ativou o Studio. O mecanismo lê a ativação do perfil desse usuário, em
.sentinel-studio\license.json, portanto um serviço de runner em outra conta não encontra nenhuma.
O job usa a ativação desta máquina: uma ativação por máquina, já contada no seu plano, e nenhuma chave no pipeline. Use um runner self-hosted apenas com um repositório privado, como o Studio avisa: em um repositório público, qualquer pessoa que abra um pull request pode executar código na sua máquina.
Opção B: um runner em uma VPS, em um contêiner
Uma VPS com Ubuntu 24.04 LTS x86_64, Docker Engine e Compose v2, acessada com autenticação por chave SSH. Ela conta como uma máquina do seu plano.
- Na tela CI/CD, escolha My machine + Docker. Além do arquivo de pipeline, o Studio grava
docker-compose.sentinel-runner.yml,Dockerfile.runnere os dois scripts de entrypoint do runner no workspace. ODockerfile.runnerparte demcr.microsoft.com/playwright:v1.62.1-noble. - A tela mostra os comandos para colar em uma sessão SSH na VPS, não no terminal do próprio Studio. Para o GitHub, ela busca um token de registro, válido por 1 hora, e define
REPO_URL,RUNNER_TOKENeRUNNER_NAME; para o GitLab,GITLAB_URLeGITLAB_RUNNER_TOKEN. Em seguida:
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
A primeira linha é para o GitHub, a segunda para o GitLab. Dentro de um contêiner Linux, a licença identifica a máquina por /etc/machine-id: monte o do host somente leitura, /etc/machine-id:/etc/machine-id:ro, e mantenha a pasta .sentinel-studio do diretório pessoal do runner em um volume, para que a ativação sobreviva a uma reconstrução. Ative uma vez, manualmente, com nexus license activate e a sua chave, nunca a partir do arquivo de pipeline.
Hoje a imagem do runner é construída na VPS a partir do Dockerfile.runner. O repositório ainda não tem um registro de contêineres: uma imagem publicada no GitHub Container Registry, a que o runtime de VPS do Studio executa, chegará com a próxima versão.
Opção C: o job de CI inicia uma execução em um host via SSH
O job continua pequeno, em qualquer runner, e as suítes rodam em um host seu, com o workspace e o engine em um caminho nele, como o runtime SSH do Studio espera. A tela CI/CD não gera este job; estas são as opções que o próprio runtime SSH do Studio usa:
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
- Somente autenticação por chave.
BatchMode=yesnunca pede senha. Grave a chave privada de um secret do CI em um arquivo legível apenas pelo job e apague-a quando o job terminar. StrictHostKeyChecking=yes. A chave do host já deve estar noknown_hostsdo runner: mantenha a linha da chave pública do host em uma variável do CI e grave-a lá antes do primeirossh. Nunca defina comono.- O código de saída volta. O
sshsai com o código do comando remoto, então a etapa falha quando a suíte falha, e oscptraz a evidência, incluindo o JUnit XML, de volta para a etapa de artefato. - O host verifica a própria licença e conta como uma máquina do seu plano.
Segredos
- Armazene tokens, URLs de webhook e chaves privadas SSH como secrets do CI: no GitHub em Settings, Secrets and variables, Actions, ou com
gh secret set <KEY>; no GitLab como variáveis mascaradas em Settings, CI/CD, Variables. Nunca no repositório, no arquivo de pipeline ou em um log. - O workflow gerado do GitHub lê apenas as chaves de integração, de
secrets.<KEY>, e somente nas etapas do Nexus:TELEGRAM_*,SLACK_ENABLED,SLACK_WEBHOOK_URL,JIRA_*e as chaves de notificação. A tela CI/CD lista um comandogh secret setpara cada uma; oghpede o valor, e nada é exibido. - A chave de licença não pertence ao CI. Ative um runner persistente uma única vez, manualmente: a chave é enviada uma vez e não é mantida. Se o seu processo exigir a chave no sistema de CI mesmo assim, armazene-a apenas como um secret mascarado; nada no pipeline gerado a lê.
- Nunca exiba um secret com echo em uma etapa. O engine remove os secrets do texto que registra como evidência, como mensagens de falha do JUnit e logs; ele não limpa a saída do console do próprio job, e o serviço de CI mascara apenas os valores armazenados como secrets.
JUnit XML e evidências como artefatos
- O GitHub envia
evidence/comonexus-evidence, umnexus-evidence-<browser>por navegador com matrix, quer a execução tenha passado ou falhado. O JUnit XML está dentro, emevidence/ci/junit.xml. - O GitLab mantém
evidence/e informaevidence/ci/junit.xmlcomo relatório JUnit, de modo que os testes com falha aparecem no merge request. - A partir do Studio, a tela CI/CD pode iniciar uma execução de workflow do GitHub e baixar a evidência para
evidence/ci-remote/run-<id>no workspace. - Onde fica a cópia. Um artefato é uma cópia da evidência, incluindo capturas de tela e logs, no armazenamento do seu serviço de CI; em um serviço hospedado, isso é o hardware de outra pessoa. Defina a retenção de artefatos que a sua política permite, ou mantenha a evidência no seu runner e envie apenas
evidence/ci/junit.xml.
Solução de problemas
SEAT_LIMIT em um runner na nuvem ou efêmero
Cada nova máquina virtual é uma nova máquina para a licença, então um runner efêmero precisaria de uma ativação a cada job. Quando todas as máquinas do seu plano estiverem ativas, a ativação é recusada com SEAT_LIMIT: “Todas as máquinas do seu plano estão em uso. Desative uma em sua conta.” Use um runner self-hosted persistente (opção A ou B) e desative as máquinas que você não usa mais em License & machines na sua conta (saiba mais sobre SEAT_LIMIT).
O runner ficou offline por dias
A licença de uma máquina precisa ser validada pelo menos a cada 7 dias. Depois disso, ela recebe mais 4 dias com um aviso e então passa para somente leitura: as suítes não rodam até que uma verificação seja bem-sucedida, e a evidência continua legível. Em um runner que voltou a ficar online, nexus license renew verifica novamente (trabalhando offline).
“no /etc/machine-id” em um container
O container não tem um ID de máquina para a licença ler. Monte o do host: -v /etc/machine-id:/etc/machine-id:ro, ou a mesma linha em volumes: no arquivo compose.
O job sai com o código 2
Nada foi executado: nenhum teste correspondeu aos IDs, ou o comando estava errado. Verifique os IDs passados para nexus ci, em tc_ids no GitHub ou TC_IDS no GitLab.
Falha na verificação da chave do host
O StrictHostKeyChecking=yes recusou um host que não está no known_hosts, ou cuja chave mudou. Adicione a chave do host a partir de uma fonte confiável, depois de conferir a impressão digital no próprio host. Não desative a verificação.