Docs-pipeline

Docs Pipeline

stack-docs/.github/workflows/docs.yml · scripts/inject-doc-meta.mjs · scripts/build-changelog.mjs · quartz-overrides/

Як stack-docs рендериться у єдиний сайт docs.besocial.tech. ~2-3 хв на тригер.

Як це працює

  1. Тригер — один з трьох:

    • push у master stack-docs зі змінами в **/*.md, scripts/, quartz-overrides/, workflow
    • repository_dispatch з типом service-docs-updated (його шлють сервісні репо коли в них змінюється docs/)
    • cron щодоби о 04:00 UTC — запасний механізм
    • workflow_dispatch (ручний запуск з UI Actions)
  2. Checkout stack-docs з повною git-історією (fetch-depth: 0).

  3. Setup Quartz — клонується Quartz у _quartz/, запінений на тег v4.5.2 (--branch v4.5.2). Без піна clone тягнув HEAD і breaking v5.0.0 ламав білд — деталі і план переходу у Quartz v5 Migration.

  4. Apply overrides — rsync stack-docs/quartz-overrides/ _quartz/.

  5. Copy root content — все з кореня stack-docs (окрім services/, scripts/, .github/, quartz-overrides/, тощо) у _quartz/content/.

  6. Inject metadata for root — inject-doc-meta.mjs --repo stack-docs --src . додає у frontmatter modified і author з git log stack-docs.

  7. Aggregate services — для кожного сервісу з реєстру scripts/services.mjs (workflow отримує рядки vault:repo:branch від node scripts/services.mjs):

    • клонується сервісне репо з PAT (depth=200, потрібна свіжа гілка з docs/)
    • rsync <repo>/docs/ _quartz/content/services/<vault>/
    • rewrite-service-wikilinks.mjs — переписує relative wikilinks ([[ui/Chat]] → [[services/<vault>/ui/Chat]]) і basename-лінки які мають локальний match, повним шляхом з підпапкою ([[01-project-admins]] → [[services/<vault>/entities/01-project-admins]]). Лінки на інший сервіс ([[services/client/...]]) і на root-папки (architecture/, examples/) лишає як є. Без цього кроку сервісні wikilinks ламаються в спільному vault — Quartz shortest mode не вміє резолвити slash-форми.
    • inject-doc-meta.mjs --repo <repo> --src docs --target ... --prefix services/<vault>/
    • тимчасова папка чиститься

    .canvas файли копіюються в build, але Quartz їх нативно не рендерить — це обмеження. Для візуальних мап на сайті використовуємо mermaid у тілі md-сторінок (зокрема index.md сервісу). canvas-to-mermaid.mjs залишився в scripts/ як реалізована опція автоконвертації, зараз не використовується через слабкий auto-layout для великих канв.

  8. Build changelog — build-changelog.mjs збирає _changelog-partial.json з усіх піддиректорій у єдиний changelog.md.

  9. Build Quartz — npx quartz build → _quartz/public/.

  10. Deploy — wrangler pages deploy на Cloudflare Pages projект stack-docs.

Список сервісів

Єдине місце — scripts/services.mjs: з нього читають workflow, sync.mjs, dev-preview.mjs, inject-doc-meta.mjs і build-changelog.mjs. Для CI реєстр друкує рядки формату:

<vault_name>:<repo_name>:<branch>
  • vault_name — як називається папка у vault (напр. electron, golden)
  • repo_name — назва репо в GitHub-org, не локальна папка. Зараз єдине розходження — локальна папка stack-electron, а на GitHub репо називається electron (історично). Тому в реєстрі repo: 'electron', dir: 'stack-electron'; поле dir — локальна папка, якщо вона не збігається з назвою репо (репозиторії Project Platform лежать у workspace project-platform). Коли клонуєш сервіси для перевірки — git ls-remote https://github.com/it-monkeys/<repo_name> дасть точно.
  • branch — конвенція: завжди docs. Кожне сервісне репо тримає окрему довгу гілку docs, з неї стак-докс агрегує. У цю гілку пишемо док-перш (часто випереджає код); чорнові сторінки маркуються #draft. Коли відповідний код мерджиться в master, доки з гілки docs поступово мерджаться у master сервісу, #draft → #reviewed. Поле branch у реєстрі задавати — тільки тимчасово (наприклад поки docs гілка ще не створена в репо).

Якщо в репо ще нема гілки docs або в ній нема docs/ — пайплайн пропускає сервіс з warning’ом, не падає.

Як тригернути ручно

Поки webhook’и з сервісів не налаштовані, оновлення сайту після зміни доки в сервісі робиться одним з трьох способів:

1. GitHub UI (найшвидше).

  • github.com/it-monkeys/stack-docs/actions
  • Зліва обрати workflow Build & Deploy Docs
  • Над списком ранів буде блакитна смуга з текстом «This workflow has a workflow_dispatch event trigger.» — у її правій частині кнопка Run workflow ▼.
  • Клік → dropdown Use workflow from: Branch master → кнопка Run workflow.
  • Через ~1.5 хв білд завершиться, сайт оновиться.

2. gh CLI (якщо встановлено gh):

gh workflow run docs.yml --repo it-monkeys/stack-docs

3. Порожній коміт у stack-docs (без UI):

cd stack-docs
git commit --allow-empty -m "trigger rebuild" && git push

Тригерить workflow по push фільтру.

4. Cron щодоби о 04:00 UTC — нічого не робиш, ранкова зміна сама опиниться на сайті за добу.

Опційно: webhook з сервісного репо

Якщо хочеться щоб push у <service>/docs/ одразу тригерив білд stack-docs — кладемо .github/workflows/notify-stack-docs.yml у сервісне репо за шаблоном stack-docs/scripts/service-trigger-template.yml.

Передумови у сервісному репо:

  • secret STACK_DOCS_DISPATCH_TOKEN — fine-grained PAT з permission Actions: Read and write на it-monkeys/stack-docs (один токен на всі сервіси)
  • branch у paths workflow має збігатись з branch сервісу в scripts/services.mjs (за замовчуванням docs)

Має сенс налаштовувати коли 2+ людей паралельно редагують доки і набридло натискати Run workflow вручну.

Секрети у stack-docs

SecretПризначенняТермін дії
SERVICES_READ_TOKENFine-grained PAT з Contents: read на всі сервісні реподо 1 року (GitHub обмеження для PAT до org-репо)
CLOUDFLARE_API_TOKENAPI токен Cloudflare з permission на Pagesза вибором при створенні (типово без expiration)
CLOUDFLARE_ACCOUNT_IDID акаунту Cloudflareне протухає

Ротація SERVICES_READ_TOKEN

Токен живе максимум 1 рік (GitHub-обмеження для fine-grained PAT що дають доступ до org-репо). Поточний stack-docs-services-read діє до 02.05.2027.

Коли токен протух, ще не погоджений org (статус Pending) або не має доступу до репо — workflow не падає: крок Clone services and aggregate docs пише warning «Не вдалось клонити <repo>@docs — пропускаю», лишається зеленим, а сервіс зникає з сайту.

GitHub за ~7 днів до експірації шле email-нагадування власнику токена. Краще перестворити заздалегідь.

Як перестворити

  1. GitHub → профіль → Settings → Developer settings → Personal access tokens → Fine-grained tokens
  2. Generate new token зі старими параметрами:
    • Token name: stack-docs-services-read
    • Resource owner: it-monkeys
    • Expiration: 1 year (максимум)
    • Repository access: Only select repositories — обрати всі сервісні репо з scripts/services.mjs (electron, stack-golden, stack-client, stack, stack-prime, stack-udate, stack-chathouse, stack-academy, stack-ai, project-application-api)
    • Repository permissions → Contents: Read-only (Metadata: Read-only додасться автоматично як Required)
  3. Якщо org має policy на approval — попроси org-owner схвалити у it-monkeys → Settings → Personal access tokens → Pending requests.
  4. У it-monkeys/stack-docs → Settings → Secrets and variables → Actions → SERVICES_READ_TOKEN → Update value (вставити новий токен).
  5. Старий токен можна revoke у Fine-grained tokens після того як перевірив що новий працює.
  6. Перевірка: Actions → Build & Deploy Docs → Run workflow. Якщо крок Clone services and aggregate docs проходить без warning’ів «Не вдалось клонити» — все ок.

Важливо: не забувай оновлювати список репо у пункті 2 коли в проєкт додається новий сервіс — інакше workflow тихо буде skip’ати його з варнінгом «не вдалось клонити».

Метадані файлів

Інжектиться у frontmatter:

  • modified — ISO 8601 дата останнього коміту що торкався файла (з відповідного репо!)
  • author — %an останнього коміту
  • tags — JSON-array з першого рядка body (Obsidian inline-теги #x #y)

Файли в репо НЕ модифікуються — інжект на копії у _quartz/content/. Локально в Obsidian усе як було.

Нюанси

  • fetch-depth: 0 обов’язковий — без нього git log поверне 1 коміт і дати/changelog зламаються.
  • Сервісні репо клонуються --depth=200 — компроміс між швидкістю і точністю історії. Якщо потрібна повна історія — підвищити або прибрати.
  • concurrency: docs-build — два пайплайни одночасно не біжать. Запит що прийшов поки інший виконується — стає у чергу (cancel-in-progress: false).
  • Cron 04:00 UTC — підстраховка на випадок якщо webhook з сервісу загубився. Не критичний — головний канал це repository_dispatch.
  • _changelog-partial.json — тимчасові артефакти що залишають inject-doc-meta після кожного репо. build-changelog.mjs їх збирає і видаляє. На сайт не попадають.
  • Файли крос-сервісних wikilinks з префіксом services/<vault>/ — тому коли стійкий лінк ставиш на чужий сервіс у root-доці, пиши [[services/golden/api/index]].

Чек-ліст коли ламається пайплайн

  • Дата на сторінці = unix epoch (1970) → fetch-depth не 0 або сервіс склонувався без історії (підвищити depth)
  • Сервіс не з’явився на сайті (у лозі «Не вдалось клонити») → перевір що додано в scripts/services.mjs з назвою репо як на GitHub, що гілка docs існує, що репо є в Repository access токена stack-docs-services-read, що токен погоджений org і не протух
  • Webhook з сервісу не тригерить білд → перевір STACK_DOCS_DISPATCH_TOKEN в сервісному репо, дивись Actions runs у stack-docs
  • Cloudflare deploy впав → перевір CLOUDFLARE_API_TOKEN і CLOUDFLARE_ACCOUNT_ID
  • Quartz побудувався з помилкою про брокен лінк → лінк на файл який не існує у vault. Якщо це крос-сервіс — перевір що цільовий сервіс має docs/ і присутній у scripts/services.mjs.

Як змінити пайплайн

  • Додати сервіс — запис у scripts/services.mjs (vault, repo, за потреби dir, title) і репо в Repository access токена stack-docs-services-read (GitHub → Settings → Developer settings → Fine-grained tokens; після зміни доступу org може знову попросити погодження). Якщо репо вже має гілку docs з docs/ — підхопиться при наступному запуску.
  • Перейменувати репо сервісу — оновити repo у scripts/services.mjs і запушити stack-docs: CI читає реєстр з master на GitHub, а не локальний.
  • Прибрати сервіс — видалити рядок. Старий контент зникне з сайту після наступного білду.
  • Змінити вигляд автора/дати — quartz-overrides/quartz/components/ContentMeta.tsx.
  • Додати ще overrides Quartz-компонента — кладемо у quartz-overrides/quartz/components/<Name>.tsx. Rsync скопіює автоматично.
  • Розширити changelog — функції в build-changelog.mjs.

Зв’язки

  • Тригериться: пуш у stack-docs master, repository_dispatch з сервісів, cron, ручний dispatch
  • Читає: git log усіх сервісних репо
  • Пише: _quartz/content/** (тимчасово, у CI)
  • Деплоїть: docs.besocial.tech (Cloudflare Pages)