HTTP API

Base URL:

https://qa.videograce.ru/api/v1

Все JSON mutation-запросы должны иметь Content-Type: application/json.

Аутентификация человека

Browser session

POST /api/v1/auth/login
Content-Type: application/json

{"username":"qa1","password":"..."}

Ответ устанавливает HttpOnly session cookie и возвращает csrf_token. Для POST и DELETE из browser session передавайте:

X-QA-CSRF: <csrf_token>

CLI session token

QA_TOKEN="$(
  curl -fsS https://qa.videograce.ru/api/v1/auth/token \
    -H 'Content-Type: application/json' \
    -d '{"username":"qa1","password":"..."}' |
  python3 -c 'import json,sys; print(json.load(sys.stdin)["token"])'
)"

Дальше:

Authorization: Bearer <QA_TOKEN>

Для Bearer session token CSRF header не требуется.

Аутентификация агента

Agent API принимает только token, выданный при регистрации:

Authorization: Bearer qaa_...

User token нельзя использовать вместо agent token и наоборот.

Пользователи

Метод Endpoint Назначение
GET /users Активные аккаунты
POST /users Создать аккаунт
POST /users/<id>/update Имя, роль, active или пароль
DELETE /users/<id> Обезличить и удалить доступ

Создание:

{
  "username": "qa1",
  "display_name": "QA Engineer",
  "password": "long-random-password",
  "role": "tester"
}

Увольнение без удаления истории:

{"active": false}

Окружения

Получить список

GET /environments

Создать

POST /environments
Content-Type: application/json

{
  "name": "stage1",
  "base_url": "https://stage1.videograce.ru",
  "secret_ref": "env://VG_QA_STAGE1_SECRET"
}

Каталог

Метод Endpoint Назначение
GET /suites Список suite
GET /suites/<id> Suite с кейсами
POST /catalog/import Идемпотентный импорт JSON

Прогоны

Создать

POST /runs
Content-Type: application/json

{
  "suite_id": 1,
  "environment_id": 2,
  "mode": "combined",
  "build_info": "3.0.260708 / web 609"
}

mode: manual, agent, combined.

Получить

GET /runs
GET /runs/<run_id>

Детальный ответ содержит cases, steps, jobs и artifacts.

Ручной результат

POST /case-runs/<case_run_id>/manual-result
Content-Type: application/json

{
  "status": "failed",
  "actual_result": "После повторного включения исходящий RTP отсутствует",
  "steps": [
    {"step_index": 0, "status": "passed", "comment": ""},
    {"step_index": 1, "status": "passed", "comment": ""},
    {"step_index": 2, "status": "failed", "comment": "trackMuted=true"}
  ]
}

Итог: passed, failed, skipped.

Отменить

POST /runs/<run_id>/cancel
Content-Type: application/json

{}

Финализировать

POST /runs/<run_id>/finalize
Content-Type: application/json

{"summary":"Release candidate rejected"}

Для combined-прогона с завершенной ручной частью:

{
  "summary": "Manual verification only",
  "skip_pending_agents": true
}

Ожидающие jobs отменяются, agent results становятся skipped.

Ручная загрузка артефакта

curl -fsS \
  "https://qa.videograce.ru/api/v1/runs/$RUN_ID/artifacts" \
  -H "Authorization: Bearer $QA_TOKEN" \
  -H "X-QA-Case-Run: $CASE_RUN_ID" \
  -H "X-QA-Filename-Encoded: $(python3 -c \
    'import urllib.parse; print(urllib.parse.quote("Снимок экрана.png"))')" \
  -H 'Content-Type: image/png' \
  --data-binary @screenshot.png

Скачать:

GET /artifacts/<artifact_id>/download

Отчеты

GET /runs/<run_id>/report?format=json
GET /runs/<run_id>/report?format=markdown
GET /runs/<run_id>/report?format=junit

Agent API

Метод Endpoint Ответственность
POST /agent/jobs/claim Получить совместимый job
POST /agent/jobs/<id>/heartbeat Продлить lease
POST /agent/jobs/<id>/events Записать событие
POST /agent/jobs/<id>/complete Передать итог
POST /agent/runs/<run_id>/artifacts Загрузить artifact

Подробный flow и примеры находятся в разделе Агенты и runner-ы.

Ошибки

Ошибка возвращается в едином формате:

{
  "error": {
    "code": "run_incomplete",
    "message": "complete all cases before finalizing (2 cases remaining)"
  }
}

Ориентируйтесь на error.code, а не на текст message.

HTTP Значение
400 Неверный payload
401 Нет или истекла аутентификация
403 Нет permission или CSRF
404 Объект не найден
409 Конфликт состояния
413 Artifact или JSON слишком большой
415 Неверный Content-Type