Files
tgit/docs/dev/SOURCECRAFT_API.md
ElebobaandClaude Opus 5.5 25735fee96 feat(bot): клиент SourceCraft API — прогоны, логи кубов, sha коммита, ретраи
- SourceCraftClient (httpx): list_runs, get_run, get_cube_logs (постранично), run_commit_sha;
  ретраи на сетевые ошибки и 5xx с экспоненциальной задержкой, 4xx — SourceCraftError без повторов
- модели: RunStatus/EventType из swagger, «1970-01-01» = не задано, failed_cubes без служебных #-кубов
- у прогона в API нет sha → куб check/meta в tgit-uploads печатает TGIT_COMMIT_SHA (ADR-014)
- CLI: python -m app.sourcecraft.cli runs
- тесты на реальных ответах API (фикстуры), порог покрытия 45 → 80

Refs #10

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 18:45:42 +03:00

7.1 KiB
Raw Permalink Blame History

SourceCraft API — шпаргалка

Issues и PR ведём в Gitea (GITEA_API.md, ADR-010). Здесь нужны в основном CI-прогоны, логи и секреты; разделы про issues/метки/PR — справочно (бот и скрипты могут работать с tgit-uploads).

Справочник: методы · интерактивный · swagger.json

set -a; . ./.env; set +a                     # SOURCECRAFT_TOKEN
R=https://api.sourcecraft.tech/repos/rogachevegorushka/tgit
H="Authorization: Bearer $SOURCECRAFT_TOKEN"
alias curl='curl --retry 4 --retry-all-errors --retry-delay 2'
J="Content-Type: application/json"

В CI вместо личного токена — предопределённая переменная SOURCECRAFT_TOKEN.

Подводные камни

  • Соединение с api.sourcecraft.tech иногда рвётся (curl: (35), пустой ответ) — отсюда --retry. Перед повторным POST проверить, не создалась ли сущность.
  • color у метки — hex без # ("ff7f0e"), иначе 400 ValidationError.
  • Ответы-списки кладут элементы в разные ключи: /issues → issues, /labels и /milestones → items, /pulls → pull_requests, метки issue → labels, связи → links.
  • Веха в issue задаётся milestone_id (UUID); milestone_slug отвергается с 400 must be a valid ID.
  • Issue адресуется номером (issues/1), метка — slug'ом (size/0.5 → size-0-5).
  • Тело issue — поле description (не body); тело комментария — body.
  • Длинный markdown удобнее собрать в JSON-файл и передать --data @file.json.

Issues

# список / одна
curl -s -H "$H" "$R/issues"
curl -s -H "$H" "$R/issues/1"

# создать (status_slug: open | inProgress | paused | closed | declined | duplicate)
curl -s -X POST -H "$H" -H "$J" "$R/issues" --data @issue.json
# issue.json: {"title": "...", "description": "...", "label_slugs": ["bot","feature","size-1"], "status_slug": "open"}

# обновить (описание, статус, исполнитель)
curl -s -X PATCH -H "$H" -H "$J" "$R/issues/1" -d '{"status_slug":"closed"}'

# комментарий
curl -s -X POST -H "$H" -H "$J" "$R/issues/1/comments" -d '{"body":"текст"}'

# метки issue: POST — добавить, PUT — заменить, DELETE — убрать
curl -s -X POST -H "$H" -H "$J" "$R/issues/1/labels" -d '{"slugs":["ci"]}'

# связь между issue (related_to | parent_of | subissue_of | blocks | blocked_by | duplicates | duplicated_by)
curl -s -X POST -H "$H" -H "$J" "$R/issues/9/issue_links" -d '{"target_issue_slug":"8","link_type":"blocked_by"}'

Вехи

curl -s -H "$H" "$R/milestones"
curl -s -X POST -H "$H" -H "$J" "$R/milestones" -d '{"name":"M5 · …","description":"…"}'   # → id для milestone_id

CI/CD

curl -s -H "$H" "$R/cicd/runs"                                   # прогоны: {"runs": [...], "next_page_token"}
curl -s -H "$H" "$R/cicd/runs/<run>"                             # прогон: status + workflows[].tasks[].cubes[]
curl -s -H "$H" "$R/cicd/logs/<run>/<workflow>/<task>/<cube>"    # лог куба: {"logs": "...", "page_complete", "done"}

# ручной запуск (head и config_revision — {"branch"|"tag"|"commit": ...}; по умолчанию — основная ветка)
curl -s -X POST -H "$H" -H "$J" "$R/cicd/runs" \
  -d '{"head":{"branch":"feat/x"},"config_revision":{"branch":"feat/x"},"workflows":[{"name":"check"}]}'

# секрет: value — base64 от значения
curl -s -X PUT -H "$H" -H "$J" "$R/secrets/DEPLOY_HOST" -d "{\"value\":\"$(printf %s 'user@host' | base64 -w0)\"}"
  • Триггеры on: читаются из .sourcecraft/ci.yaml основной ветки репозитория. Пока файла там нет — push ничего не запускает. Основная ветка tgit в SourceCraft — dev (PATCH $R -d '{"default_branch":"dev"}'), чтобы CI включался мержем в dev, а не продвижением в main.
  • Прогон: slug — числовой (1000000…), status: created → processing → success/failed; event_type: push/manual/…. У кубов служебные шаги со slug, начинающимся на # (#git-clone, #prepare-image-for-<cube>).
  • Если куб упал, остальные кубы задачи остаются в created и не запускаются.
  • В прогоне нет sha коммита (ни в списке, ни в деталях), фильтра по коммиту нет → в tgit-uploads куб check/meta печатает TGIT_COMMIT_SHA=…, бот читает его лог (ADR-014).
  • Логи служебных кубов (#git-clone и т.п.) API не отдаёт: 400 CITaskName.Pattern.
  • Логи постранично: ?page=N с 1; читать по порядку, пока page_complete: true; следующая страница незаконченной — 404.
  • Статусы прогона: created, prepared, processing, success, failed, canceled, timeout, skipped, awaiting_approval, rejected. Типы события: push, pr_update, manual, restart, schedule, repository_event.
  • Очередь бесплатных раннеров бывает минутами: прогон может стоять в prepared/created до ~6 мин до старта.
  • Веб-интерфейс — SPA, на любой путь отвечает 200: формат ссылки на прогон снаружи не проверить (SOURCECRAFT_RUN_URL_TEMPLATE).
  • Код в кубе склонирован в /sourcecraft/workspace ($SOURCECRAFT_WORKSPACE) — это рабочий каталог. Переменные: SOURCECRAFT_COMMIT_SHA, SOURCECRAFT_COMMIT_REF_NAME и др.
  • Исходящих webhooks нет — статус CI получаем опросом (ADR-003).

Метки репозитория

curl -s -H "$H" "$R/labels"
curl -s -X POST -H "$H" -H "$J" "$R/labels" -d '{"name":"size/1","slug":"size-1","color":"a0a0a0"}'

Заведены: зоны bot ci infra llm docs · типы feature fix refactor · размеры size/0.5 size/1 size/2.

Pull requests

# создать PR в dev
curl -s -X POST -H "$H" -H "$J" "$R/pulls" --data @pr.json
# pr.json: {"title": "...", "description": "...", "source_branch": "feat/2-x", "target_branch": "dev", "publish": true}

curl -s -H "$H" "$R/pulls/1"
curl -s -H "$H" "$R/pulls/1/merge-checks"

# мерж (rebase | squash, delete_branch)
curl -s -X POST -H "$H" -H "$J" "$R/pulls/1/merge" -d '{"delete_branch": true}'