CI/CD에서 테스트 실행하기
Studio의 CI/CD 화면에서는 GitHub Actions 또는 GitLab CI용 파이프라인 파일을 작성할 수 있습니다. 이 가이드에서는 해당 파일이 실행하는 작업, 작업을 실행할 수 있는 세 가지 위치, 비밀 정보, 실행 후 남는 JUnit XML과 증거 자료, CI 컴퓨터에서 발생하는 오류를 다룹니다.
파이프라인 파일
CI/CD 화면에서 GitHub Actions 또는 GitLab CI, 브라우저, 검사 항목, 작업 실행 위치를 선택한 다음 파일을 생성하세요. Studio는 먼저 로컬에서 파일의 유효성을 검사하며, 같은 화면에서 커밋하고 푸시할 수도 있습니다. 터미널에서는 nexus init --ci github 또는 nexus init --ci gitlab으로 동일한 파일을 작성할 수 있습니다.
| 구성 요소 | GitHub Actions | GitLab CI |
|---|---|---|
| 파일 | .github/workflows/nexus-ci.yml | .gitlab-ci.yml |
| 실행 조건 | 풀 리퀘스트, main 또는 master로의 푸시, tc_ids 입력값을 사용하는 수동 실행(workflow_dispatch). 야간 회귀 테스트를 켜면 UTC 기준 schedule cron이 추가되며, 기본값은 0 6 * * *입니다. | 프로젝트의 파이프라인 규칙을 따릅니다. 파일에는 일정이 없습니다: 야간에 실행하려면 GitLab에서 파이프라인 일정을 추가하세요. |
| Runner | 클라우드 호스팅 실행기는 runs-on: ubuntu-latest, 자체 실행기는 runs-on: [self-hosted] | 이미지는 mcr.microsoft.com/playwright:v1.62.1-noble; 자체 실행기는 tags: [self-hosted] |
| 단계 | actions/checkout@v4; Docker 대상을 제외하고 Node.js 22를 사용하는 actions/setup-node@v4; npm ci; npx playwright install --with-deps; node bin/nexus.js ci --all 또는 선택한 테스트 ID | npm ci; TC_IDS 변수 또는 --all을 사용하는 node bin/nexus.js ci. 이미지에는 브라우저가 이미 포함되어 있습니다. |
| 결과물 | actions/upload-artifact@v4, if: always(), 이름 nexus-evidence, 경로 evidence/ | artifacts: when: always, reports: junit: evidence/ci/junit.xml, paths: evidence/ |
브라우저가 두 개 이상이면 GitHub는 fail-fast: false로 브라우저별 작업을 하나씩 실행하며, 각 작업에 --project=<browser>를 추가합니다. 선택한 검사 항목에 따라 --visual, --a11y, --chaos=, --loop= 또는 --no-retry가 추가됩니다.
종료 코드와 JUnit XML
nexus ci는 지정한 테스트(TC1,TC2) 또는 --all로 모든 테스트를 실행하고, 통과하면 0, 실패하면 1, 아무것도 실행되지 않았거나 명령이 잘못되었으면 2로 종료합니다. JUnit XML은 evidence/ci/junit.xml에 저장됩니다; --junit=<path>를 사용하면 다른 위치에 저장할 수 있습니다.
작업 실행 위치: 세 가지 옵션
모든 옵션에는 활성화된 컴퓨터가 필요합니다: 엔진은 활성화되지 않은 컴퓨터에서 테스트 모음을 실행하지 않으며, 활성화된 각 컴퓨터는 요금제의 컴퓨터 수에 포함됩니다(요금제와 컴퓨터). 클라우드 호스팅 실행기인 runs-on: ubuntu-latest는 작업마다 새 가상 머신을 시작하므로 활성화 상태를 유지하지 못합니다; 계속 유지되는 자체 실행기를 사용하세요.
옵션 A: Studio가 설치된 컴퓨터의 자체 호스팅 실행기
- Nexus Studio가 설치되고 활성화된 Windows 11 PC 또는 미니 PC에 실행기를 등록하세요: GitHub에서는 저장소의 설정, Actions, 실행기, 새 자체 호스팅 실행기에서; GitLab에서는 설정, CI/CD, 실행기에서 등록합니다.
- CI/CD 화면에서 내 컴퓨터를 선택하세요. 그러면 파일에 GitHub의 경우
runs-on: [self-hosted], GitLab의 경우tags: [self-hosted]가 지정됩니다. - Studio를 활성화한 Windows 사용자 계정으로 러너를 실행하세요. 엔진은 해당 사용자의 프로필에 있는
.sentinel-studio\license.json에서 활성화 정보를 읽으므로, 다른 계정으로 실행되는 러너 서비스는 활성화 정보를 찾지 못합니다.
작업은 이 기기의 활성화 정보를 사용합니다: 기기당 활성화 1개가 이미 요금제에 반영되어 있으며, 파이프라인에는 키를 넣지 않습니다. Studio의 경고대로, 자체 호스팅 러너는 비공개 저장소에서만 사용하세요: 공개 저장소에서는 누구든 풀 리퀘스트를 열어 사용자 기기에서 코드를 실행할 수 있습니다.
옵션 B: VPS의 컨테이너에서 실행되는 러너
Ubuntu 24.04 LTS x86_64, Docker Engine 및 Compose v2가 설치되어 있고 SSH 키 인증으로 접속하는 VPS입니다. 요금제의 기기 1대로 계산됩니다.
- CI/CD 화면에서 내 기기 + Docker를 선택하세요. Studio는 파이프라인 파일 외에도
docker-compose.sentinel-runner.yml,Dockerfile.runner및 러너의 진입점 스크립트 2개를 작업 공간에 작성합니다.Dockerfile.runner는mcr.microsoft.com/playwright:v1.62.1-noble을 기반으로 합니다. - 화면에는 Studio 자체 터미널이 아닌 VPS의 SSH 세션에 붙여 넣을 명령이 표시됩니다. GitHub의 경우 유효 시간이 1시간인 등록 토큰을 가져와
REPO_URL,RUNNER_TOKEN및RUNNER_NAME을 설정하고; GitLab의 경우GITLAB_URL및GITLAB_RUNNER_TOKEN을 설정합니다. 그런 다음:
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
첫 번째 줄은 GitHub용이고, 두 번째 줄은 GitLab용입니다. Linux 컨테이너 내부에서 라이선스는 /etc/machine-id로 기기를 식별합니다: 호스트의 파일을 /etc/machine-id:/etc/machine-id:ro와 같이 읽기 전용으로 마운트하고, 러너 홈의 .sentinel-studio 폴더를 볼륨에 보관하여 다시 빌드해도 활성화 정보가 유지되도록 하세요. nexus license activate와 키를 사용해 수동으로 한 번만 활성화하고, 파이프라인 파일에서는 절대 활성화하지 마세요.
현재 러너 이미지는 VPS에서 Dockerfile.runner로 빌드됩니다. 저장소에는 아직 컨테이너 레지스트리가 없습니다: Studio의 VPS 런타임에서 실행할 이미지는 다음 릴리스에서 GitHub Container Registry에 게시됩니다.
옵션 C: CI 작업이 SSH를 통해 호스트에서 실행을 시작
어떤 실행기를 사용하든 작업은 간소하게 유지되며, 테스트 모음은 소유한 호스트에서 실행됩니다. 해당 호스트의 경로에 작업 공간과 엔진을 두는 방식으로, Studio의 SSH 런타임이 요구하는 구성입니다. CI/CD 화면은 이 작업을 생성하지 않습니다; 다음은 Studio 자체 SSH 런타임이 사용하는 옵션입니다:
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
- 키 인증만 사용합니다.
BatchMode=yes는 비밀번호를 묻지 않습니다. CI 비밀 값에 저장된 개인 키를 작업에서만 읽을 수 있는 파일에 기록하고, 작업이 끝나면 삭제하세요. StrictHostKeyChecking=yes. 호스트 키는 실행기의known_hosts에 미리 등록되어 있어야 합니다: 호스트의 공개 키 행을 CI 변수에 저장하고 첫ssh실행 전에 해당 파일에 기록하세요. 절대no로 설정하지 마세요.- 종료 코드가 반환됩니다.
ssh는 원격 명령의 코드로 종료되므로 테스트 모음이 실패하면 해당 단계도 실패하며,scp는 JUnit XML을 포함한 증거 자료를 가져와 산출물 저장 단계에 전달합니다. - 호스트는 자체적으로 라이선스를 확인하며 요금제의 기기 한 대로 집계됩니다.
비밀 정보
- 토큰, 웹훅 URL, SSH 개인 키는 CI 비밀 값으로 저장하세요: GitHub에서는 설정, 비밀 값 및 변수, Actions에서 저장하거나
gh secret set <KEY>를 사용하세요; GitLab에서는 설정, CI/CD, 변수에서 마스킹된 변수로 저장하세요. 저장소, 파이프라인 파일 또는 로그에는 절대 남기지 마세요. - 생성된 GitHub 워크플로는 Nexus 단계에서만
secrets.<KEY>의 연동 키를 읽습니다:TELEGRAM_*,SLACK_ENABLED,SLACK_WEBHOOK_URL,JIRA_*및 알림 설정입니다. CI/CD 화면에는 각 키에 대한gh secret set명령이 표시됩니다;gh가 값 입력을 요청하며, 입력한 값은 출력되지 않습니다. - 라이선스 키는 CI에 저장하지 않아야 합니다. 영구 실행기는 한 번만 수동으로 활성화하세요: 키는 한 번 전송되며 보관되지 않습니다. 절차상 CI 시스템에 키를 저장해야 하는 경우에도 반드시 마스킹된 비밀 값으로만 저장하세요; 생성된 파이프라인은 이 키를 읽지 않습니다.
- 어떤 단계에서도 비밀 값을 출력하지 마세요. 엔진은 JUnit 실패 메시지나 로그처럼 증거 자료로 저장하는 텍스트에서 비밀 값을 제거합니다; 작업 자체의 콘솔 출력에서는 제거하지 않으며, CI 서비스는 비밀 값으로 저장된 값만 마스킹합니다.
JUnit XML 및 증거 자료를 산출물로 저장
- GitHub는 실행 성공 여부와 관계없이
evidence/를nexus-evidence로 업로드하며, 행렬을 사용하면 브라우저별로nexus-evidence-<browser>를 하나씩 업로드합니다. JUnit XML은 그 안의evidence/ci/junit.xml에 있습니다. - GitLab은
evidence/를 보관하고evidence/ci/junit.xml을 JUnit 보고서로 등록하므로, 병합 요청에 실패한 테스트가 표시됩니다. - Studio의 CI/CD 화면에서 GitHub 워크플로 실행을 시작하고 해당 증거 자료를 작업 공간의
evidence/ci-remote/run-<id>로 다운로드할 수 있습니다. - 사본이 저장되는 위치. 산출물은 스크린샷과 로그를 포함한 증거 자료의 사본으로, CI 서비스의 저장소에 보관됩니다; 호스팅 서비스라면 다른 주체의 하드웨어에 저장됩니다. 정책에서 허용하는 산출물 보관 기간을 설정하거나, 증거 자료를 실행기에 보관하고
evidence/ci/junit.xml만 업로드하세요.
문제 해결
클라우드 호스팅 또는 임시 실행기에서 발생하는 SEAT_LIMIT
라이선스는 새 가상 머신을 각각 새 기기로 인식하므로, 임시 실행기는 작업마다 활성화해야 합니다. 요금제에서 허용하는 모든 기기가 활성화되면 SEAT_LIMIT 오류와 함께 활성화가 거부됩니다: “요금제의 모든 기기가 사용 중입니다. 계정에서 한 대를 비활성화하세요.” 영구 자체 호스팅 실행기(옵션 A 또는 B)를 사용하고, 계정의 라이선스 & 기기에서 더 이상 사용하지 않는 기기를 비활성화하세요(SEAT_LIMIT 자세히 알아보기).
실행기가 며칠 동안 오프라인 상태였음
각 컴퓨터의 라이선스는 최소 7일마다 검증을 받아야 합니다. 이후 4일 동안 안내가 표시된 뒤 읽기 전용으로 전환됩니다: 검증에 성공할 때까지 테스트 모음은 실행되지 않으며, 증거 자료는 계속 열람할 수 있습니다. 실행기가 다시 온라인 상태가 되면 nexus license renew로 재검증할 수 있습니다 (오프라인 작업).
컨테이너에서 “no /etc/machine-id” 발생
컨테이너에 라이선스 검증 시 읽을 컴퓨터 ID가 없습니다. 호스트의 ID를 마운트하세요: -v /etc/machine-id:/etc/machine-id:ro, 또는 compose 파일의 volumes: 아래에 같은 줄을 추가하세요.
작업이 종료 코드 2로 종료됨
아무것도 실행되지 않았습니다: ID와 일치하는 테스트가 없거나 명령이 잘못되었습니다. nexus ci에 전달한 ID를 확인하세요. GitHub에서는 tc_ids, GitLab에서는 TC_IDS에 지정되어 있습니다.
호스트 키 검증 실패
StrictHostKeyChecking=yes가 known_hosts에 없거나 키가 변경된 호스트를 거부했습니다. 호스트 자체에서 키 지문을 확인한 다음, 신뢰할 수 있는 출처에서 얻은 호스트 키를 추가하세요. 검증을 끄지 마세요.