Files
tgit/docs/dev/SOURCECRAFT_API.md
T
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

114 lines
7.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SourceCraft API — шпаргалка
> Issues и PR ведём в Gitea ([`GITEA_API.md`](GITEA_API.md), ADR-010). Здесь нужны в основном CI-прогоны, логи и секреты;
> разделы про issues/метки/PR — справочно (бот и скрипты могут работать с `tgit-uploads`).
Справочник: [методы](https://sourcecraft.dev/portal/docs/en/api-ref/index.md) ·
[интерактивный](https://api.sourcecraft.tech/docs/index.html) ·
[swagger.json](https://api.sourcecraft.tech/sourcecraft.swagger.json)
```bash
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
```bash
# список / одна
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"}'
```
## Вехи
```bash
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
```bash
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).
## Метки репозитория
```bash
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
```bash
# создать 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}'
```