fix(tools): create-issue sends labels as strings, Forgejo API expects int64 IDs (HTTP 422) #4
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Контекст
При создании issue через
create-issuetool в Forgejo-режиме (FORGEJO_URLзадан в окружении) tool падает с HTTP 422 Unprocessable Entity, если передан параметрlabels.Воспроизведение: вызов
create-issueсlabels: ["enhancement"]→ Forgejo API возвращает 422. Повторный вызов безlabels— успешен (issue создается без меток).Причина: tool отправляет массив labels как массив строк (
["enhancement"]), но Forgejo API endpointPOST /api/v1/repos/{owner}/{repo}/issuesожидает вCreateIssueOption.labelsмассив int64 ID лейблов (не имён). См. https://codeberg.org/forgejo/forgejo/src/branch/forgejo/modules/structs/issue.go —Labels []int64.GitHub API (
POST /repos/{owner}/{repo}/issues) принимает строки — поэтому в GitHub-режиме tool работает корректно. Расхождение контрактов GitHub vs Forgejo.Обход, который использовал subagent: повторный вызов без labels, затем прикрепление label через отдельный вызов API
POST /api/v1/repos/{repo}/issues/{number}/labelsс правильным форматом. Но это ручной workaround, не решение.Задача
Починить
create-issuetool для корректной работы с labels в Forgejo-режиме: принимать имена labels как строки (текущий контракт tool'а), внутри конвертировать в int64 ID через lookupGET /api/v1/repos/{repo}/labelsперед отправкойPOST .../issues. Если label не найден — либо создать его (POST .../labels), либо вернуть понятную ошибку (решить при имплементации).Контракты
create-issue(title, body, labels: string[], repo?)— labels как массив строк имён, не ID. Этот контракт НЕ меняем (обратная совместимость с GitHub-режимом и существующими вызовами).POST /api/v1/repos/{owner}/{repo}/issues: тело{"title": "...", "body": "...", "labels": [int64, ...]}. Документация: https://forgejo.org/docs/api/ (swagger /api/v1).GET /api/v1/repos/{owner}/{repo}/labels: список лейблов с id/name.POST /api/v1/repos/{owner}/{repo}/labels: создание лейбла (если решено автосоздавать).POST /api/v1/repos/{owner}/{repo}/issues/{number}/labels: альтернативный путь — создать issue без labels, потом прикрепить через этот endpoint (принимает{"labels": ["name1", "name2"]}— строки, не ID!). См. https://forgejo.org/docs/api/ —IssueLabelsOption.labelsэто[]string.Инварианты
string[]имёнghCLI) не должен сломаться —gh issue create --label "enhancement"принимает строкиГраничные случаи
labelsв теле)Влияние на связанные компоненты
create-issue.ts— основной файл правки,Forgejo-ветка (через_shared.ts:callForgejoGhили inline). GitHub-ветка (runGh) не трогаем_shared.ts— если lookup/conversion вынесен в shared helper, может потребоваться расширениеcreate-pr.ts— потенциально тот же баг с labels (PR тоже принимают labels). Проверить и при необходимости починить одновременноpost-review.ts— не использует labelsmerge-pr.ts— не использует labelsrunGh— проверить кто еще передаёт labels в API-вызовыopencode.jsondescription — если упоминается labels format, обновитьВне scope
ghCLI)create-prесли он есть — сделать отдельной задачей или включить в эту на усмотрение имплементатора, но не блокировать_shared.tsКритерии приемки
create-issueсlabels: ["enhancement"]на Forgejo-репо — до фикса возвращает 422, после фикса успешно создаёт issue с labelGET /api/v1/repos/{repo}/labels— реализован и используетсяFORGEJO_URL): не сломан,gh issue create --label ...отрабатывает как раньшеcreate-pr.tsс labels в Forgejo-режиме — либо починен в этом PR, либо заведён отдельный issue если баг есть/issues/{n}вернётlabelsмассив не пустой)