fix(discovery): switch runtime from GitHub API to Forgejo API #2

Closed
opened 2026-08-07 12:59:38 +03:00 by slaid098 · 0 comments
Owner

Контекст

GitHub-аккаунт slaid098 забанен, api.github.com/raw.githubusercontent.com мертвы. Сайт-витрина собирает README и cover.png из git-репозиториев — сейчас все запросы идут в GitHub API, который больше не отвечает. Git remote уже переведён на Forgejo (git.slaid098.dev), но рантайм-код сайта по-прежнему хардкодит GitHub-эндпоинты. Сайт не показывает витрину и не рендерит обложки.

Архитектура discovery нейтральна к хосту: fetch list → detail → raw README + cover-meta → parse → render. Логику переписывать не нужно — только адаптировать URL-шаблоны, заголовки и webhook под Forgejo API.

Задача

  1. Вынести конфиг хоста в одно место: src/lib/git-host.ts (или env) — FORGEJO_URL, SHOWCASE_OWNER="slaid098", токен из FORGEJO_TOKEN. Заменить хардкод GITHUB_API/RAW_BASE в src/lib/readme-discovery.ts и src/app/apps/[slug]/cover/route.ts.
  2. Эндпоинты (Forgejo API, версия /api/v1):
    • список репо: /api/v1/users/{owner}/repos?limit=50 (параметр visibility у Forgejo может не работать — фильтр публичности на стороне клиента по полю private:false).
    • detail: /api/v1/repos/{owner}/{repo} (поле default_branch есть).
    • contents (cover SHA): /api/v1/repos/{owner}/{repo}/contents/{path}?ref={branch} (поле sha есть).
    • raw README/cover: /api/v1/repos/{owner}/{repo}/raw/{path}?ref={branch} (НЕ GitHub-формат /{owner}/{repo}/{branch}/path).
  3. Заголовки: Authorization: Bearer {token} (или token {token} — проверить формат Forgejo) оставить; убрать X-GitHub-Api-Version; Accept: application/json.
  4. Webhook src/app/api/webhook/route.ts: заголовки x-github-eventX-Gitea-Event, x-hub-signature-256 (с префиксом sha256=) → X-Gitea-Signature (hex без префикса). Логика HMAC + timingSafeEqual та же. Имя env секрета GITHUB_WEBHOOK_SECRETWEBHOOK_SECRET.
  5. UI-ссылки: src/components/site-footer.tsxgit.slaid098.dev/slaid098; src/components/qa-chat.tsx PROJECT_LINKS → Forgejo URL; src/lib/support.ts GITHUB_URL → Forgejo (или удалить, в UI не используется); лейблы i18n.ts «GitHub →» → «Репозиторий →»/«Repository →».
  6. Env: GITHUB_TOKENFORGEJO_TOKEN (или сохранить имя — нетвредно, но осмысленное лучше). Прописать на Vercel FORGEJO_URL, FORGEJO_TOKEN, WEBHOOK_SECRET.
  7. Тесты src/__tests__/: обновить hostname-матчеры (api.github.comgit.slaid098.dev/api/v1), имена webhook-заголовков, env-имена. ~6 тестовых файлов.

Контракты

  • Discovery запрашивает публичные репо slaid098 на git.slaid098.dev, парсит README (6 delimiter-секций) + assets/cover.png, рендерит карточки. Контракт с парсером и showcase-рендером не меняется.
  • Webhook от Forgejo на /api/webhook (секрет WEBHOOK_SECRET) → revalidateTag. Cron /api/cron-refresh не меняется.
  • SHOWCASE_OWNER = "slaid098" (владелец тот же на Forgejo).

Инварианты

  • ISR/статика не ломается: cache: "force-cache" + next:{revalidate:3600, tags:["showcase"]} на всех fetch'ах сохраняется. Теги showcase / repo:{name} не меняются.
  • generateStaticParams try/catch → [] (билд не падает без токена / при rate limit) сохранён.
  • Graceful degradation: fetch fail → ready:false, не выбрасывает.
  • noUncheckedIndexedAccess / exactOptionalPropertyTypes — для полей Forgejo API (private, default_branch) guard !== undefined.

Граничные случаи

  • Forgejo API: поле fork есть → фильтр !r.fork сохранён. Проверить, что html_url возвращает git.slaid098.dev/... (для кнопки detail + JSON-LD codeRepository).
  • Raw URL для приватных репо: discovery берёт только публичные — raw доступен анонимно.
  • Webhook: Forgejo не шлёт событие public — код уже skip'ает unknown events, не ломается.
  • GITHUB_TOKEN как рудимент в env — убрать или переименовать.

Влияние на связанные компоненты

  • src/lib/readme-discovery.ts — основная адаптация URL/заголовков.
  • src/app/apps/[slug]/cover/route.ts — raw-URL + detail.
  • src/app/api/webhook/route.ts — имена заголовков + env секрета.
  • src/components/{site-footer,qa-chat}.tsx, src/lib/support.ts, src/lib/i18n.ts — UI-ссылки и лейблы.
  • .env.example — переименование/добавление переменных.
  • scripts/spike-discovery.ts — использует readme-discovery, поменяется автоматически.
  • docs/project-map/, docs/decisions/ — новый ADR про Forgejo-миграцию (supersedes GitHub-discovery ADR-014).

Вне scope

  • Деплой и CI (отдельная задача).
  • Перенос issues с GitHub (отдельная задача).
  • Расширение showcase новыми публичными репо (отдельная задача — сейчас ~2-3 публичных с валидным README).

Критерии приемки

  • /ru/apps и /en/apps рендерят карточки из публичных репо Forgejo (с валидным README + cover).
  • Детальная страница [slug] показывает README + обложку из Forgejo.
  • Webhook от Forgejo инвалидирует ISR при пуше в репо с README/cover.png.
  • npm run build, lint, typecheck, тесты зелёные.
  • В коде не осталось ссылок на api.github.com / raw.githubusercontent.com / github.com/slaid098.
## Контекст GitHub-аккаунт `slaid098` забанен, `api.github.com`/`raw.githubusercontent.com` мертвы. Сайт-витрина собирает README и cover.png из git-репозиториев — сейчас все запросы идут в GitHub API, который больше не отвечает. Git remote уже переведён на Forgejo (`git.slaid098.dev`), но рантайм-код сайта по-прежнему хардкодит GitHub-эндпоинты. Сайт не показывает витрину и не рендерит обложки. Архитектура discovery нейтральна к хосту: fetch list → detail → raw README + cover-meta → parse → render. Логику переписывать не нужно — только адаптировать URL-шаблоны, заголовки и webhook под Forgejo API. ## Задача 1. **Вынести конфиг хоста в одно место**: `src/lib/git-host.ts` (или env) — `FORGEJO_URL`, `SHOWCASE_OWNER="slaid098"`, токен из `FORGEJO_TOKEN`. Заменить хардкод `GITHUB_API`/`RAW_BASE` в `src/lib/readme-discovery.ts` и `src/app/apps/[slug]/cover/route.ts`. 2. **Эндпоинты** (Forgejo API, версия `/api/v1`): - список репо: `/api/v1/users/{owner}/repos?limit=50` (параметр `visibility` у Forgejo может не работать — фильтр публичности на стороне клиента по полю `private:false`). - detail: `/api/v1/repos/{owner}/{repo}` (поле `default_branch` есть). - contents (cover SHA): `/api/v1/repos/{owner}/{repo}/contents/{path}?ref={branch}` (поле `sha` есть). - raw README/cover: `/api/v1/repos/{owner}/{repo}/raw/{path}?ref={branch}` (НЕ GitHub-формат `/{owner}/{repo}/{branch}/path`). 3. **Заголовки**: `Authorization: Bearer {token}` (или `token {token}` — проверить формат Forgejo) оставить; убрать `X-GitHub-Api-Version`; `Accept: application/json`. 4. **Webhook** `src/app/api/webhook/route.ts`: заголовки `x-github-event` → `X-Gitea-Event`, `x-hub-signature-256` (с префиксом `sha256=`) → `X-Gitea-Signature` (hex без префикса). Логика HMAC + `timingSafeEqual` та же. Имя env секрета `GITHUB_WEBHOOK_SECRET` → `WEBHOOK_SECRET`. 5. **UI-ссылки**: `src/components/site-footer.tsx` → `git.slaid098.dev/slaid098`; `src/components/qa-chat.tsx` `PROJECT_LINKS` → Forgejo URL; `src/lib/support.ts` `GITHUB_URL` → Forgejo (или удалить, в UI не используется); лейблы `i18n.ts` «GitHub →» → «Репозиторий →»/«Repository →». 6. **Env**: `GITHUB_TOKEN` → `FORGEJO_TOKEN` (или сохранить имя — нетвредно, но осмысленное лучше). Прописать на Vercel `FORGEJO_URL`, `FORGEJO_TOKEN`, `WEBHOOK_SECRET`. 7. **Тесты** `src/__tests__/`: обновить hostname-матчеры (`api.github.com`→`git.slaid098.dev`/`api/v1`), имена webhook-заголовков, env-имена. ~6 тестовых файлов. ## Контракты - Discovery запрашивает публичные репо `slaid098` на `git.slaid098.dev`, парсит README (6 delimiter-секций) + `assets/cover.png`, рендерит карточки. Контракт с парсером и showcase-рендером не меняется. - Webhook от Forgejo на `/api/webhook` (секрет `WEBHOOK_SECRET`) → `revalidateTag`. Cron `/api/cron-refresh` не меняется. - `SHOWCASE_OWNER = "slaid098"` (владелец тот же на Forgejo). ## Инварианты - ISR/статика не ломается: `cache: "force-cache"` + `next:{revalidate:3600, tags:["showcase"]}` на всех fetch'ах сохраняется. Теги `showcase` / `repo:{name}` не меняются. - `generateStaticParams` try/catch → `[]` (билд не падает без токена / при rate limit) сохранён. - Graceful degradation: fetch fail → `ready:false`, не выбрасывает. - `noUncheckedIndexedAccess` / `exactOptionalPropertyTypes` — для полей Forgejo API (`private`, `default_branch`) guard `!== undefined`. ## Граничные случаи - Forgejo API: поле `fork` есть → фильтр `!r.fork` сохранён. Проверить, что `html_url` возвращает `git.slaid098.dev/...` (для кнопки detail + JSON-LD `codeRepository`). - Raw URL для приватных репо: discovery берёт только публичные — raw доступен анонимно. - Webhook: Forgejo не шлёт событие `public` — код уже skip'ает unknown events, не ломается. - `GITHUB_TOKEN` как рудимент в env — убрать или переименовать. ## Влияние на связанные компоненты - `src/lib/readme-discovery.ts` — основная адаптация URL/заголовков. - `src/app/apps/[slug]/cover/route.ts` — raw-URL + detail. - `src/app/api/webhook/route.ts` — имена заголовков + env секрета. - `src/components/{site-footer,qa-chat}.tsx`, `src/lib/support.ts`, `src/lib/i18n.ts` — UI-ссылки и лейблы. - `.env.example` — переименование/добавление переменных. - `scripts/spike-discovery.ts` — использует `readme-discovery`, поменяется автоматически. - `docs/project-map/`, `docs/decisions/` — новый ADR про Forgejo-миграцию (supersedes GitHub-discovery ADR-014). ## Вне scope - Деплой и CI (отдельная задача). - Перенос issues с GitHub (отдельная задача). - Расширение showcase новыми публичными репо (отдельная задача — сейчас ~2-3 публичных с валидным README). ## Критерии приемки - `/ru/apps` и `/en/apps` рендерят карточки из публичных репо Forgejo (с валидным README + cover). - Детальная страница `[slug]` показывает README + обложку из Forgejo. - Webhook от Forgejo инвалидирует ISR при пуше в репо с README/cover.png. - `npm run build`, lint, typecheck, тесты зелёные. - В коде не осталось ссылок на `api.github.com` / `raw.githubusercontent.com` / `github.com/slaid098`.
Sign in to join this conversation.
No labels
bug
performance
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
slaid098/slaid098-dev#2
No description provided.