Files
de-roadmap/project/ADR.md
T
ddadmin 8584fc225b docs(project): добавлена спецификация публикации сайта
- Зачем:
  - нужен согласованный вариант публикации сайта без зависимости от GitHub Pages.
- Что:
  - описан контур Gitea Actions, host runner, nginx и резерв на GitHub Pages.
  - в архитектурный документ добавлена ссылка на новую спецификацию.
- Проверка:
  - git diff --cached --check.
2026-08-04 10:01:58 -04:00

16 KiB
Raw Blame History

ADR: Архитектура сайта de-roadmap

Архитектурный документ. Проектные цели и требования — в PRD. Решения о публикации и custom domain заменены спецификацией «Публикация сайта через Gitea Actions и VPS». Решения о MkDocs, структуре файлов и ссылках остаются актуальными.


1. Ключевые архитектурные требования

Из PRD вытекают четыре жёстких ограничения, определяющих выбор инструментов:

  1. Сайт опционален. Репозиторий должен полноценно работать без сайта. Удалили конфиг — всё как было.
  2. Dual-compatible links. Внутренние ссылки между .md файлами должны работать и на GitHub, и на сайте.
  3. Один файл = один источник правды. Не должно быть копий или генерируемых .md. Редактируем один раз — рендерится везде.
  4. Zero-effort deploy. Push в main → сайт обновился. Без ручных шагов, без локальной сборки.

2. Выбор генератора статического сайта

Рассмотренные варианты

Критерий MkDocs Material Docusaurus Hugo Astro
Язык/экосистема Python Node.js (React) Go Node.js
Порог входа Минимальный — pip install, один YAML Средний — npm, React-компоненты Средний — Go templates Высокий — фреймворк
Поддержка Markdown «как есть» Отличная, расширения через плагины Хорошая, но MDX-ориентирован Хорошая, но shortcodes вместо стандартного MD Хорошая
Навигация по длинной странице TOC sidebar из коробки Есть, но заточен под многостраничность Зависит от темы Зависит от темы
Поиск Встроенный (lunr.js), работает offline Algolia (внешний сервис) или плагин Нет из коробки Нет из коробки
Тёмная тема Из коробки, переключатель Из коробки Зависит от темы Зависит от темы
GitHub Pages деплой Одна команда / готовый Action Готовый Action Готовый Action Готовый Action
Dual-compatible links Поддерживает с настройкой use_directory_urls Преобразует ссылки, может ломать GitHub Преобразует ссылки Преобразует ссылки
Один мейнтейнер, Python-стек Идеально Node.js ⚠️ Go, но бинарник Node.js

Решение: MkDocs Material

Почему:

  • Python-based — совпадает со стеком автора, pip install и готово.
  • Лучшая из коробки поддержка длинных страниц с TOC — именно наш сценарий.
  • Встроенный поиск без внешних сервисов.
  • Самый простой конфиг — один mkdocs.yml.
  • Крупнейшее комьюнити среди генераторов документации, активно развивается.
  • Dual-compatible links решаемы (см. раздел 4).

Почему не Docusaurus: Node.js-зависимость, ориентирован на многостраничные доки с MDX-компонентами — overkill для «красивый рендер Markdown». Преобразование ссылок может конфликтовать с GitHub-форматом.

Почему не Hugo: Быстрый, но Go-шаблоны сложнее отлаживать. Нет встроенного поиска. Для нашего объёма контента скорость сборки не критична.

Почему не Astro: Полноценный веб-фреймворк — избыточен. Подошёл бы, если бы мы строили маркетинговый сайт с интерактивом, но это не текущая цель.


3. Структура файлов

Решение открытого вопроса: docs/ vs корень репо

Решение: docs_dir: . (корень репо = корень сайта), с исключениями.

Причина: не создаём отдельную папку docs/, не дублируем и не перемещаем файлы. MkDocs умеет работать с корнем репо как источником, исключая ненужное.

# mkdocs.yml (в корне репо)
docs_dir: .

Решение открытого вопроса: README.md как index

Решение: плагин awesome-pages или конфигурация nav с явным указанием.

MkDocs по умолчанию ищет index.md. Но мы хотим сохранить README.md (GitHub его рендерит на главной репо). Есть два пути:

  • Вариант A: Симлинк docs/index.md → ../README.md. Но мы не используем docs/.
  • Вариант B (выбран): В mkdocs.yml явно указать README.md как главную:
nav:
  - Роадмап: README.md
  - Моделирование данных:
    - Введение: dwh-modeling/README.md
    - SCD: dwh-modeling/SCD.md
    - Data Vault: dwh-modeling/DataVault.md
    - "Домашка: STG → DDS → DM": dwh-modeling/Homework_Customer_Status_DDS_DM.md

MkDocs Material корректно обрабатывает README.md файлы — рендерит их как index.html соответствующей директории.

Исключения из сборки

Файлы и папки, которые не должны попасть на сайт:

exclude_docs: |
  project/          # проектная документация (PRD, ADR)
  postgres-bookings/ # скрипты стенда (не контент сайта)
  AGENTS.md         # конфигурация для AI-агентов
  LICENSE           # лицензия (есть в footer)
  .gitignore

Итоговая структура репо

de-roadmap/
├── mkdocs.yml              ← конфиг сайта (единственный новый файл в корне)
├── README.md               ← главная страница сайта И главная страница GitHub
├── dwh-modeling/
│   ├── README.md           ← подстраница «Введение в DWH»
│   ├── SCD.md              ← подстраница
│   ├── DataVault.md        ← подстраница
│   └── Homework_*.md       ← подстраница
├── postgres-bookings/      ← исключён из сайта
├── project/                ← PRD, ADR — исключены из сайта
│   ├── PRD.md
│   └── ADR.md
├── .github/
│   └── workflows/
│       └── deploy-site.yml ← CI/CD pipeline
├── AGENTS.md               ← исключён из сайта
└── LICENSE

4. Стратегия ссылок (Dual Compatibility)

Проблема

GitHub рендерит ссылки вида [текст](dwh-modeling/SCD.md) как переход к файлу. MkDocs по умолчанию преобразует .md.html и может менять структуру URL.

Решение

Комбинация настроек MkDocs:

use_directory_urls: true  # /dwh-modeling/SCD/ вместо /dwh-modeling/SCD.html

И ссылки в Markdown пишем всегда как относительные пути к .md файлам:

<!-- Это работает и на GitHub, и в MkDocs -->
[Теория про SCD](dwh-modeling/SCD.md)
[Введение в DWH](dwh-modeling/README.md)

MkDocs Material автоматически резолвит .md ссылки в правильные URL сайта.

Кириллические якоря

GitHub генерирует якоря из кириллических заголовков с URL-encoding: ## Базы данных#базы-данных

MkDocs Material по умолчанию делает то же самое через расширение toc:

markdown_extensions:
  - toc:
      slugify: !!python/object/apply:pymdownx.slugs.slugify
        kwds:
          case: lower
      permalink: true

Риск: поведение может различаться на edge cases (спецсимволы, эмодзи в заголовках). Митигация — на этапе MVP протестировать все существующие якорные ссылки в README.


5. CI/CD Pipeline

GitHub Actions Workflow

# .github/workflows/deploy-site.yml
name: Deploy MkDocs to GitHub Pages

on:
  push:
    branches: [main]
  workflow_dispatch:  # ручной запуск для отладки

permissions:
  contents: read
  pages: write
  id-token: write

concurrency:
  group: "pages"
  cancel-in-progress: false

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v5
        with:
          python-version: '3.x'

      - run: pip install mkdocs-material

      - run: mkdocs build --strict
        # --strict: падает на warnings (битые ссылки, отсутствующие файлы)

      - uses: actions/upload-pages-artifact@v3
        with:
          path: site/

  deploy:
    needs: build
    runs-on: ubuntu-latest
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - id: deployment
        uses: actions/deploy-pages@v4

Что даёт --strict

Сборка упадёт, если:

  • Есть ссылка на несуществующий .md файл.
  • Есть битый якорь.
  • Есть warning от MkDocs.

Это наш автотест ссылок — бесплатно, в CI.


6. Конфигурация MkDocs Material

Минимальный mkdocs.yml для MVP

site_name: "DE Roadmap — Data Engineering с нуля до middle"
site_url: https://dementev-dev.github.io/de-roadmap/
site_description: "Роадмап по Data Engineering: SQL, Python, Airflow, Greenplum и далее"
site_author: Dmitry Dementev

repo_url: https://github.com/dementev-dev/de-roadmap
repo_name: dementev-dev/de-roadmap

docs_dir: .
site_dir: site

# Исключаем из сборки
exclude_docs: |
  project/
  postgres-bookings/
  AGENTS.md
  LICENSE
  .gitignore
  .github/
  site/

nav:
  - Роадмап: README.md
  - Моделирование данных:
    - Введение: dwh-modeling/README.md
    - SCD: dwh-modeling/SCD.md
    - Data Vault: dwh-modeling/DataVault.md
    - "Домашка: STG → DDS → DM": dwh-modeling/Homework_Customer_Status_DDS_DM.md

theme:
  name: material
  language: ru
  palette:
    - scheme: default
      primary: indigo
      accent: indigo
      toggle:
        icon: material/brightness-7
        name: Тёмная тема
    - scheme: slate
      primary: indigo
      accent: indigo
      toggle:
        icon: material/brightness-4
        name: Светлая тема
  features:
    - navigation.top          # кнопка «наверх»
    - navigation.tracking     # URL обновляется при скролле
    - search.suggest          # подсказки в поиске
    - search.highlight        # подсветка найденного
    - toc.follow              # TOC следит за скроллом
    - content.code.copy       # кнопка копирования кода

markdown_extensions:
  - toc:
      permalink: true
  - admonition                # сворачиваемые блоки (Спринт 2)
  - pymdownx.details          # для <details>
  - pymdownx.superfences      # вложенные блоки кода
  - pymdownx.highlight        # подсветка синтаксиса
  - attr_list                 # атрибуты для элементов

plugins:
  - search:
      lang: ru

Что уже включено в MVP (бесплатно с Material)

  • Тёмная/светлая тема с переключателем.
  • Полнотекстовый поиск на русском.
  • TOC (оглавление) в правом sidebar.
  • Кнопка «наверх» на длинной странице.
  • URL обновляется при скролле (можно дать ссылку на конкретный раздел).
  • Подсветка синтаксиса в блоках кода.
  • Кнопка копирования кода.
  • Ссылка на GitHub-репозиторий в шапке.

7. Кастомный домен (Спринт 2)

Домен dementev.space уже есть. Для подключения:

  1. Создать CNAME-запись: roadmap.dementev.space → dementev-dev.github.io.
  2. Добавить файл CNAME в корень репо с содержимым roadmap.dementev.space.
  3. В mkdocs.yml обновить site_url.
  4. Включить HTTPS в настройках GitHub Pages.

8. Риски и митигации

Риск Митигация
docs_dir: . подхватывает лишние файлы exclude_docs со списком исключений; --strict ловит проблемы
Кириллические якоря ведут себя по-разному Тестируем все якорные ссылки из README при первом деплое
README.md содержит GitHub-специфичный синтаксис Проверяем рендер; при необходимости используем MkDocs-совместимые альтернативы
Зависимость от mkdocs-material Активный проект (30k+ stars), Python-пакет; при необходимости — заморозить версию в requirements.txt
exclude_docs — относительно новая фича MkDocs Альтернатива: .mkdocsignore или плагин mkdocs-exclude; протестировать на MVP

9. Порядок действий (Спринт 1)

  1. Создать ветку feature/site.
  2. Добавить mkdocs.yml в корень репо.
  3. Добавить .github/workflows/deploy-site.yml.
  4. Добавить project/PRD.md и project/ADR.md.
  5. Проверить локально: pip install mkdocs-material && mkdocs serve.
  6. Протестировать все внутренние ссылки и якоря.
  7. При необходимости — адаптировать ссылки для dual compatibility.
  8. Merge в main → автодеплой → проверить https://dementev-dev.github.io/de-roadmap/.
  9. Включить GitHub Pages (Settings → Pages → Source: GitHub Actions).