Агенты и runner-ы¶
Что такое агент¶
Агент в QA Hub — это identity runner-а:
- уникальный
id; - отображаемое имя;
- набор capabilities;
- список разрешенных окружений;
- отдельный Bearer token.
Runner — процесс, который использует этот token, забирает совместимый job и возвращает результат. Один агент может последовательно обработать много jobs.
Pull-модель подключения¶
Дополнительный входящий порт на agent host не нужен:
loop:
POST /agent/jobs/claim
if job is null:
sleep
continue
start heartbeat
execute known scenario
upload evidence
POST events
POST complete
Hub никогда не передает runner-у shell-команду. Поле agent_spec является
декларативным контрактом, который runner обязан валидировать.
1. Спроектируйте capabilities¶
Capability — точная строка, описывающая доверенную возможность runner-а:
http
playwright.chromium
conference.participant
media.diagnostics
android.device
ios.safari
Не используйте capability как название конкретного теста. Хорошая capability переиспользуется разными кейсами и однозначно говорит, что runner умеет делать.
Кейс может требовать несколько capabilities:
{
"required_capabilities": [
"conference.participant",
"media.diagnostics"
]
}
Job получит только агент, у которого есть все требуемые значения.
2. Зарегистрируйте агента¶
В UI откройте Управление → Агенты, укажите:
- ID:
http-stage1-01; - имя:
HTTP stage1 runner; - capabilities:
http; - environments:
stage1.
Token показывается один раз. Сразу сохраните его в secret manager. Hub хранит только SHA-256 и восстановить token позже не сможет.
То же через API:
QA_TOKEN="$(
curl -fsS https://qa.videograce.ru/api/v1/auth/token \
-H 'Content-Type: application/json' \
-d '{"username":"admin","password":"..."}' |
python3 -c 'import json,sys; print(json.load(sys.stdin)["token"])'
)"
curl -fsS https://qa.videograce.ru/api/v1/agents \
-H "Authorization: Bearer $QA_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"id": "http-stage1-01",
"name": "HTTP stage1 runner",
"capabilities": ["http"],
"environments": ["stage1"]
}'
Ответ содержит token вида qaa_....
3. Запустите готовый HTTP runner¶
В репозитории VideoGrace находится безопасный declarative runner:
Services/QaAgent.
Для первого production smoke:
- В разделе Наборы импортируйте
Services/QaHub/seed/examples/http-health-production.json. - В разделе Управление → Агенты зарегистрируйте агента:
ID
http-qa-prod-01, capabilityhttp, environmentqa-hub-production. - Сохраните показанный token.
- Создайте прогон
QA Hub production HTTP smokeв режиме Только агенты. - Запустите runner из корня репозитория:
VG_QA_HUB_URL=https://qa.videograce.ru \
VG_QA_AGENT_TOKEN='qaa_...' \
PYTHONPATH=Services/QaAgent \
python3 -m qaagent.runner
Runner последовательно заберет три jobs. В карточке прогона должны появиться
назначенный агент и результаты passed; после этого прогон можно завершить и
открыть итоговый отчет. Остановите runner через Ctrl+C.
Полезные параметры:
| Переменная | По умолчанию | Назначение |
|---|---|---|
VG_QA_POLL_SEC |
3 |
Интервал claim при пустой очереди |
VG_QA_HEARTBEAT_SEC |
20 |
Интервал heartbeat |
VG_QA_HUB_URL |
— | URL QA Hub |
VG_QA_AGENT_TOKEN |
— | Token зарегистрированного агента |
Флаг --once обрабатывает не более одного job и удобен для CI smoke.
Docker¶
cd Services/QaAgent
docker build -t videograce/qa-http-agent:0.1.0 .
docker run --rm \
--read-only \
--security-opt no-new-privileges \
-e VG_QA_HUB_URL=https://qa.videograce.ru \
-e VG_QA_AGENT_TOKEN='qaa_...' \
videograce/qa-http-agent:0.1.0
4. Создайте свой runner¶
Минимальный runner реализует пять операций.
Claim¶
POST /api/v1/agent/jobs/claim
Authorization: Bearer qaa_...
Content-Type: application/json
{}
Если подходящих jobs нет:
{"job": null}
Если job найден:
{
"job": {
"id": "3c14...",
"claimed_at": 1784790000,
"lease_expires_at": 1784790060,
"payload": {
"run_id": "d92f...",
"case_run_id": "2e8a...",
"environment": {
"name": "stage1",
"base_url": "https://stage1.videograce.ru",
"secret_ref": "env://VG_QA_STAGE1_SECRET"
},
"case": {
"external_id": "API-001",
"agent_spec": {}
}
}
}
}
Считайте payload недоверенным вводом. Проверяйте driver, actions, timeout, paths и assertions по allowlist.
Heartbeat¶
POST /api/v1/agent/jobs/<job_id>/heartbeat
Authorization: Bearer qaa_...
Content-Type: application/json
{}
Отправляйте heartbeat не реже трети lease. При lease 60 секунд практический интервал — 20 секунд.
События¶
POST /api/v1/agent/jobs/<job_id>/events
Authorization: Bearer qaa_...
Content-Type: application/json
{
"level": "info",
"event": "media_connected",
"data": {"elapsed_ms": 820}
}
Уровни: debug, info, warning, error. Не отправляйте heartbeat как
событие: для продления lease есть отдельный endpoint.
Артефакты¶
curl -fsS \
"https://qa.videograce.ru/api/v1/agent/runs/$RUN_ID/artifacts" \
-H "Authorization: Bearer $QA_AGENT_TOKEN" \
-H "X-QA-Job-Id: $JOB_ID" \
-H "X-QA-Case-Run: $CASE_RUN_ID" \
-H 'X-QA-Filename: diagnostics.json' \
-H 'Content-Type: application/json' \
--data-binary @diagnostics.json
Передается raw body, без base64. По умолчанию сервер принимает до 50 MiB.
Complete¶
POST /api/v1/agent/jobs/<job_id>/complete
Authorization: Bearer qaa_...
Content-Type: application/json
{
"status": "passed",
"result": {
"schema": "my.runner.result.v1",
"assertions": 12
}
}
Допустимые итоговые статусы агента: passed, failed.
Lease, restart и идемпотентность¶
Если heartbeat прекратился:
- Lease истекает.
- При следующем обращении Hub возвращает job в
queued. - Другой агент может получить тот же job.
- Старый агент больше не сможет отправить complete или artifact.
Поэтому сценарий runner-а должен быть безопасен при повторном запуске:
- создавать уникальные тестовые данные;
- удалять временных пользователей и комнаты;
- не считать наличие старого объекта успехом без проверки;
- использовать
run_idилиjob_idв external ID; - не выполнять необратимые production-действия.
Секреты окружения¶
Hub хранит только secret_ref. Готовый HTTP runner поддерживает ссылки
env://VARIABLE:
export VG_QA_STAGE1_SECRET='{
"headers": {
"Authorization": "Bearer replace-me"
}
}'
В production переменная должна приходить из Docker/Kubernetes secret или внешнего secret manager. Не записывайте секрет в suite JSON, agent result, event или artifact.
Отзыв агента¶
В UI нажмите Отозвать либо:
curl -fsS \
https://qa.videograce.ru/api/v1/agents/http-stage1-01/revoke \
-H "Authorization: Bearer $QA_TOKEN" \
-H 'Content-Type: application/json' \
-d '{}'
После отзыва token перестает проходить аутентификацию. Для замены token зарегистрируйте новый agent ID и затем отзовите старый.
Диагностика¶
| Симптом | Проверка |
|---|---|
claim всегда возвращает null |
Совпадают ли capabilities и environment |
| Job постоянно возвращается в очередь | Heartbeat реже lease или runner падает |
job_lease_expired |
Старый runner продолжил работу после потери lease |
job_not_found |
Job принадлежит другому агенту или уже перевыдан |
401 invalid_agent_token |
Token неверен или агент отозван |
| Agent job висит после ручного прогона | Запустить runner или завершить без агентов |