Всем привет! В процессе обновления инфраструктуры сопровождения наших программных решений мы получили интересный опыт, которым хотим поделиться. Эта статья не просто пошаговая инструкция, а практический разбор того, как мы выстроили процесс подготовки технической документации на основе MkDocs Material, автоматизировали его через GitLab CI/CD и встроили полученный результат в сайт на Битрикс. Наш опыт окажется полезным тем, кто хочет навести порядок в документации и сделать её частью полноценного dev-процесса.

Предисловие

Наша компания сопровождает несколько интернет‑магазинов на платформе Битрикс, каждый из которых включает собственную линейку программных решений. По всем продуктам необходимо составлять и публиковать актуальную документацию. Ситуация усложнилась после того, как мы перевели наши продукты в OpenSource и выложили их в публичные репозитории GitLab. Теперь документация должна быть актуальна и синхронизирована как на сайте магазина, так и в репозиториях.

Перед нами возникла проблема: как автоматизировать работу с документацией?

Мы начали с определения ключевых требований:

  • Адаптивный веб‑сайт, автоматически генерируемый из текстовых файлов;

  • Версионный и открытый исходный код в репозитории GitLab;

  • Возможность публиковать контент разного формата: от статей о продуктах до постов в блоге и справочных руководств;

  • Развертывание и размещение, желательно бесплатное, с возможностью непрерывного обновления в автоматическом режиме через CI/CD;

  • Динамический контент во время сборки для оперативного изменения дизайна статического сайта;

  • Возможность встраивания цифровых ассистентов с использованием технологий искусственного интеллекта;

  • Перспектива автоматизированного тестирования.

После анализа доступных решений, остановились на MkDocs — генераторе статических сайтов, разработанном специально для документации и использующем разметку Markdown.

Конечно, не обошлось без рассмотрения альтернатив:

  1. Sphinx — это популярный инструмент для создания документации, особенно для проектов на Python. Однако, как и любое другое решение, он имеет свои недостатки. Sphinx использует язык reStructuredText, который является менее интуитивным по сравнению с Markdown. Sphinx не предоставляет встроенных функций для редактирования документации в реальном времени, что затрудняет совместную работу. И он требует больше настроек, что сопровождается большей сложностью в переопределении шаблонов.

  2. Docusaurus — это статический генератор сайтов, предназначенный для упрощения создания, развертывания и ведения документации и веб‑сайтов. Docusaurus показался избыточным для наших задач. Он требует больше усилий для первоначальной настройки, особенно если вы не знакомы с React. Конфигурация может быть более сложной из‑за множества доступных опций.

Еще нам довелось поработать с Gatsby, но на момент его использования этот генератор статических сайтов выдавал слишком упрощенный сайт по сравнению с возможностями MkDocs.

Наша документация на Gatsby
Наша документация на Gatsby

MkDocs показался лучшим вариантом: прост в настройке и использовании, поддерживает адаптивный дизайн и имеет множество тем, интегрируется с GitLab CI/CD для автоматической сборки и публикации документации, а также позволяет расширять функциональность с помощью плагинов. Кроме того, шаблон MkDocs Material предоставляет массу возможностей быстрой организации сайта документации.

Как установить и настроить MkDocs

Следует отметить, что MkDocs написан на Python и в нем используется язык шаблонов Jinja2, который позволяет создавать динамически генерируемые HTML‑страницы с простой и понятной разметкой. В MkDocs шаблоны Jinja2 используются для генерации HTML‑страниц из файлов Markdown. Когда запускается команда mkdocs build, MkDocs обрабатывает Markdown‑файлы, применяет к ним шаблоны Jinja2 и создает статические HTML‑страницы, которые затем можно развернуть на веб‑сервере.

Для тех, кто знаком с Python и менеджерами пакетов, установка MkDocs не представляет сложностей. Вот основные шаги для запуска сервера и генерации статического сайта:

Шаг 1: Подготовка окружения

Для MkDocs требуется последняя версия Python и менеджер пакетов PIP. Убедимся, что у нас есть все необходимое. Откройте командную строку (терминал) и введите:

python --version

Должна отобразиться версия Python. Если команда не работает, потребуется установить Python. Скачайте его с официального сайта. Во время установки не забудьте установить флажок «Add python.exe to PATH» (обычно по умолчанию он не активен). Если у вас установлен Python, убедитесь, что PIP обновлен до последней версии. Для его обновления воспользуйтесь командой:

pip install --upgrade pip

Шаг 2: Установка MkDocs

Для установки MkDocs выполните команду:

pip install mkdocs

После этого проверьте успешность установки с помощью команды:

mkdocs --version

Шаг 3: Создание нового проекта

Для создания нового проекта MkDocs выполните команду:

mkdocs new my-project

где my-project — это имя директории проекта. 

Эта команда создаст следующую структуру файлов:

.
├─ docs/
│  └─ index.md # Домашняя страница по умолчанию
└─ mkdocs.yml # Основные настройки вашего проекта

Перейдите в созданную директорию с помощью команды:

cd my-project

Шаг 4: Запуск локального сервера

MkDocs содержит встроенный сервер разработки. С помощью этого сервера можно просматривать документацию во время работы над ней.

Запустите сервер по команде:

mkdocs serve

Теперь можно открыть http://127.0.0.1:8000 в браузере и увидеть заготовку документации:

Заготовка документации
Заготовка документации

Шаг 5: Минимальная конфигурация

Файл mkdocs.yml содержит основные настройки вашего проекта.

Откройте файл в редакторе:

site_name: Документация

Пока что в файле есть только один параметр site_name, который задает название сайта. Задайте свое название и сохраните файл. После сохранения страница в браузере перезагрузится и отобразится новое название.

Настройка названия сайта
Настройка названия сайта
Пример со структурой нашего конфигурационного файла
site_name: Документация # Отображаемое название сайта (в шапке и title)
site_url: https://trusted.ru/documentation/ # Базовый URL сайта
site_author: digtlab.ru  # Имя автора сайта (добавляется в метатег <meta name="author">)
theme:
  name: material # Используется тема MkDocs Material
  custom_dir: overrides # Кастомные шаблоны/стили в папке `overrides`
  features: # Активированные фичи темы:
    - announce.dismiss  # Закрываемые уведомления
    - content.code.annotate  # Аннотации к коду
    - content.code.copy  # Кнопка копирования кода
    - navigation.tracking  # Отслеживание активного раздела
    - navigation.indexes  # Индексирование навигации
    - navigation.sections  # Группировка разделов
    - search.highlight  # Подсветка результатов поиска
    - search.share  # Кнопка поделиться поиском
    - search.suggest  # Подсказки при поиске
    - toc.follow  # Автопрокрутка оглавления
    - toc.integrate  # Интеграция с навигацией
  font:  # Шрифты
    text: PT sans # Основной шрифт
    code: PT Mono # Моноширинный для кода
  logo: assets/crypto.png # Логотип в шапке
  favicon: assets/crypto.png # Иконка вкладки браузера
  language: ru # Локализация интерфейса
plugins: # Установленные плагины MkDocs
  - search:  # Встроенный поиск
      separator: '[\s\u200b\-_,:!=\[\]()"`/]+|\.(?!\d)|&[lg]t;|(?!\b)(?=[A-Z][a-z])'  # Правила разбиения слов
  - minify:  # Минификация HTML
      minify_html: true  # Включено
hooks: # Хуки
  - overrides/hooks/translations.py
extra: # Дополнительная конфигурация
  generator: false
  status:  # Кастомные статусы для страниц
    new: Recently added
    deprecated: Deprecated
extra_css:
  - stylesheets/extra.css  # Дополнительные CSS-стили
watch:  # Папки для отслеживания изменений при `mkdocs serve`
  - docs
  - overrides
  - mkdocs.yml
markdown_extensions: # Список расширений для парсера Markdown, которые добавляют новые возможности к стандартному синтаксису Markdown
  - abbr  # Сокращения (HTML <abbr>)
  - admonition  # Блоки-уведомления (!!! note)
  - attr_list  # Атрибуты HTML ({: .class })
  - def_list  # Списки определений (<dl>)
  - footnotes  # Сноски ([^1])
  - md_in_html  # Markdown внутри HTML-блоков
  - toc:  # Оглавление
      toc_depth: "1-1"  # Уровни заголовков (только h1)
      permalink: true  # Якорные ссылки
      slugify: !!python/name:pymdownx.slugs.uslugify # Алгоритм генерации якорей для заголовков
  - pymdownx.arithmatex:  # Поддержка LaTeX
      generic: true  # Совместимость с MathJax/Katex
  - pymdownx.betterem:  # Умное выделение (**bold**, _italic_)
      smart_enable: all
  - pymdownx.caret # Вставка символов (^sup^)
  - pymdownx.details  # Сворачиваемые блоки (<details>)
  - pymdownx.emoji:  # Эмодзи
      emoji_generator: !!python/name:material.extensions.emoji.to_svg  # SVG-генератор
      emoji_index: !!python/name:material.extensions.emoji.twemoji  # Библиотека Twemoji
  - pymdownx.highlight:  # Подсветка кода
      anchor_linenums: true  # Якоря для строк
      line_spans: __span  # CSS-классы для строк
      pygments_lang_class: true  # Классы языков
  - pymdownx.inlinehilite  # Подсветка в строке (`code`)
  - pymdownx.keys  # Клавиши (++ctrl+alt+del++)
  - pymdownx.mark  #==Выделение текста==
  - pymdownx.smartsymbols  # Поддержка (c) → ©, (tm) → ™
  - pymdownx.snippets:  # Вставка указанных файлов в конец каждой страницы
      auto_append:
        - includes/mkdocs.md  # Путь относительно папки `docs/`
  - pymdownx.superfences:  # Расширенные блоки кода
      custom_fences:
        - name: mermaid  # Диаграммы Mermaid
          class: mermaid
          format: !!python/name:pymdownx.superfences.fence_code_format
  - pymdownx.tabbed:  # Вкладки
      alternate_style: true  # Альтернативный стиль
      combine_header_slug: true  # Генерация slug для заголовков
      slugify: !!python/object/apply:pymdownx.slugs.slugify
        kwds:
          case: lower
  - pymdownx.tasklist:  # Чекбоксы
      custom_checkbox: true  # Кастомные CSS-классы
  - pymdownx.tilde  # ~~Зачеркивание~~
nav: # Структура сайта
…

Подробнее про конфигурацию файла mkdocs.yml читайте на сайте разработчика.

Шаг 6: Добавление контента

Содержимое документации размещается в директории docs/.

По умолчанию папка docs/ содержит один файл с домашней страницей index.md. Добавьте свои файлы в формате markdown (.md) в эту директорию.

.
├─ docs/
│  └─ index.md
│  └─instructions.md
│  └─setup.md
└─ mkdocs.yml

Откройте браузер и убедитесь, что добавленные файлы отобразились на сайте.

Добавление контента
Добавление контента

По умолчанию MkDocs автоматически формирует структуру сайта из всех файлов каталога docs в алфавитном порядке. Порядок сортировки можно настроить в mkdocs.yml с помощью параметра nav:

site_name: Документация
nav:
  - index.md
  - setup.md
  - instructions.md

Теперь на сайте изменилась очередность страниц:

Настройка навигации
Настройка навигации

Стоит отметить, что MkDocs поддерживает переопределение заголовков, а также многоуровневую навигацию.

Например:

site_name: Документация
nav:
  - Главная: index.md
  - Установка и настройка:
    - Установка: setup/setup.md
    - Настройка: setup/settings.md
  - Инструкции: instructions.md

Как это выглядит на сайте:

Настройка навигации
Настройка навигации

Шаг 7: Построение статического сайта

Когда вы будете готовы к публикации, постройте статический сайт, выполнив команду:

mkdocs build

Результат сохранится в папке site. Эти файлы можно разместить на любом веб-сервере.

Шаблон MkDocs Material и его особенности

MkDocs включает несколько встроенных тем mkdocs и readthedocs, помимо которых существуют сторонние темы, разработанные независимыми командами. Вот полный список тем, которые можно установить с помощью pip.

Пожалуй, самым известной и популярной является тема MkDocs Material, именно ее мы и взяли за основу своего портала документации.

Официальный сайт MkDocs Material
Официальный сайт MkDocs Material

Тема включает адаптивный дизайн, множество функций, таких как навигация по страницам, встроенные поисковые функции и возможность добавления пользовательских элементов. Полный список плагинов и расширений темы, которые мы используем, приведен в примере со структурой нашего конфигурационного файла.

Для установки темы MkDocs Material выполните команду:

pip install mkdocs-material

Чтобы применить тему, добавьте в конфигурационный файл mkdocs.yml:

theme: material
Тема MkDocs Material

Инфраструктура создания и размещения документации (GitLab→MkDocs→Битрикс)

Процесс подготовки и публикации документации выстроен как единая цепочка и охватывает все этапы: от создания текста до его размещения на сайте Битрикс.

Как выглядит схема процесса:

Cхема создания и размещения документации
Cхема создания и размещения документации

Для каждого продукта мы разрабатываем документацию в формате Markdown, а затем размещаем ее в ветке docs/ репозитория продукта. После прохождения всех проверок и согласований, изменения вливаются в основную ветку, откуда и начинается процесс автоматической сборки.

Примеры документации:

После публикации изменений в GitLab запускается процесс переноса документации в репозиторий с предварительно настроенной платформой MkDocs Material. Под «преднастройкой» понимается то, что платформа уже нацелена на генерацию статического сайта под определенный информационный ресурс, там имеются все необходимые доработки по стартовым страницам и стилям. Остается только разместить документацию в каталог docs/ и обновить структуру навигации в файле mkdocs.yml. На выходе получается единый статический сайт со всей документацией, готовой к публикации.

Собранные HTML-страницы проходят обработку, при которой автоматически оборачиваются в PHP-шаблоны с хедерами и футерами сайта Битрикс. После преобразования готовые файлы публикуются на тестовом (dev) или рабочем (prod) сервере в зависимости от ветки GitLab. Подробнее о механизме преобразования и настройке шаблонов расскажем ниже.

Проблемы и решения

1. Кастомизация шаблона MkDocs Material

Создавая собственный сайт, вы неизбежно столкнетесь с необходимостью кастомизации MkDocs Material. Например, вы захотите разместить собственное меню в шапке или сделать футер более информативным. Такая возможность есть и это не так сложно, как может показаться. Давайте разберемся, как это сделать на примере изменения шаблонов header и main.

На портале с документацией нам требовалось перенести строку поиска из заголовка страницы в левую часть над меню с навигацией. Поскольку в правом верхнем углу уже находился стандартный поиск сайта от Битрикс, который мы решили оставить.

Кастомизация шаблона MkDocs Material
Кастомизация шаблона MkDocs Material

Для этого в структуре каталогов шаблона MkDocs Material мы создали каталог overrides. В этом каталоге разместили скрипт main.html и подкаталог partials со скриптом header.html.

.
├── docs/                       # Основная директория с документацией
├── overrides/                  # Кастомные шаблоны и стили
│   ├── partials/               # Переопределенные части шаблонов
│   │   └── header.html         # Кастомный header
│   └── main.html               # Основной шаблон
...

Как написать код для скриптов?

Все очень просто. Мы скачали cкрипты из репозитория c исходными кодами темы, а затем внесли правки.

Вот изменения в файле header.html
{% set class = "md-header" %}
{% if "navigation.tabs.sticky" in features %}
  {% set class = class ~ " md-header--shadow md-header--lifted" %}
{% elif "navigation.tabs" not in features %}
  {% set class = class ~ " md-header--shadow" %}
{% endif %}
<header class="{{ class }}" data-md-component="header">
  <nav class="md-header__inner md-grid" aria-label="{{ lang.t("header") }}">
    <a href="{{ config.extra.homepage | d(nav.homepage.url, true) | url }}"
       title="{{ config.site_name | e }}"
       class="md-header__button md-logo"
       aria-label="{{ config.site_name }}"
       data-md-component="logo">{% include "partials/logo.html" %}</a>
    <label class="md-header__button md-icon" for="__drawer">
      {% set icon = config.theme.icon.menu or "material/menu" %}
      {% include ".icons/" ~ icon ~ ".svg" %}
    </label>
    <div class="md-header__title" data-md-component="header-title">
      <div class="md-header__ellipsis">
        <div class="md-header__topic">
          <span class="md-ellipsis">{{ config.site_name }}</span>
        </div>
        <div class="md-header__topic" data-md-component="header-topic">
          <span class="md-ellipsis">
            {% if page.meta and page.meta.title %}
              {{ page.meta.title }}
            {% else %}
              {{ page.title }}
            {% endif %}
          </span>
        </div>
      </div>
    </div>
    {% if config.theme.palette %}
      {% if not config.theme.palette is mapping %}
        {% include "partials/palette.html" %}
      {% endif %}
    {% endif %}
    {% if not config.theme.palette is mapping %}
      {% include "partials/javascripts/palette.html" %}
    {% endif %}
    {% if config.extra.alternate %}
      {% include "partials/alternate.html" %}
    {% endif %}
    {% if "material/search" in config.plugins %}
      {% include "partials/search.html" %}
      <label class="md-header__button md-icon" for="__search">
        {% set icon = config.theme.icon.search or "material/magnify" %}
        {% include ".icons/" ~ icon ~ ".svg" %}
      </label>
    {% endif %}
    {% if config.repo_url %}
      <div class="md-header__source">{% include "partials/source.html" %}</div>
    {% endif %}
  </nav>
  {% if "navigation.tabs.sticky" in features %}
    {% if "navigation.tabs" in features %}
      {% include "partials/tabs.html" %}
    {% endif %}
  {% endif %}
</header>

Мы убрали блок, который отвечает за отображение элемента поиска, оставив его для мобильной верстки.

Вот изменения в файле main.html
{% extends "base.html" %}

{% block hero %}
<div class="title_container">
  <h1 class="title_main">Документация</h1>
</div>
{% endblock %}

{% block site_nav %}
<!--{% if not (page.meta and page.meta.hide) %}-->
  <div>
      {% if "material/search" in config.plugins %}
        <header class="md-search-nav" data-md-component="header">
          <!-- <div class="md-flex__cell md-flex__cell--shrink"> -->
          <label class="md-header__button md-icon" for="__search">
            {% set icon = config.theme.icon.search or "material/magnify" %}
            {% include ".icons/" ~ icon ~ ".svg" %}
          </label>
          {% include "partials/search.html" %}
          <!-- </div> -->
        </header>
      {% endif %}
    {{ super() }}
  </div>
<!--{% endif %}  -->
{% endblock %}

{% block container %}
{% if page.url == '' %}
  {{ super() | replace('<div class="md-content" data-md-component="content">', '<div class="md-content is_home" data-md-component="content">') | safe }}
{% else %}
    {{ super() }}
{% endif %}

{% endblock %}
{% block content %}
  {{ super() }}
  <div class="md-breadcrumbs-buttons" role="navigation" aria-label="navigation">
    {%- if page.previous_page and page.next_page %}
      <div class="text nav_button">
        <a href="{{ page.previous_page.url|url }}" class="float-left" title="{{ page.previous_page.title }}">Предыдущая</a>
      </div>
      <div class="text nav_button">
        <a href="{{ page.next_page.url|url }}" class="float-right" title="{{ page.next_page.title }}">Следующая</a>
      </div>
    {%- endif %}
    {%- if page.previous_page and not page.next_page %}
      <div class="text nav_button">
        <a href="{{ page.previous_page.url|url }}" class="float-left" title="{{ page.previous_page.title }}">Предыдущая</a>
      </div>
      <div></div>
    {%- endif %}
    {%- if not page.previous_page and page.next_page %}
      <div></div>
      <div class="text nav_button">
        <a href="{{ page.next_page.url|url }}" class="float-right" title="{{ page.next_page.title }}">Следующая</a>
      </div>
    {%- endif %}
  </div>
{% endblock %}
{% block footer %}{# Отключаем footer #}{% endblock %}

Также мы внесли изменения в реализацию кнопок перемещения по содержанию сайта и отключили footer.

2. Несовместимые якоря страниц в GitLab и MkDocs

При работе с документаций в формате Markdown заголовкам автоматически назначаются якорные ссылки. Ссылки упрощают навигацию внутри документа и позволяют создавать перекрестные ссылки между разными документами .

Оказалось, что GitLab и MkDocs используют разные алгоритмы генерации якорных ссылок, что приводит к поломке ссылок при переходе между системами.

В чем различия? 

GitLab приводит заголовок к нижнему регистру, убирает все не буквенно-цифровые символы, заменяет пробелы на дефисы.

Пример:

## Настройка SSL-сертификата  → "настройка-ssl-сертификата"

MkDocs удаляет кириллицу, оставляет только латинские буквы, цифры и дефисы.

Для предыдущего примера MkDocs создаст следующий заголовок:

## Настройка SSL-сертификата  → "#ssl-"

Решение: Для приведения якорей к одному виду мы добавили в файл mkdocs.yml расширение toc с правилом slugify:

markdown_extensions:
  - toc:
      slugify: !!python/name:pymdownx.slugs.uslugify

Интеграция документации в интернет-магазин на Битрикс

Рассмотрим, как интегрировать статический сайт с документацией на MkDocs Material, в интернет-магазин на платформе 1С-Битрикс. В качестве примера используем портал https://trusted.ru/documentation/.

Пример главной страницы статического сайта, созданной по шаблону MkDocs Material:

Портал https://trusted.ru/documentation/

Мы уже рассмотрели проект документации на базе  MkDocs Material. Теперь разберемся с его структурой и настройками CI/CD для автоматической сборки и доставки документации в окружение Битрикс.

В GitLab проект организован следующим образом:

.
├── docs/                   # Основная директория с документацией
├── overrides/              # Кастомные шаблоны и стили
├── extra/
│   ├── template.php        # Шаблон для интеграции с Битрикс
│   └── html-to-php.sh      # Скрипт конвертации
...

В папке docs/ размещаются исходные файлы документации в формате Markdown со стилями MkDocs Material. Именно эти файлы используются для сборки статического сайта.

Папка extra/ содержит скрипт html‑to‑php.sh и шаблон template.php, необходимые для интеграции с Битрикс.

Шаблон template.php обеспечивает обертку вокруг каждой HTML‑страницы, добавляя шапку и подвал сайта.

Пример кода template.php
require($_SERVER['DOCUMENT_ROOT'] . '/bitrix/header.php');
$APPLICATION->SetPageProperty("description", "Официальный сайт ООО «Цифровые технологии»");
$APPLICATION->SetPageProperty("title", "Сайт ООО «Цифровые технологии»");
$APPLICATION->SetTitle("Главная"); 
?>
<style>
  label.md-nav__link::before, label.md-nav__link::after {
    display: none!important;
  }
  .content {
    min-height: initial!important;
  }
</style>
<script>
  function resizeHeader() {
    const r = document.querySelector(':root');
    const h1 = $('#header_shop')?.height() || 0;
    const h2 = $('.md-overlay')?.height() || 0;
    const marginTop = Math.abs(h1 - h2 - 3);
    const additionalMarging = 17; //// ????? нужно для sidebar
    r.style.setProperty('--cryptoarm-marging-top', `${marginTop}px`);
    r.style.setProperty('--cryptoarm-marging-top-sidebar', `${marginTop + additionalMarging}px`);
  }
</script>
<div>
  <?php include ('REPLACEME'); ?>
</div>
<script>  
  // resizeHeader();
  $(window).on( "resize", resizeHeader);
</script>
<?require($_SERVER["DOCUMENT_ROOT"]."/bitrix/footer.php");?>

Скрипт html‑to‑php.sh содержит алгоритм обработки страниц документации, после их преобразования в html. Скрипт создает PHP файлы на основе шаблона из template.php, заменяя в нем строку REPLACEME на имена соответствующих HTML файлов. Каждый новый PHP файл сохраняется в ту же директорию, что и оригинальный HTML файл.

Пример кода html-to-php.sh
#!/bin/bash
template=$(cat template.php)
if [[ -z $template ]]
then
    echo 'template is empty' >&2
    exit 1
fi
find ./../docs -type f -name "*.html" | while read fname; 
do 
    dir=$(dirname -- "$fname")
    filename=$(basename -- "$fname")
    filename_noext="${filename%.*}"
    echo "${template/REPLACEME/$filename}" > "$dir/$filename_noext.php"
done

В результате этой обработки каждая сгенерированная статическая страница дополняется хедером и футером сайта Битрикс и все файлы хранятся в формате PHP с сохранением структуры статического сайта.

В каталоге overrides в проекте, использующем MkDocs Material, размещаются пользовательские файлы и настройки, которые позволяют изменять и настраивать внешний вид и поведение документации. Этот каталог используется для переопределения стандартных стилей, шаблонов и других ресурсов, предоставляемых темой Material для MkDocs. В файле mkdocs.yml конфигурируются основные настройки проекта MkDocs, включая параметры для темы, навигации, расширений и других аспектов.

Процесс сборки документации организован с помощью двухэтапного Dockerfile. На первом этапе мы собираем сайт из исходников, на втором — упаковываем в образ с минималистичным nginx‑сервером.

Пример кода dockerfie
FROM registry.example.ru/mkdocs/mkdocs-material-data:9 as build

ARG CI_COMMIT_BRANCH
ARG CI_JOB_TOKEN
ARG CI_SERVER_HOST
ARG CI_PROJECT_NAMESPACE
ARG CI_PROJECT_NAME

ENV DOCS_PATH /docs
RUN git clone -b ${CI_COMMIT_BRANCH} --single-branch --depth 1 \  https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_NAMESPACE}/${CI_PROJECT_NAME}.git \
    ${DOCS_PATH}
RUN mkdocs build -f ${DOCS_PATH}/mkdocs.yml -d ${DOCS_PATH}/site
FROM flashspys/nginx-static
COPY --from=build /docs/site /static
EXPOSE 80
STOPSIGNAL SIGTERM
CMD ["nginx", "-g", "daemon off;"]

Конвейер CI/CD состоит из трёх стадий:

  1. build  — собирает и сохраняет сайт;

  2. convert — преобразует HTML в PHP с помощью html-to-php.sh;

  3. deploy— выкладывает результат на dev или prod-сервер в зависимости от ветки.

Пример кода gitlab-ci.yml
stages:
  - build
  - convert
  - deploy

workflow:
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
      when: never
    - when: always

docs_build:
  stage: build
  tags:
    - mkdocs
  before_script:
    - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
    - export BUILD_VERSION=${CI_COMMIT_BRANCH}-$(date +%Y-%m-%d-%H%M)
    - export LATEST_VERSION=${CI_COMMIT_BRANCH}-latest
    - export DOCS_DIR=$CI_PROJECT_DIR/docs
  script:
    - echo "Building and pushing BUILD_VERSION version for $CI_COMMIT_BRANCH branch"
    - if [ -d "$DOCS_DIR" ]; then rm -Rf $DOCS_DIR; fi
    - >
      docker build 
      --pull 
      --no-cache 
      --tag $CI_REGISTRY_IMAGE:$BUILD_VERSION 
      --build-arg CI_COMMIT_BRANCH=$CI_COMMIT_BRANCH 
      --build-arg CI_JOB_TOKEN=$CI_JOB_TOKEN 
      --build-arg CI_SERVER_HOST=$CI_SERVER_HOST 
      --build-arg CI_PROJECT_NAMESPACE=$CI_PROJECT_NAMESPACE 
      --build-arg CI_PROJECT_NAME=$CI_PROJECT_NAME 
      .
    - docker create --name $BUILD_VERSION $CI_REGISTRY_IMAGE:$BUILD_VERSION
    - docker cp $BUILD_VERSION:/static $DOCS_DIR
    - docker rm -f $BUILD_VERSION
    - docker tag $CI_REGISTRY_IMAGE:$BUILD_VERSION $CI_REGISTRY_IMAGE:$LATEST_VERSION
    - docker push $CI_REGISTRY_IMAGE:$BUILD_VERSION;
    - docker push $CI_REGISTRY_IMAGE:$LATEST_VERSION;
    - docker rmi $CI_REGISTRY_IMAGE:$BUILD_VERSION
    - docker rmi $CI_REGISTRY_IMAGE:$LATEST_VERSION
  artifacts:
    name: docs
    paths:
      - ./docs
    expire_in: never

convert_html_to_php:
  stage: convert
  tags:
    - mkdocs
  needs: ["docs_build"]
  script:
    - cd ./extra && bash html-to-php.sh
  artifacts:
    name: docs-php
    paths:
      - ./docs
    expire_in: never

docs_deploy_dev:
  stage: deploy
  variables:
    GIT_STRATEGY: none
  tags:
    - mkdocs
  needs: ["convert_html_to_php"]
  rules:
    - if: $CI_COMMIT_BRANCH == 'dev'
  script:
    - echo "Deploying dev version"
    - rm -rf /var/www/dev_trusted/documentation/*
    - cp -r ./docs/* /var/www/dev_trusted/documentation

docs_deploy_prod:
  stage: deploy
  variables:
    GIT_STRATEGY: none
  tags:
    - mkdocs
  needs: ["convert_html_to_php"]
  rules:
    - if: $CI_COMMIT_BRANCH == 'main'
  script:
    - echo "Deploying prod version"

Послесловие

Мы интегрировали MkDocs Material и автоматизировали публикацию в Битрикс, создав единую систему документации. Это принесло положительные результаты:

  • Оперативность обновлений: правки доходят до пользователей за считанные минуты.  

  • Снижение нагрузки: нет необходимости дублировать контент для GitLab и Битрикс — всё синхронизируется автоматически.  

  • Гибкость: Markdown дает свободу форматирования, а тема Material обеспечивает современный адаптивный дизайн.  

Эта система — не финальное решение, а гибкая основа, которая будет развиваться вместе с нашими продуктами. Сейчас мы активно работаем над улучшениями. Вводим версионность документации и добавляем выбор продукта. Если у вас есть опыт подобных внедрений, мы будем рады обсудить в комментариях!

Спасибо, что прочитали до конца.

Комментарии (0)