Author SHA1 Message Date
ddadmin 86c67951da fix(site): сборка runner переведена со Snap uv на venv
- Зачем:
  - Snap uv не запускался внутри ограниченного systemd-сервиса без cap_dac_override.
- Что:
  - workflow переведён на системный Python, venv и pinned pip-зависимости.
  - Snap удалён из PATH runner, а runbook дополнен пакетом python3-venv.
- Проверка:
  - от имени gitea-runner выполнены clone, создание venv, pip install и mkdocs build --strict.
  - обновлённый systemd unit прошёл systemd-analyze verify и успешно перезапущен.
2026-08-04 16:06:24 -04:00
12 changed files with 119 additions and 514 deletions

No files matched your search

-2
View File
@@ -1,2 +0,0 @@
mkdocs-material==9.6.14
mkdocs-same-dir==0.1.3
-31
View File
@@ -1,31 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
readonly venv_dir="/var/lib/gitea-runner/venvs/site"
if [[ $# -ne 1 ]]; then
echo "Usage: $0 SOURCE_DIR" >&2
exit 2
fi
source_dir=$(realpath "$1")
requirements_file="${source_dir}/.gitea/requirements-site.txt"
if [[ ! -f $requirements_file ]]; then
echo "Requirements file not found: ${requirements_file}" >&2
exit 2
fi
mkdir -p "$(dirname "$venv_dir")"
if [[ ! -x "${venv_dir}/bin/python" ]]; then
python3 -m venv "$venv_dir"
fi
"${venv_dir}/bin/python" -m pip install \
--disable-pip-version-check \
--no-input \
--requirement "$requirements_file"
"${venv_dir}/bin/python" -m pip check
cd "$source_dir"
"${venv_dir}/bin/python" -m mkdocs build --strict
+10 -1
View File
@@ -31,7 +31,16 @@ jobs:
git -C source -c advice.detachedHead=false checkout --detach FETCH_HEAD
- name: Build the site strictly
run: source/.gitea/scripts/build-site.sh source
run: |
set -euo pipefail
cd source
python3 -m venv .venv
.venv/bin/python -m pip install \
--disable-pip-version-check \
--no-input \
'mkdocs-material==9.6.14' \
'mkdocs-same-dir==0.1.3'
.venv/bin/python -m mkdocs build --strict
- name: Publish the complete release atomically
env:
+2 -4
View File
@@ -55,12 +55,10 @@ All `.md` files MUST render correctly on both GitHub and the MkDocs Material sit
- Avoid: em-dash `—`, en-dash `–` — slug behavior differs between GitHub and MkDocs.
## MkDocs Site Commands
- Initialize or update the persistent local environment:
`python3 -m venv "${HOME}/.cache/de-roadmap-mkdocs" && "${HOME}/.cache/de-roadmap-mkdocs/bin/python" -m pip install -r .gitea/requirements-site.txt`
- Local preview (user starts, ask user to run via `!`):
`"${HOME}/.cache/de-roadmap-mkdocs/bin/python" -m mkdocs serve`
`uv run --with 'mkdocs-material==9.6.14' --with 'mkdocs-same-dir==0.1.3' mkdocs serve`
- Build with strict validation (catches broken links/anchors):
`"${HOME}/.cache/de-roadmap-mkdocs/bin/python" -m mkdocs build --strict`
`uv run --with 'mkdocs-material==9.6.14' --with 'mkdocs-same-dir==0.1.3' mkdocs build --strict`
- Visual check via Playwright (when `mkdocs serve` is running on port 8000):
`npx playwright screenshot --viewport-size='1280,800' 'http://127.0.0.1:8000/#anchor' /path/to/screenshot.png`
Then read the screenshot with the Read tool to inspect rendering. Use `--viewport-size='1280,2000'` for tall pages.
+59 -148
View File
@@ -4,7 +4,7 @@
Он подойдёт тем, кто хочет:
- системно войти в профессию с нуля или близкого к нулю уровня;
- закрыть пробелы в базе (SQL, Git, Python, DWH, Airflow, Greenplum, Kafka, ClickHouse);
- закрыть пробелы в базе (SQL, Git, Python, DWH, Airflow, Greenplum);
- подготовиться к собеседованиям и первым рабочим задачам.
Роадмап можно проходить самостоятельно или вместе со мной в формате менторства.
@@ -13,9 +13,9 @@
### Оглавление
- [Основные знания](#основные-знания) — Linux, Git, SQL, Python, методологии, Docker
- [Практика и инструменты](#практика-и-инструменты) - Airflow, Greenplum, Streaming, ClickHouse, две курсовые
- [Практика и инструменты](#практика-и-инструменты) — Airflow, Greenplum, курсовая работа
- [Карьера и менторство](#карьера-и-менторство) — резюме, собеседования, испытательный срок
- [Расширенные навыки](#расширенные-навыки) - Lakehouse, dbt
- [Расширенные навыки](#расширенные-навыки) — Streaming, ClickHouse, Lakehouse, dbt
- [Софт скиллы](#софт-скиллы)
- [Дополнительные материалы](#дополнительные-материалы)
@@ -25,11 +25,6 @@
- выполнять практику и домашки, а не только смотреть материалы;
- возвращаться к разделам по мере появления реальных задач.
Основная программа включает две курсовые: сначала хранилище на Greenplum,
затем [Clickstream на ClickHouse](#большая-курсовая-clickstream).
Streaming и ClickHouse входят в обязательную часть подготовки к трудоустройству.
Lakehouse и dbt можно изучать после нее, под задачи и интересующие вакансии.
---
## Основные знания
@@ -90,17 +85,12 @@ SQL и моделирование данных специально идут р
#### Повышение знаний SQL
**Перед DEV1: запустите учебную базу.** Для практики рекомендую
[стенд PostgreSQL с базой bookings](https://github.com/dementev-dev/de-roadmap/tree/main/postgres-bookings).
В README стенда описаны запуск в Docker, подключение через `psql` и DBeaver.
Это наше первое знакомство с Docker: пока достаточно научиться запускать
и останавливать стенд, смотреть его статус и подключаться к базе.
Подробный [блок Docker](#docker) будет дальше.
Смотрим курс от Postgres Pro [DEV1](https://postgrespro.ru/education/courses/DEV1)
Темы - от "Введение" до "SQL" включительно, "Управление доступом", "Резервное копирование". Для лучшего усваивания материала проделываем все примеры и домашние задания из конспектов лекций.
С темой "PL/pgSQL" можно ознакомиться обзорно.
Для развития навыков инженера будет полезно лабораторные работы делать не в виртуальной машине, а в docker контейнере. Предложенный (не обязательный) вариант - в каталоге `postgres-bookings` репозитория.
Для дальнейшего закрепления материала - читаем книгу [PostgreSQL. Основы языка SQL](https://postgrespro.ru/education/books/sqlprimer)
- Глава 8 - Индексы + ДЗ
@@ -108,7 +98,7 @@ SQL и моделирование данных специально идут р
- Глава 10 - Повышение производительности + ДЗ
Вопросы оптимизации запросов хорошо описаны в курсе [QPT](https://postgrespro.ru/education/courses/QPT) от Postgres Pro. Полученные навыки применимы для работы в том числе с Greenplum, и частично, другими БД.
На странице курса выбирайте материалы и видеозаписи для PostgreSQL 16.
На момент написания, видеолекции были доступны только для старой версии Postgres 13, но ее вполне достаточно.
#### Моделирование данных
Понимание того, **как устроены данные и зачем они нужны**, — ключ к качественным ETL-процессам.
@@ -130,9 +120,7 @@ SQL и моделирование данных специально идут р
- Теория про Slowly Changing Dimensions: [SCD](dwh-modeling/SCD.md)
- (Опционально) Ральф Кимбалл — «Инструментарий хранения и анализа данных» (The Data Warehouse Toolkit) - первые 3 главы
- Практика по моделированию статусов клиента: [домашка STG → ODS → DDS → DM](dwh-modeling/Homework_Customer_Status_DDS_DM.md)
- Data Vault и Anchor Modeling изучаем обзорно, для знакомства с основными
понятиями. Глубокий разбор и самостоятельное проектирование на этом этапе
не требуются. Материалы для знакомства:
- Еще про Data Vault:
- Конспект и примеры из этого репозитория: [DataVault.md](dwh-modeling/DataVault.md)
- [DataVault за 10 минут - Youtube](https://www.youtube.com/watch?v=9oQs_wJ045I)
- Статья [«Что такое Data Vault: моделирование КХД для архитектора Big Data»](https://bigdataschool.ru/blog/what-is-data-vault/) — обзор, плюсы/минусы, контекст применения.
@@ -151,36 +139,13 @@ SQL и моделирование данных специально идут р
### Python
Если совсем не знакомы с Python, начинаем с курса ["Поколение Python": курс для начинающих - Stepik](https://stepik.org/course/58852/info).
Перед курсом для продвинутых подготовьте рабочую среду. Она пригодится для
экспериментов с кодом и домашних заданий.
- Виртуальные окружения (venv) изолируют зависимости проекта:
- [Habr: как настроить виртуальное окружение](https://habr.com/ru/articles/889670/)
- [SkillFactory: Виртуальные окружения в Python](https://blog.skillfactory.ru/venv-virtualnoe-okruzhenie-v-python/)
- [Создание venv и установка пакетов: документация Python](https://docs.python.org/3/tutorial/venv.html)
- JupyterLab позволяет выполнять код по ячейкам и сохранять пояснения рядом с результатами:
- [Блог Практикума: что такое Jupyter Notebook](https://practicum.yandex.ru/blog/chto-takoe-jupyter-notebook/)
- [Установка JupyterLab](https://jupyterlab.readthedocs.io/en/stable/getting_started/installation.html)
Создайте venv, установите в него JupyterLab и запустите из этого же окружения.
В новом ноутбуке выполните несколько ячеек, сохраните `.ipynb`, перезапустите
ядро и выполните все ячейки по порядку. В Git сохраняйте ноутбуки и скрипты,
а каталог `.venv/` добавьте в `.gitignore`.
Теперь продолжаем изучать Python:
- Если совсем не знакомы с Python, начинаем с курса ["Поколение Python": курс для начинающих – Stepik](https://stepik.org/course/58852/info)
- Изучаем глубже и "оттачиваем" live coding: ["Поколение Python": курс для продвинутых – Stepik](https://stepik.org/course/68343/info)
- Продолжение "базы", спрашиваемой на собеседованиях, по Python: ["Поколение Python": курс для профессионалов](https://stepik.org/course/82541/promo). Курс очень полезный, но платный. Вместо него можно почитать "продвинутые" темы дальше.
- "Продвинутые" темы:
- [Полезные функции](https://pyneng.readthedocs.io/ru/latest/book/10_useful_functions/index.html)
- [Работа с файлами в формате CSV, JSON, YAML](https://pyneng.readthedocs.io/ru/latest/book/17_serialization/index.html)
- [Итераторы, итерируемые объекты и генераторы](https://pyneng.readthedocs.io/ru/latest/book/13_iterator_generator/index.html)
- Управление памятью (документация на английском):
- [Объекты, ссылки и изменяемость](https://docs.python.org/3/reference/datamodel.html#objects-values-and-types) - почему два имени могут указывать на один список и что происходит при его изменении.
- [Как Python управляет памятью](https://docs.python.org/3/faq/design.html#how-does-python-manage-memory) - подсчет ссылок и сборка циклов в CPython; особенности других реализаций Python.
- [Модуль gc](https://docs.python.org/3/library/gc.html) - справочник для экспериментов со сборщиком мусора. Детали поколений и порогов смотрите для своей версии Python.
- [Декораторы Python: пошаговое руководство](https://habr.com/ru/companies/otus/articles/727590/)
- Работа с датой/временем: [официальная документация по модулю datetime](https://docs.python.org/3/library/datetime.html)
- [Сложность алгоритмов. Разбор Big O](https://habr.com/ru/articles/782608/) — короткий материал, чтобы понимать O(n) vs O(n²) на собеседованиях и в коде
@@ -189,6 +154,12 @@ SQL и моделирование данных специально идут р
- Введение в [ООП](https://metanit.com/python/tutorial/7.1.php)
- [Яндекс Учебник: «Объектная модель Python: классы, поля и методы»](https://education.yandex.ru/handbook/python/article/obuektnaya-model-python-klassy-polya-i-metody)
- [Real Python: OOP in Python (tutorial)](https://realpython.com/python3-object-oriented-programming/)
- Виртуальные окружения (venv) — изолируют зависимости проекта; настройте перед установкой Jupyter и библиотек
- [Habr: как настроить виртуальное окружение](https://habr.com/ru/articles/889670/)
- [SkillFactory: Виртуальные окружения в Python](https://blog.skillfactory.ru/venv-virtualnoe-okruzhenie-v-python/)
- Jupyter Lab
- [Блог Практикума: «Что такое Jupyter Notebook: как установить и открыть»](https://practicum.yandex.ru/blog/chto-takoe-jupyter-notebook/)
- Готовая реализация Jupyter Lab, включающая в себя Spark, в Docker: [jupyter-spark-docker](https://github.com/dementev-dev/jupyter-spark-docker)
- Pandas
- [GeeksforGeeks: “Why Pandas is Used in Python”](https://www.geeksforgeeks.org/pandas/why-pandas-is-used-in-python/)
- [Skillbox: «Для чего нужна библиотека Pandas»](https://skillbox.ru/media/code/rabotaem-s-pandas-osnovnye-ponyatiya-i-realnye-dannye/)
@@ -202,14 +173,10 @@ SQL и моделирование данных специально идут р
**Когда блок Python считаем пройденным:**
- создаете venv, устанавливаете в него пакеты и запускаете JupyterLab; можете повторить вычисления в ноутбуке после перезапуска ядра;
- вы без подсказок пишете небольшие скрипты с циклами, функциями, обработкой ошибок и работой с коллекциями;
- умеете читать и модифицировать чужой код, в том числе с использованием pandas и DataFrame;
- уверенно проходите простой live-coding по Python для DE: прочитать CSV/JSON, отфильтровать, сгруппировать данные и посчитать агрегаты.
- можете отвечать как на простые вопросы собеседований (циклы, списки, словари), так и продвинутые (итераторы, декораторы, базовые понятия ООП);
- на примере со списком объясняете разницу между объектом и ссылкой на него,
почему `del` одного имени не обязательно уничтожает объект и зачем CPython
нужен сборщик циклического мусора.
- можете отвечать как на простые вопросы собеседований (циклы, списки, словари), так и продвинутые (итераторы, декораторы, управление памятью, базовые понятия ООП)
### Методологии разработки
@@ -317,20 +284,11 @@ Apache Airflow — инструмент для оркестрации ETL-про
Материалы:
- [Учебник по Airflow](https://github.com/dementev-dev/airflow-manual)
- [Практические задания на стенде](https://github.com/dementev-dev/airflow-manual/blob/main/educational-tasks.md)
Задания выполняем параллельно с чтением учебника. Начинаем с простых DAG
и SQL, затем обрабатываем файлы, загружаем CSV в PostgreSQL и добавляем
проверки качества. Дальше расширяем ETL, разбираем ветвление, повторные
попытки и логирование. Здесь Python и SQL впервые работают вместе
в пайплайне, которым управляет Airflow.
**Когда блок Airflow считаем пройденным:**
- вы можете объяснить, что такое DAG, задачи, операторы и сенсоры, и как между ними задаются зависимости;
- на базе учебного стенда подготавливаете, отлаживаете и запускаете свои DAG'и с расписанием и несколькими шагами (например, загрузка данных и последующие трансформации);
- расширяете загрузку CSV в PostgreSQL: меняете генерацию данных, схему таблицы и загрузку новой колонки;
- добавляете свою проверку качества и убеждаетесь, что она обнаруживает подготовленную ошибку в данных;
- уверенно смотрите логи, находите место падения и понимаете, как перезапустить задачу.
### Greenplum
@@ -366,8 +324,7 @@ Apache Airflow — инструмент для оркестрации ETL-про
- можете объяснить, в чём практическая разница между MPP-хранилищем и одиночным Postgres на уровне типичных задач DE и собеседований.
### Курсовая работа
Первая курсовая собирает изученное в один проект: загрузку данных из PostgreSQL,
слои хранилища в Greenplum и управление обработкой через Airflow.
Курсовая работа — важный майлстоун роадмапа: ваш первый end-to-end data-проект. После неё у вас есть ключевые технические навыки для старта карьеры в Data Engineering.
Курсовая выполняется на том же стенде [airflow-dwh-gp-lab](https://github.com/dementev-dev/airflow-greenplum), который вы уже использовали для практики по Greenplum.
@@ -385,86 +342,6 @@ Apache Airflow — инструмент для оркестрации ETL-про
- автоматическая проверка (валидационный DAG) проходит без ошибок;
- вы можете на собеседовании за 5–10 минут рассказать архитектуру проекта, его цели и показать ключевые части кода.
После этой работы переходим к потокам событий и ClickHouse. Они понадобятся
для [большой курсовой Clickstream](#большая-курсовая-clickstream).
### Streaming (NiFi + Kafka)
В первой курсовой мы загружали данные из базы. Теперь разберем прием потока
событий: как доставить их в хранилище и продолжить чтение после остановки
обработчика. NiFi помогает собрать поток обработки визуально, Kafka хранит
события в распределенном журнале и позволяет потребителям читать их независимо.
Материалы:
- [Apache NiFi с нуля за 3 часа (Youtube-плейлист)](https://youtube.com/playlist?list=PL4MpKy3QjNp_rOEEibc4Ro8UK4g8vLX6_&si=W_hidjHmBOZ_aUfS) — первые 4 видео, дальше — по желанию
- [Лучший Гайд по Kafka для Начинающих За 1 Час (Youtube)](https://www.youtube.com/watch?v=hbseyn-CfXY)
Практика — на стенде [nifi-kafka-postgres-lab](https://github.com/dementev-dev/nifi-kafka-postgres-lab) (Docker Compose с NiFi, Kafka и Postgres):
- настраиваем в NiFi простой генератор данных и поток в Postgres;
- строим поток NiFi → Kafka → NiFi → Postgres.
**Перед большой курсовой нужно уметь:**
- объяснить связь между топиком, партицией, consumer group и offset;
- отправить сообщения в Kafka и прочитать их потребителем;
- показать на учебном потоке, откуда продолжится чтение после перезапуска,
и объяснить, почему при повторной доставке могут появиться дубли.
В [курсовой Clickstream](#большая-курсовая-clickstream) события и заказы
поступают через Kafka в ClickHouse. Вернемся к этим вопросам, когда будем
разбирать прием данных и их обработку в хранилище.
### ClickHouse
ClickHouse используем для аналитики по событиям и заказам. Здесь нужно
разобраться, как хранить данные, выбирать ключ сортировки и строить витрины.
Затем применим это в большой курсовой.
Материалы:
- Бесплатный курс [ClickHouse от Yandex Cloud](https://yandex.cloud/ru/training/clickhouse) берем за основу.
Практика:
Упражнения по самой СУБД можно выполнять локально на
[clickhouse-learning-cluster](https://github.com/dementev-dev/clickhouse-learning-cluster):
четыре узла ClickHouse в Docker Compose, репликация, шардинг и HAProxy.
Задания по облачной инфраструктуре требуют Yandex Cloud и оплаты ресурсов.
**Когда готовы переходить к курсовой:**
- создаете таблицы семейства MergeTree и объясняете выбор `ORDER BY` и `PARTITION BY`;
- различаете шардирование и репликацию, понимаете роль таблиц Distributed;
- загружаете данные, пишете аналитические запросы и можете объяснить,
как устройство таблицы влияет на чтение данных.
### Большая курсовая: Clickstream
На стенде [clickstream-data-platform](https://github.com/dementev-dev/clickstream-data-platform)
работаем с хранилищем интернет-магазина. Генератор создает события посетителей
и заказы, Kafka доставляет их в ClickHouse. Данные проходят слои STG, ODS,
DDS и DM; Airflow управляет обработкой, Superset показывает отчеты.
Часть хранилища уже работает. В заданиях вы строите свои витрины, разбираете
готовые загрузки и меняете их, сверяя результат с исходными данными.
Проверки качества и мониторинг нужны здесь для конкретных задач: заметить
потери и дубли, найти причину расхождения, проверить результат своей правки.
Начните с запуска по README репозитория, затем прочитайте
[путеводитель по стенду](https://github.com/dementev-dev/clickstream-data-platform/blob/main/docs/handbook/README.md)
и переходите к [учебным заданиям](https://github.com/dementev-dev/clickstream-data-platform/blob/main/docs/labs/README.md).
В основной программе семь ступеней: пять витрин DM, свой график в Superset,
самостоятельная нарезка сессий, изменение расчета сессий в конвейере,
проверки и обработка заказов, разбор сырых событий, мониторинг.
Факультативные расследования можно взять после основной программы.
**Когда большую курсовую считаем пройденной:**
- выполнены семь ступеней основной программы и проверки из заданий;
- пять учебных витрин проходят `homework_check`, в Superset построен свой график;
- можете проследить путь события от Kafka до отчета, объяснить свои изменения
и показать, как проверяли их корректность.
---
## Карьера и менторство
@@ -517,12 +394,49 @@ DDS и DM; Airflow управляет обработкой, Superset показ
---
## Расширенные навыки
После двух курсовых можно расширить стек: попробовать обработку файлов
в Lakehouse и управление SQL-моделями через dbt. Выбирайте тему под задачи,
с которыми хотите работать.
Эти темы выходят за рамки базового минимума для старта в Data Engineering, но дают более полное представление об экосистеме.
Их цель — понимать, зачем и когда используется тот или иной инструмент, а не осваивать его на уровне администратора или DevOps-инженера.
[[к оглавлению]](#оглавление)
Мы кратко знакомимся с:
- **Streaming** (NiFi + Kafka) — инструментами для построения потоковых и интеграционных пайплайнов;
- **ClickHouse** — колоночной СУБД для высоконагруженной аналитики;
- **Lakehouse** (Spark, Iceberg, Trino) — архитектурой, построенной на разделении compute и storage;
- **dbt** — подходом к трансформации данных как кода.
Практика ограничивается минимальным рабочим примером (запуск в Docker, простой пайплайн или SQL-модель).
Этого достаточно, чтобы уверенно говорить об инструменте на собеседовании и понимать его место в архитектуре — а всё остальное при необходимости осваивается уже на проекте.
### Streaming (NiFi + Kafka)
NiFi — визуальный конструктор потоков данных, Kafka — распределённая очередь сообщений. Вместе они закрывают типичный сценарий: принять данные, буферизовать, доставить в хранилище.
Материалы:
- [Apache NiFi с нуля за 3 часа (Youtube-плейлист)](https://youtube.com/playlist?list=PL4MpKy3QjNp_rOEEibc4Ro8UK4g8vLX6_&si=W_hidjHmBOZ_aUfS) — первые 4 видео, дальше — по желанию
- [Лучший Гайд по Kafka для Начинающих За 1 Час (Youtube)](https://www.youtube.com/watch?v=hbseyn-CfXY)
Практика — на стенде [nifi-kafka-postgres-lab](https://github.com/dementev-dev/nifi-kafka-postgres-lab) (Docker Compose с NiFi, Kafka и Postgres):
- настраиваем в NiFi простой генератор данных и поток в Postgres;
- строим поток NiFi → Kafka → NiFi → Postgres.
Знакомство с Kafka здесь пригодится и дальше: стенд по ClickHouse в следующей секции принимает данные именно через Kafka.
### ClickHouse
ClickHouse — колоночная СУБД для аналитики на больших объёмах: миллиарды строк, агрегации за секунды. В российских компаниях это фактический стандарт для витрин, отчётности и продуктовой аналитики, поэтому на собеседованиях тема всплывает часто.
Материалы:
- Бесплатный курс [ClickHouse от Yandex Cloud](https://yandex.cloud/ru/training/clickhouse) — берём за основу, в нём много упражнений
- Платный курс [ClickHouse для аналитика – Stepik](https://stepik.org/course/100210/promo?search=6551441002)
Практика:
- Упражнения курса Яндекса можно выполнять в их облаке (с оплатой за ресурсы) или бесплатно у себя — на учебном кластере [clickhouse-learning-cluster](https://github.com/dementev-dev/clickhouse-learning-cluster): 4 узла ClickHouse в Docker Compose, репликация, шардинг, балансировка через HAProxy.
- Следующий шаг — стенд [clickstream-ch-kafka-superset-demo](https://github.com/dementev-dev/clickstream-ch-kafka-superset-demo), имитирующий полноценное аналитическое хранилище на ClickHouse: Kafka, Airflow, дашборды в Superset, мониторинг (Prometheus/Grafana), слои STG → ODS → DDS → DM. Внутри — собственный продвинутый курс «Кликстрим на ClickHouse» с уроками прямо на стенде.
### Lakehouse (Spark, Iceberg, Trino)
Lakehouse — архитектурный подход, который соединяет гибкость Data Lake с гарантиями классического DWH.
@@ -566,12 +480,9 @@ dbt (data build tool) — инструмент для трансформации
**Когда блок расширенных навыков считаем пройденным:**
Оценивайте выбранную тему по результату практики:
- для Lakehouse можете записать таблицу через Spark, прочитать ее через Trino
и объяснить роль Iceberg, каталога и объектного хранилища;
- для dbt можете изменить SQL-модель, выполнить сборку и тесты,
посмотреть зависимости в документации проекта.
- вы можете на собеседовании кратко объяснить, когда уместны Streaming (NiFi/Kafka), ClickHouse, Lakehouse-стек и dbt, и чем они дополняют базовый стек (Postgres, Airflow, Greenplum);
- понимаете типичные сценарии: потоковые интеграции и очереди (NiFi + Kafka), аналитические витрины и отчёты на ClickHouse, Lakehouse-архитектура (Spark/Iceberg/Trino), трансформации данных как код (dbt);
- не боитесь увидеть эти инструменты в описании вакансии и можете поддержать содержательный разговор об их месте в архитектуре.
---
+6 -6
View File
@@ -1,10 +1,10 @@
site_name: "DE Roadmap — Data Engineering с нуля до middle"
site_url: https://de.dementev.space/
site_description: "Роадмап по Data Engineering: SQL, Python, Airflow, Greenplum, Kafka и ClickHouse"
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
repo_url: https://git.dementev.space/ddmitry/de-roadmap
repo_name: ddmitry/de-roadmap
docs_dir: .
site_dir: site
@@ -76,9 +76,9 @@ markdown_extensions:
extra:
social:
- icon: fontawesome/brands/github
link: https://github.com/dementev-dev/de-roadmap
name: GitHub
- icon: simple/gitea
link: https://git.dementev.space/ddmitry/de-roadmap
name: Gitea
- icon: fontawesome/brands/telegram
link: https://t.me/dementev_dev
name: Написать в Telegram
+5 -9
View File
@@ -8,13 +8,10 @@
### Текущее состояние
Роадмап по Data Engineering живет как Git-репозиторий. Основной origin
и работа над материалами остаются в собственной Gitea
([ddmitry/de-roadmap](https://git.dementev.space/ddmitry/de-roadmap)).
После восстановления аккаунта GitHub изменения зеркалируются туда средствами
Gitea. Ссылки для менти ведут на [GitHub](https://github.com/dementev-dev/de-roadmap),
откуда удобно клонировать стенды и делать свои форки. Сайт по-прежнему
публикуется через Gitea Actions на VPS; GitHub Pages сохраняется как резерв.
Роадмап по Data Engineering живёт как Git-репозиторий. Основной origin
размещён в собственной Gitea
([ddmitry/de-roadmap](https://git.dementev.space/ddmitry/de-roadmap)), а
GitHub Pages сохраняется как резерв после восстановления доступа к GitHub:
- Основной контент — монолитный `README.md` (~700 строк) с полным учебным планом.
- Дополнительные материалы — в подпапках (`dwh-modeling/`, `postgres-bookings/`): теория DWH-моделирования, SCD, Data Vault, домашние задания, скрипты.
@@ -91,8 +88,7 @@ GitHub README — рабочий, но не презентабельный фо
### 4.2. Желательные (Спринт 2+)
- [x] Кастомный домен: `de.dementev.space` (подключён 2026-03-27, переведён на
VPS 2026-08-05).
- [x] Кастомный домен: `de.dementev.space` (подключён 2026-03-27).
- [x] Тёмная тема (переключатель light/dark).
- [x] Сворачиваемые блоки (`<details>`) — точечно, для подсказок/решений в домашках (2026-03-29).
- [x] Кнопка «Написать в Telegram» — floating-кнопка + иконки в футере (2026-03-29).
+3 -42
View File
@@ -4,29 +4,12 @@
## P1
- [ ] **Проверить синхронизацию GitHub-зеркала `airflow-greenplum`.**
Проверка через `git ls-remote` 2026-09-27: GitHub отстает от Gitea
на коммит `4ed7e6f`, меняющий только `docs/agents/triage-labels.md`.
Учебные материалы совпадают. У `airflow-manual`, `mini-lakehouse-lab`
и `de-roadmap` ветки `main` в Gitea и GitHub совпали; прежнее подозрение
об их отставании по ответам API не подтвердилось.
- [ ] **Перенести публикацию сайта на Gitea Actions и VPS.**
Настроить repository-scoped host runner, строгую сборку MkDocs, атомарные
релизы, nginx и TLS для `de.dementev.space` по согласованной спецификации.
## P2
- [ ] **Проработать инструкции по прохождению крупных блоков.**
Начать с Python: определить части внешних курсов, глубину изучения
и практику для бесплатной альтернативы. Далее связать DEV1, книгу и QPT,
затем главы Airflow с существующими заданиями.
[Черновик обсуждения](specs/2026-09-27-learning-route.md).
- [ ] **Дополнить практику Kafka перед Clickstream.**
В `nifi-kafka-postgres-lab` добавить опыты на существующем потоке:
остановить потребителя и дочитать накопившиеся сообщения; прочитать
события двумя независимыми consumer groups; повторить чтение и проверить
дубли в PostgreSQL. Для каждого опыта описать исходное состояние,
действия и проверку результата. Идея согласована 2026-09-27;
реализация в репозитории стенда еще не начата.
- [ ] **Перенос учебника Airflow в de-roadmap.**
Перенести 9 глав учебника из `airflow-manual` в `airflow/` (de-roadmap).
В `airflow-manual` оставить только стенд (`airflow-docker/`).
@@ -62,28 +45,6 @@
## Сделано
- [x] **Исправлена ссылка на практику Airflow** — 2026-10-18:
`educational-tasks.md` перенесён в корень `airflow-manual`; ссылка в роадмапе
обновлена, новая страница возвращает HTTP 200. Проверены HTTP-ответы
118 внешних адресов; единственный полученный 404 исправлен. Ответы
403/502 и капча не подтверждают недоступность материала для читателя;
доступность видео YouTube по HTTP-статусу не определяется.
- [x] **Актуализация маршрута и учебных ссылок** - 2026-09-27:
ссылки на стенды, SQL и данные, кнопки репозитория на сайте возвращены
на GitHub; рабочий origin и публикация сайта остаются в Gitea.
Streaming и ClickHouse включены в основную программу перед трудоустройством,
`clickstream-data-platform` стал второй, большой курсовой с критериями
прохождения. Ссылка на курс ClickHouse для аналитика удалена.
venv и JupyterLab перенесены перед курсом Python для продвинутых;
в альтернативу курсу для профи добавлены материалы по управлению памятью
и критерий проверки понимания.
- [x] **Публикация сайта перенесена на Gitea Actions и VPS** —
2026-08-05: настроены repository-scoped host runner, строгая сборка MkDocs,
атомарные релизы, nginx и TLS для `de.dementev.space`; GitHub Pages сохранён
как неактивный резерв.
- [x] **Подраздел «Linux и терминал» в блоке базовых инструментов** —
2026-07-12: видео-интро («Девопс на троечку», покрытие проверено по
субтитрам) + три статьи (навигация и grep — habr, права — FirstVDS,
+25 -151
View File
@@ -12,38 +12,14 @@
- Пользователь сервиса: `gitea-runner`, без `sudo` и Docker.
- Корень публикации: `/srv/de-roadmap`.
- Хранение: текущий релиз и две предыдущие версии.
- Окружение сборки: `/var/lib/gitea-runner/venvs/site`.
- Публичный IPv4 VPS: `167.224.64.252`.
## Предварительные условия
- Есть пользователь с `sudo` и рабочий SSH-доступ к VPS.
- Есть доступ к управлению DNS-зоной `dementev.space`.
- В репозитории `ddmitry/de-roadmap` включены Gitea Actions.
## Подготовка VPS
Установить Git, HTTP-сервер, Certbot, UFW и Python venv:
Установить HTTP-сервер и Certbot:
```bash
sudo apt-get update
sudo apt-get install \
ca-certificates \
certbot \
curl \
git \
jq \
nginx \
python3-certbot-nginx \
python3-venv \
ufw
```
Получить административный checkout, из которого устанавливаются tracked-файлы:
```bash
git clone https://git.dementev.space/ddmitry/de-roadmap.git
cd de-roadmap
sudo apt-get install nginx certbot python3-certbot-nginx python3-venv
```
Создать пользователя и каталоги:
@@ -117,19 +93,14 @@ sudo rm /var/lib/gitea-runner/.registration-token
sudo chmod 0600 /var/lib/gitea-runner/.runner
sudo systemctl daemon-reload
sudo systemctl enable --now gitea-runner
systemctl is-enabled gitea-runner
systemctl is-active gitea-runner
```
Временный файл с токеном удаляют сразу после успешной регистрации. В Gitea на
странице Settings → Actions → Runners runner `de-roadmap-vps` должен перейти в
состояние online и показывать метку `de-roadmap-host`.
Временный файл с токеном удаляют сразу после успешной регистрации.
## Nginx и первичная публикация
Из корня репозитория установить bootstrap-конфигурацию nginx, создать ссылку,
отключить стандартный сайт Ubuntu и только затем перечитать проверенную
конфигурацию:
Из корня репозитория установить virtual host, создать ссылку и только затем
перечитать проверенную конфигурацию:
```bash
sudo install -o root -g root -m 0644 \
@@ -138,146 +109,49 @@ sudo install -o root -g root -m 0644 \
sudo ln -s \
/etc/nginx/sites-available/de-roadmap \
/etc/nginx/sites-enabled/de-roadmap
sudo unlink /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx
```
Первый server block в `nginx.conf` возвращает `404` для неизвестных HTTP Host,
не раскрывает версию nginx и отклоняет TLS handshake для IP или неизвестного
SNI. Поэтому сертификат `de.dementev.space` не выдаётся при обращении к VPS по
IP. Если проверка конфигурации не прошла, отключить новый virtual host,
восстановить стандартный сайт и перечитать проверенную конфигурацию:
Default-сайт можно отключить только после успешной проверки нового virtual
host.
До первого workflow можно собрать сайт вручную и опубликовать его тем же
скриптом с тестовым release id. Проверка до переключения DNS:
```bash
sudo unlink /etc/nginx/sites-enabled/de-roadmap
sudo ln -s \
/etc/nginx/sites-available/default \
/etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx
curl --header 'Host: de.dementev.space' http://127.0.0.1/
```
Файл `project/ops/gitea-vps-site/nginx.conf` предназначен только для запуска до
выпуска сертификата. После выпуска сертификата Certbot изменяет установленный
virtual host. Повторная установка bootstrap-файла поверх рабочего конфига
удалит TLS-директивы.
## Окружение сборки
Скрипт `.gitea/scripts/build-site.sh` создаёт persistent venv при первом запуске
и переиспользует его в следующих сборках. `pip install` выполняется каждый раз,
чтобы применить изменения `.gitea/requirements-site.txt`, но уже установленные
версии пакетов не переустанавливаются.
## Первый деплой
В Gitea открыть Actions → Deploy MkDocs to VPS, выбрать ветку `main` и нажать
Run workflow. Job `deploy` должен завершиться успешно. Проверить опубликованный
release и локальную выдачу nginx до переключения DNS:
```bash
readlink -f /srv/de-roadmap/current
curl --fail --header 'Host: de.dementev.space' http://127.0.0.1/
```
Затем разрешить SSH, HTTP и HTTPS в UFW. Если SSH работает не на стандартном
порту `22`, сначала разрешить фактический порт вместо профиля `OpenSSH`:
```bash
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
sudo ufw status verbose
```
Ожидается политика `deny (incoming)` и разрешения только для SSH, `80/tcp` и
`443/tcp`.
После локальной проверки разрешить профили `Nginx Full` в UFW. До этого
публичные порты `80/tcp` и `443/tcp` должны оставаться закрытыми.
## DNS и TLS
1. Уменьшить TTL записи `de.dementev.space`.
2. Направить `A` на VPS; удалить или корректно направить `AAAA`.
3. Убедиться, что сайт доступен извне по HTTP:
3. Убедиться, что сайт доступен извне по HTTP.
4. Выпустить сертификат:
```bash
curl --fail --head http://de.dementev.space/
sudo certbot --nginx -d de.dementev.space
```
4. Выпустить сертификат и включить перенаправление HTTP на HTTPS:
```bash
sudo certbot --nginx \
--non-interactive \
--agree-tos \
--email me@dementev.space \
--redirect \
-d de.dementev.space
```
5. В созданном Certbot HTTP-блоке для `de.dementev.space` добавить
`server_tokens off;`, затем проверить и перечитать конфигурацию:
```bash
sudoedit /etc/nginx/sites-available/de-roadmap
sudo nginx -t
sudo systemctl reload nginx
```
6. Проверить перенаправление, HTTPS, сертификат и автоматическое продление:
```bash
curl --head http://de.dementev.space/
curl --fail --head https://de.dementev.space/
! curl --insecure --head https://167.224.64.252/
sudo certbot certificates
systemctl is-enabled certbot.timer
systemctl is-active certbot.timer
```
Ожидаются `301 Moved Permanently`, затем `200 OK`, отказ TLS по IP,
действующий сертификат и состояния таймера `enabled` и `active`.
7. Вернуть обычный DNS TTL.
5. Проверить HTTPS и `systemctl status certbot.timer`.
6. Вернуть обычный DNS TTL.
## Проверка и откат
Активная версия определяется ссылкой `/srv/de-roadmap/current`. Для ручного
отката сначала выбрать точный release id из сохранённых каталогов, затем создать
временную ссылку и атомарно заменить `current`:
```bash
find /srv/de-roadmap/releases \
-mindepth 1 \
-maxdepth 1 \
-type d \
-printf '%f\n' \
| sort
rollback_release='<COMMIT_SHA>-<RUN_ID>'
rollback_link='/srv/de-roadmap/.current.rollback'
[[ "$rollback_release" =~ ^[0-9a-f]{40}-[0-9]+$ ]]
sudo test -d "/srv/de-roadmap/releases/${rollback_release}"
sudo test ! -e "$rollback_link"
sudo -u gitea-runner \
ln -s "releases/${rollback_release}" "$rollback_link"
sudo -u gitea-runner \
mv -Tf "$rollback_link" /srv/de-roadmap/current
readlink -f /srv/de-roadmap/current
curl --fail --head https://de.dementev.space/
```
Откат не удаляет более новые releases. Перед их ручным удалением всегда
проверять результат `readlink -f /srv/de-roadmap/current`.
отката создать временную ссылку на нужный каталог в `releases/` и атомарно
заменить `current` через `mv -Tf`. Перед удалением релиза всегда проверять
результат `readlink -f /srv/de-roadmap/current`.
Диагностика:
```bash
sudo systemctl status gitea-runner
sudo journalctl -u gitea-runner
sudo nginx -t
readlink -f /srv/de-roadmap/current
curl --fail --head https://de.dementev.space/
systemctl status gitea-runner
journalctl -u gitea-runner
nginx -t
curl --header 'Host: de.dementev.space' http://127.0.0.1/
```
-13
View File
@@ -1,16 +1,3 @@
server {
listen 80 default_server;
listen [::]:80 default_server;
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
server_name _;
server_tokens off;
ssl_reject_handshake on;
return 404;
}
server {
listen 80;
listen [::]:80;
@@ -1,10 +1,7 @@
# Публикация сайта через Gitea Actions и VPS
Статус: публикация на VPS реализована 2026-08-05. После восстановления
доступа к GitHub выбран встроенный push mirror Gitea для синхронизации
репозиториев; рабочий origin остается в Gitea. Инструкции по
восстановлению и эксплуатации находятся в
[`project/ops/gitea-vps-site/README.md`](../ops/gitea-vps-site/README.md).
Статус: согласовано 2026-08-04; механизм синхронизации GitHub-резерва
требует отдельного решения после восстановления доступа к GitHub.
## Проблема
@@ -29,7 +26,7 @@
- Изменение существующих файлов в `.github/workflows/`.
- Добавление динамического приложения, авторизации или серверной базы данных.
## Исходное состояние на 2026-08-04
## Текущее состояние
- MkDocs Material собирает статический каталог `site/`; `site_url` уже равен `https://de.dementev.space/`.
- Публичный репозиторий `ddmitry/de-roadmap` в Gitea является текущим `origin`.
@@ -67,11 +64,7 @@ TLS-сертификат для `de.dementev.space` получает и прод
### Резерв на GitHub Pages
Изменения из основной Gitea передаются на GitHub встроенным push mirror.
Ссылки для учащихся ведут на GitHub-зеркала, основной домен остается на VPS.
Workflow в `.github/workflows/deploy-site.yml` сохранен для резервной
публикации. Перед использованием резерва нужно проверить настройки Pages
и успешный деплой: наличие зеркала репозитория само по себе этого не подтверждает.
После восстановления доступа к GitHub существующий GitHub workflow продолжает собирать сайт из GitHub-репозитория. Чтобы резерв оставался актуальным, изменения из основной Gitea должны автоматически синхронизироваться с GitHub. Предпочтительный кандидат — встроенный Gitea push mirror; окончательный механизм и его права будут согласованы отдельно после восстановления учётной записи. Резерв доступен по стандартному адресу GitHub Pages, но основной домен направлен на VPS.
GitHub Pages считается тёплым резервом контента и холодным резервом домена. При отказе VPS владелец вручную переключает DNS и при необходимости повторно активирует custom domain в настройках GitHub Pages. Допустимы задержка распространения DNS и ожидание выпуска TLS-сертификата; автоматический failover не требуется.
@@ -92,10 +85,10 @@ GitHub Pages считается тёплым резервом контента
| Ошибка сборки ломает опубликованный сайт | Сборка в отдельной версии и атомарное переключение только после успеха |
| Сторонний action выполняет неожиданный код | Workflow состоит из собственных команд и не использует `uses:` |
| Gitea временно недоступна | Уже опубликованный сайт обслуживается независимо от Gitea |
| VPS недоступна или потеряна | Исходники остаются в Gitea; GitHub Pages служит ручным резервом после проверки резервной публикации |
| VPS недоступна или потеряна | Исходники остаются в Gitea; GitHub Pages служит ручным резервом после восстановления GitHub |
| После переключения DNS HTTPS ещё не готов | DNS TTL уменьшается заранее; Certbot запускается сразу после подтверждения публичного HTTP; короткий перерыв принят как допустимый |
| Сертификат GitHub Pages не готов во время аварии | Допускается задержка; на время восстановления используется стандартный адрес GitHub Pages |
| GitHub-резерв отстает от Gitea | Проверяем результат push mirror, совпадение коммитов и резервную сборку; до успешной проверки резерв не считается готовым |
| GitHub-резерв отстаёт от Gitea | После восстановления GitHub настраивается автоматическая синхронизация; до выбора механизма резерв не считается тёплым |
## Проверка реализации
@@ -114,13 +107,8 @@ GitHub Pages считается тёплым резервом контента
Эта спецификация заменяет решения о публикации и custom domain из `project/ADR.md`. Решения того документа о MkDocs Material, структуре файлов и dual-compatible links остаются актуальными.
Документация проекта описывает Gitea Actions и VPS как основной контур
публикации. Ссылки репозитория в `mkdocs.yml` направлены на GitHub для менти;
рабочий origin остается в Gitea.
После реализации нужно обновить `AGENTS.md`, `project/PRD.md` и `project/TODO.md`, чтобы они описывали фактический основной контур публикации. Ссылку на исходный репозиторий в `mkdocs.yml` следует направить на Gitea; ссылку на GitHub можно сохранить как дополнительную после восстановления доступа.
## Синхронизация GitHub
## Открытый вопрос
Способ синхронизации выбран: встроенный Gitea push mirror. Рабочие изменения
вносятся в Gitea, GitHub используется как зеркало для чтения и создания
учебных форков. Нужно отдельно проверить работу зеркал всех стендов и
готовность резервной публикации Pages.
После восстановления GitHub нужно окончательно выбрать способ автоматической синхронизации резервного репозитория. Базовый кандидат — Gitea push mirror с синхронизацией при каждом push; GitHub при этом становится read-only зеркалом, поскольку mirror перезаписывает расходящиеся изменения.
@@ -1,86 +0,0 @@
# Как проходить материалы роадмапа
Статус: черновик для обсуждения. Базовая актуализация опубликована отдельно
в коммите `806417c`. Здесь прорабатываем следующий этап: письменные указания
по порядку занятий, глубине чтения и выполнению заданий.
## Задача
На занятиях ментор регулярно объясняет, какие части внешнего курса нужны
целиком, где достаточно нескольких упражнений и когда переходить к стенду.
Эти указания должны быть доступны рядом с материалами, до начала работы.
Предлагаемый формат: в README оставить общий маршрут. Подробные инструкции
к крупным блокам вынести на отдельные страницы со ссылками из этих разделов.
У каждого шага должны быть понятны материал, глубина изучения, практика
и результат, с которым можно переходить дальше.
## Какие вопросы должна закрыть инструкция
- Какие части внешних курсов Python нужны для дальнейшей практики?
- Насколько подробно изучать устройство PostgreSQL в QPT?
- Какие главы книги прочитать перед конкретными лекциями DEV1?
- Как поддерживать SQL-практику после перехода к следующему блоку?
- Когда запускать каждый стенд и какие задания на нем выполнять?
Объем упражнений связываем с проверяемыми умениями. Индивидуальные сроки
и сокращения программы не превращаем в требования ко всем учащимся.
## Что уже определено
- Docker впервые используем на DEV1: запускаем PostgreSQL, проверяем статус,
подключаемся к базе. Подробный блок Docker остается дальше.
- Data Vault и Anchor Modeling изучаем обзорно.
- venv и JupyterLab осваиваем перед Python для продвинутых.
- Greenplum остается первой курсовой; Kafka, ClickHouse и Clickstream входят
в основную программу. Lakehouse и dbt идут после нее.
- Задания Python и SQL в Airflow уже есть. Для них нужна привязка к чтению
учебника и моменту выполнения.
- Опыты с Kafka записаны отдельной задачей в [TODO](../TODO.md).
## Первый блок для проработки: Python
Собрать инструкцию к существующим курсам и бесплатным материалам.
Начальный вариант границ для проверки:
| Тема | Как проходить | Как проверить результат |
|---|---|---|
| Вложенные списки и матрицы | Выборочные упражнения на механику | Самостоятельно обойти и изменить вложенный список |
| Словари, функции, файлы | Подробно, с практикой | Прочитать данные, преобразовать их и сохранить результат |
| Turtle и Monte Carlo | Можно пропустить в основном маршруте | Отдельная проверка не нужна |
| Память и ссылки, исключения, итераторы и генераторы | Включить и в курс, и в бесплатную альтернативу | Объяснить поведение небольшого примера и самостоятельно изменить его |
Два варианта после advanced Python должны приводить к одному набору умений:
выбранные части Python Professional или последовательность бесплатных
материалов с упражнениями. Особенно проверить покрытие управления памятью
и обработки исключений.
Перед публикацией нужно сверить актуальное оглавление обоих курсов,
подобрать точные разделы и определить достаточную практику. Проценты заданий
из отдельной встречи не заменяют этого отбора. Также нужно уточнить глубину
ООП, pandas и декораторов для дальнейших заданий Airflow.
## Следующие кандидаты
Для DEV1 связать лекции, главы книги и практику на `postgres-bookings`.
Например, чтение о транзакциях поставить перед темой MVCC. На входе пояснить,
где выполняются команды: терминал, `psql`, редактор SQL в DBeaver.
Для QPT описать результат первого прохода и возвращение к теме позже.
Предлагаемый результат: прочитать план, сопоставить оценки с фактическими
строками, сформулировать и проверить гипотезу. Повторная практика должна
использовать уже знакомую базу и конкретный запрос.
Для Airflow сопоставить главы учебника с существующими заданиями.
В каждом переходе обозначить, что сначала разбираем по готовому примеру,
что делаем самостоятельно и как проверяем результат.
На переходах между крупными блоками напомнить о короткой регулярной практике
SQL, а после Python добавить и его поддержание. Объем подбирать по учебной
нагрузке; календарные сроки всей программы пока не фиксировать.
## Как оценить первый результат
На примере Python проверить, может ли читатель определить свой следующий шаг,
объем чтения и практики, способ проверки и условие перехода дальше.
После этого решить, подходит ли такой формат для остальных блоков.