Перейти к содержимому

CI / GitHub Actions

CI-раннер не может открыть браузер для входа, поэтому входит по персональному токену. Создайте его на своей машине — браузер откроется один раз для SSO, а токен будет показан один раз и больше никогда:

Terminal window
tapstep token create --name github # печатает tapstep_pat_… в stdout
tapstep token create --name github | gh secret set TAPSTEP_TOKEN # сразу в секрет репозитория
tapstep token create --name nightly --expires-days 90

В stdout уходит только сам токен, поэтому его удобно передавать по пайпу; пояснение к нему уходит в stderr. Десктоп умеет то же в Settings → General → CI tokens: создать, один раз скопировать, отозвать.

Положите токен в GitHub → ваш репозиторий → Settings → Secrets and variables → Actions под именем TAPSTEP_TOKEN и передайте его джобу переменной окружения — TAPSTEP_TOKEN в окружении считается входом.

Terminal window
tapstep token list # id, имя, префикс, создан, последнее использование, срок — без самого токена
tapstep token revoke github # по id или по имени, если имя уникально

Как CLI его проверяет: токен tapstep_pat_… сверяется с api.tapstep.dev один раз, и ответ кэшируется в ~/.tapstep/token-check.json на 24 часа — на свежем раннере это один запрос на джоб. Отозванный, истёкший или неизвестный токен останавливает команду с ошибкой. Если API недоступен, прогон идёт дальше — со строкой warning: в stderr, если эта машина ещё ни разу не проверяла токен (свежий раннер), и молча, если проверяла. Наш простой никогда не красит ваш пайплайн.

TAPSTEP_TOKEN с любым другим значением — старые доки пропускали любую строку — работает с предупреждением в stderr до 0.15. До этого замените его токеном из tapstep token create.

.github/workflows/e2e.yml:

name: e2e
on: [push, pull_request]
jobs:
web:
runs-on: ubuntu-latest
env:
TAPSTEP_TOKEN: ${{ secrets.TAPSTEP_TOKEN }}
TAPSTEP_NO_SANDBOX: "1" # Ubuntu 24.04 не даёт песочнице Chromium стартовать, см. ниже
steps:
- uses: actions/checkout@v4
- name: Install tapstep
run: |
curl -fsSL https://s3.tapstep.dev/tapstep-cli/tapstep-latest-linux-x86_64.tar.gz | tar -xz
sudo mv tapstep /usr/local/bin/
- name: Validate flows
run: tapstep validate flows/
- name: Run flows
run: tapstep test flows/ --report junit --output results.xml
- name: Upload results
if: always()
uses: actions/upload-artifact@v4
with:
name: tapstep-results
path: |
results.xml
reports/
if-no-files-found: ignore

tapstep validate проверяет разбор каждого флоу и его include’ов без устройства, так что опечатка валит джоб за секунду, а не на середине прогона.

Код выхода отличает красный прогон от сломанного раннера: 1 — флоу выполнились, часть упала; 2 — tapstep не смог их запустить (плохой флаг, нет устройства, нечитаемый конфиг). Оба валят джоб; красный продукт означает только 1.

В образе GitHub Ubuntu уже есть Google Chrome, и tapstep его подхватит. --browser managed вместо этого скачивает прибитый Chromium в ~/.tapstep/browsers, чтобы CI и все ноутбуки гоняли одну версию браузера, — если пользуетесь им, кэшируйте эту папку между джобами.

TAPSTEP_NO_SANDBOX=1 нужен потому, что на ubuntu-latest (Ubuntu 24.04) песочница Chromium не запускается: AppArmor ограничивает непривилегированные user namespaces, и Chromium выходит с No usable sandbox. В container:-джобах и большинстве Docker-образов Chromium запущен от root и отказывается от песочницы сразу (Running as root without --no-sandbox is not supported). С 0.13.12 tapstep на Linux распознаёт оба отказа, печатает уведомление и один раз перезапускает Chromium с --no-sandbox, так что джоб без переменной тоже пройдёт — только заплатит за неудачный первый запуск. TAPSTEP_NO_SANDBOX=1 пропускает эту попытку и сразу стартует без песочницы.

Три способа — смотря где живёт тестируемое приложение.

URL стенда. Держите адрес вне флоу и выбирайте его по окружению в config.yaml:

config.yaml
environments:
local: { BASE_URL: http://localhost:3000 }
ci: { BASE_URL: https://staging.example.com }
flows/login.flow.yaml
appId: ${BASE_URL}/login
- name: Run flows
run: tapstep test flows/ --env-set ci --report junit --output results.xml
env:
APP_PASSWORD: ${{ secrets.APP_PASSWORD }}

--env-set ci подгружает environments.ci и локальный .env.ci, если он есть; внутри прогона ${TAPSTEP_ENV} равен ci. Секретам файл не нужен: любой ${NAME}, который не задал ни один слой, берётся из окружения процесса, так что секрет GitHub, выставленный в env:, доходит до ${APP_PASSWORD} как есть. См. config.yaml.

Приложение в том же джобе. Запустите его в фоне, дождитесь порта и гоняйте:

- run: npm ci && npm run build
- run: npm start &
- run: curl -fsS --retry 30 --retry-delay 2 --retry-connrefused http://localhost:3000 > /dev/null
- run: tapstep test flows/ -e BASE_URL=http://localhost:3000 --report junit --output results.xml

Или напишите во флоу прямо appId: http://localhost:3000.

Без UI вообще. Флоу device: none из шагов request: и sql: не нужны ни браузер, ни устройство — они идут на любом раннере, см. API-тестирование.

Поднимите эмулятор через reactivecircus/android-emulator-runner и запустите tapstep внутри него. Запущенный эмулятор tapstep сам находит через adb:

android:
runs-on: ubuntu-latest
env:
TAPSTEP_TOKEN: ${{ secrets.TAPSTEP_TOKEN }}
steps:
- uses: actions/checkout@v4
- name: Enable KVM
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- name: Install tapstep
run: |
curl -fsSL https://s3.tapstep.dev/tapstep-cli/tapstep-latest-linux-x86_64.tar.gz | tar -xz
sudo mv tapstep /usr/local/bin/
- uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 34
arch: x86_64
disable-animations: true
script: |
adb install -r app/build/outputs/apk/debug/app-debug.apk
tapstep test flows/android/ --report junit --output results.xml

Каждая строка script: выполняется отдельной командой. Если подключено несколько устройств, --device <serial> выбирает одно.

Флоу iOS в CI пока не запускаются: в релизный бинарь не входит XCUITest-раннер, без которого не работает iOS-драйвер. Гоняйте их на Mac, где раннер установлен; поддержка CI появится в релизе, который его поставляет.

Флоу с vscode: запускает установленный десктопный VS Code, поэтому джоб его ставит и даёт ему виртуальный дисплей:

vscode:
runs-on: ubuntu-latest
env:
TAPSTEP_TOKEN: ${{ secrets.TAPSTEP_TOKEN }}
steps:
- uses: actions/checkout@v4
- name: Install VS Code and Xvfb
run: |
curl -fsSL -o code.deb "https://update.code.visualstudio.com/latest/linux-deb-x64/stable"
sudo apt-get update && sudo apt-get install -y ./code.deb xvfb
- name: Install tapstep
run: |
curl -fsSL https://s3.tapstep.dev/tapstep-cli/tapstep-latest-linux-x86_64.tar.gz | tar -xz
sudo mv tapstep /usr/local/bin/
- run: npm ci && npx @vscode/vsce package -o dist/my-ext.vsix
- run: xvfb-run -a tapstep test flows/vscode/ -e VSIX=${{ github.workspace }}/dist/my-ext.vsix --report junit --output results.xml

.vsix берётся из предыдущего шага сборки; флоу читает его в заголовке vscode: как vscode: { vsix: ${VSIX} } или называет testspace: из config.yaml. Относительный vsix: считается от папки самого флоу (у testspace — от корня проекта), поэтому передавайте абсолютный путь, как выше, — см. config.yaml. VS Code tapstep находит через CLI code в PATH или через TAPSTEP_VSCODE=/path/to/code.

На runs-on: windows-latest ставьте из zip в PowerShell:

- name: Install tapstep
shell: pwsh
run: |
Invoke-WebRequest https://s3.tapstep.dev/tapstep-cli/tapstep-latest-windows-x86_64.zip -OutFile tapstep.zip
Expand-Archive tapstep.zip -DestinationPath "$env:LOCALAPPDATA\tapstep\bin"
"$env:LOCALAPPDATA\tapstep\bin" | Out-File -Append -Encoding utf8 $env:GITHUB_PATH

--report junit|allure|html|json с --output <file> пишет один общий отчёт для прогона директории; allure пишет папку allure-results/ (в текущей папке или в --output <dir>). Блок report: в config.yaml пишет отчёт на каждом прогоне без флагов. Скриншоты и сетевые логи падений ложатся в reports/ — выгружайте эту папку с if: always(), как в workflow выше. См. Отчёты.

Флоу с AI-шагами и в CI нужен провайдер (TAPSTEP_AI_MODEL, TAPSTEP_AI_KEY и TAPSTEP_AI_ENDPOINT из секретов или блок ai: в config.yaml). С включённым режимом приватности запускайте tapstep privacy install при сборке образа раннера — модель маскировки весит ~945 МБ, качать её в каждом джобе не стоит.