refactor(tools): cut GitHub fallback, Forgejo-first dispatch, fix 5 contradictions #5
Loading…
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?
Контекст
GitHub-аккаунт
slaid098удалён безвозвратно. Код opencode-config уже имеет Forgejo dispatch (_shared.ts:callForgejoGh,_forgejo_gh_dispatchв 3 oracle-скриптах), но GitHub-fallback ветки остаются как dead code в нашей среде. При этом 5 противоречий в поведении Forgejo vs GitHub приводят к некорректным результатам в Forgejo-режиме.Forgejo-инстанс
git.slaid098.devверсия 10.0.3. Actions API нестандартный:/actions/runsи/actions/runnersвозвращают 404. Workflow runs доступны только через/actions/tasks→{workflow_runs[], total_count}. Branch protection endpoint/branch_protections/{branch}поддерживается, но на main НЕ настроена (список пустой). README endpoint/readmeНЕ работает (404) — нужен/contents/README.md.Задача
Вырезать GitHub-fallback ветки (5 мест):
_shared.ts:95—spawnSync("gh", fullArgs)в fallbackrunGh()(срабатывает только еслиFORGEJO_URLне задан)create-readme.ts:339-371— GitHub API-ветка черезspawnSync("gh", "api", ...)для GET/PUT README.mdpipeline-status.py:213-218— fallbacksubprocess.run(args)дляghargvspec-status.py:158-159— fallbacksubprocess.run(args)дляgh issue viewproject-status.py:237-238— fallbacksubprocess.run(args)дляgh apiПочинить 5 критических противоречий:
pipeline-status.py:116-133,_forgejo_ci_rollup): использует commit status API/repos/{repo}/commits/{sha}/status— не видит Forgejo Actions runs. Заменить на/repos/{repo}/actions/tasksendpoint →{workflow_runs[], total_count}(поля:status,display_title,head_sha,created_at,url). Деталей jobs через API нет — это OK, возвращаем summary по runs.project-status.py:1335-1342,_check_branch_protection): строковый matchif "pull_request" in out and "required_status_checks" in out— этих полей НЕТ в Forgejobranch_protectionsresponse. Заменить на проверку Forgejo полей:enable_push(false = protected),enable_status_check,required_approvals. Возвращать OK еслиenable_push == falseилиrequired_approvals > 0илиenable_status_check == true.pipeline-status.py:193-194):check_gh_authв Forgejo mode возвращает формальный(0, "", "")без проверки токена. Добавить реальную проверку:GET /api/v1/userсFORGEJO_TOKEN→ если 200, auth OK; если 401/403, вернуть ошибку.gh pr list(pipeline-status.py:167-171):/repos/{repo}/pulls?state=openбез пагинации → >50 PR теряются. Добавить?page=N&limit=50цикл пока ответ не пустой. Forgejomax_response_items: 50.pipeline-status.py:469, 633):gh pr checksиgh run viewНЕ реализованы в Forgejo dispatch. Заменить hints на Forgejo-эквиваленты: ссылку наhttps://git.slaid098.dev/{repo}/actions(веб-UI), или удалить hints.Динамический clone URL (
create-readme.ts:63): hardcodedhttps://github.com/slaid098/${repo_name}.git. Заменить наprocess.env.FORGEJO_URL ?${process.env.FORGEJO_URL}/slaid098/${repo_name}.git: ...(fallback на GitHub-URL для обратной совместимости можно оставить в описании, но в коде — Forgejo-first).Расширить
pipeline-status.py:_forgejo_gh_dispatch— добавить:gh run list→GET /repos/{repo}/actions/tasks?limit=N→ форматировать какdatabaseId,conclusion(маппингid→ databaseId,status/conclusion→ conclusion)gh run view <id>→GET /repos/{repo}/actions/tasks+ фильтр по id → вернутьdisplay_title+ logs URL (деталей jobs нет, это OK)Descriptions в tools (11 файлов): "GitHub issue" → "issue", "gh CLI" → "git-host CLI", "Actions API" → "CI", "GitHub Release" → "release". Конкретные file:line в разделе Влияние.
Контракты
${FORGEJO_URL}/api/v1/..., auth черезAuthorization: token ${FORGEJO_TOKEN}/actions/tasksresponse:{workflow_runs: [{id, name, head_branch, head_sha, run_number, event, display_title, status, workflow_id, url, created_at, updated_at}], total_count}/branch_protections/{branch}response:{branch_name, enable_push, enable_push_whitelist, enable_push_whitelist_teams, enable_status_check, status_check_contexts, required_approvals, enable_merge_whitelist, ...}/userresponse:{id, login, is_admin, ...}— для auth check/repos/{repo}/pulls?page=N&limit=50— пагинация, 50 max per pagefetch()для HTTP (уже используется в_shared.ts:66)urllib.request.urlopen()для HTTP (уже используется вpipeline-status.py:104)process.env.FORGEJO_URLиprocess.env.FORGEJO_TOKEN— env vars (уже читаются)Инварианты
create-issue,create-pr,merge-pr,post-review,pipeline-status,project-status,spec-statusостаются с теми же параметрамиghCLI больше НЕ используется в коде (толькоfetch/urllib/curlк Forgejo API)FORGEJO_URLне задан — ошибка, не fallback наgh).github/workflows/НЕ трогаем (рабочий CI, Forgejo понимает оба расположения)Граничные случаи
FORGEJO_URLне задан → tool должен вернуть понятную ошибку "FORGEJO_URL env var required", НЕ fallback наgh/actions/tasksпустой ответ (нет runs) → CI check возвращает "нет CI runs" (не ошибка)/branch_protections/main404 → branch protection check возвращает WARN "не настроена" (реальное состояние, не баг)/user401/403 → auth check возвращает FAIL с сообщением "FORGEJO_TOKEN невалиден"/actions/taskstotal_count > 50 — пагинация НЕ поддерживается этим endpoint (по разведке), возвращаем первые 50 + hint "больше 50 runs, см. веб-UI"create-readme.ts:63— еслиFORGEJO_URLне задан (теоретический случай после вырезания fallback), вернуть ошибкуВлияние на связанные компоненты
_shared.ts— основной файл правки (вырезать L94-95 fallback, обновить комментарии L11/25/86/100/181 с "GitHub tools" → "git-host tools")create-readme.ts— вырезать L339-371 GitHub-ветку, оставить L300-338 Forgejo-ветку; L63 динамический clone URL; description L135/L218/L370 убрать "GitHub API"pipeline-status.py— починить L116-133 (CI rollup), L167-171 (pagination), L193-194 (auth), L213-218 (fallback), L469/L633 (hints); добавить_forgejo_gh_dispatchдляgh run list; docstrings L4/L14/L287/L294/L326/L476 убрать "GitHub"pipeline-status.ts:6-8— description "Actions API" → "CI"spec-status.py— вырезать L158-159 fallback; docstrings L9/L34/L166/L173 убрать "GitHub"; L435 NEXT_ACTION "GitHub issues" → "issues"project-status.py— починить L1335-1342 (branch protection); вырезать L237-238 fallback; docstrings L13/L218/L1241/L1286/L1334/L1338 убрать "GitHub"project-status.ts:7,10— description "dependabot"/"gh" → host-agnostic; аргумент "branch protection via gh" → "branch protection via API"create-issue.ts:20— description "GitHub issue" → "issue"create-pr.ts:19— description "GitHub PR" → "PR"merge-pr.ts:5,8— description "gh pr merge" → "merge PR"post-review.ts:8— description "gh pr comment" → "post review comment"spec-status.ts— обёртка, без изменений (dispatch в Python)Вне scope
.github/workflows/→.forgejo/workflows/— НЕ делаем (рабочий CI, Forgejo понимает оба)Критерии приемки
rg "spawnSync.*gh" .opencode/tools/→ 0 совпадений (всеghspawnSync вырезаны)rg "subprocess.run.*gh" .opencode/scripts/→ 0 совпадений (всеghsubprocess вырезаны, кроме dispatch который перехватывает)rg "github.com" .opencode/tools/ .opencode/scripts/→ 0 совпадений в активном коде (только в docstring-примерах можно оставить как generic URL)pipeline-status({pr_number: N})в Forgejo-режиме возвращает CI status из/actions/tasks, не из commit status APIproject-statusв Forgejo-режиме проверяет branch protection по Forgejo полям (enable_push,required_approvals), не по GitHub Rules API (pull_request,required_status_checks)pipeline-statusauth check в Forgejo-режиме делает реальныйGET /userзапрос, не формальный OKpipeline-statusв репо с >50 PR не теряет PR (пагинация работает)create-readme.tsclone URL в генерируемом README —${FORGEJO_URL}/slaid098/{repo}.git, неgithub.com/slaid098/{repo}.gitFORGEJO_URLне задан → tools возвращают понятную ошибку, НЕ fallback наghpipeline-status({pr_number: N})на реальном PR возвращает статус (DONE/NOT_DONE/AMBIGUOUS), не падает