Привет! Меня зовут Андрей Гладилин, я работаю в Swordfish Security над составлением технической документации для ИТ-решений. Завершая  предыдущую статью, мы обсудили преимущества и недостатки DocOps-подхода к разработке технической документации и немного поговорили о прикладной реализации этой парадигмы — Doc-as-code. Позволю себе напомнить, что основная идея DocOps заключается в том, что создание технической документации осуществляется в тесном контакте с разработкой программного продукта и во многом «отзеркаливает» этапы последней — рабочие процессы максимально синхронизируются и объединяются в общую систему, широко применяется автоматизация рутинных операций и упрощается совместная работа, что позволяет повысить общую эффективность процесса. Теперь перейдем к практической реализации DocOps-решения, которое мы начали обсуждать в первой части статьи. Что же, начнем! Перед техническими писателями, помимо прочего, почти всегда стоит задача разработки и публикации эксплуатационной документации для продукта — руководства пользователя, администратора и т. д. Если говорить о форматах публикации, как правило, необходим онлайн справочный портал, а также зачастую документы в формате для печати, например PDF. Кроме этого, предположим, что наши клиенты одновременно пользуются несколькими версиями продукта, — потребуется версионирование документации. Собственно, исходя из перечисленных требований, предлагаю приступить к созданию инструментальной среды разработки технической документации. Очевидно, что реальные требования конкретного проекта могут быть гораздо шире: часто нужны документы в формате docx, иногда оформленные в соответствии с требованиями ГОСТов или конкретных заказчиков, но это определенно выходит за рамки нашей сегодняшней беседы. Текущая задача — «завести» систему, которая будет «закрывать» базовые потребности, в части разработки и публикации эксплуатационной документации, а дальше можно наращивать функционал по мере необходимости. Для решения поставленной задачи предлагаю следующий базовый набор инструментов: Система контроля версий (Version Control System, VCS) для хранения исходных файлов (в нашем случае в формате MarkDown). Сервис выполнения CI/CD-конвейеров (пайплайнов) для автоматизации процессов сборки и публикации. Static Site Generator для конвертации MarkDown‑файлов в статические HTML‑страницы и создания онлайн‑версии документации с поддержкой поиска, версионирования и других базовых функций. Плагины для генерации документации в PDF‑формате. Выбирая что-то  конкретное, стоит помнить, что поставленная задача может быть решена с использованием широкого спектра инструментов, — одних только генераторов статики несколько сотен. Разумно остановить выбор на достаточно популярных решениях, позволяющих в полной мере реализовать необходимый функционал. Предлагаю сфокусироваться на Git и на популярных сервисах для работы с этой системой — GitHub и GitLab. Кроме основных функций системы контроля версий, они предлагают возможность запуска CI/CD-конвейеров, что позволит нам автоматизировать, а значит упростить и ускорить процесс публикации. В части решения аналогичных задач мне приходилось работать с обоими сервисами и я не заметил существенных преимуществ одного над другим — есть некоторые особенности, но они не имеют решающего значения. Логично сделать выбор в пользу того, который используется в вашей компании при разработке программных продуктов. Если говорить о бесплатных тарифах, стоит, пожалуй, упомянуть, что запуск пайплайнов в GitLab возможен только после указания данных платежной карты, с чем могут возникнуть проблемы, однако никто не мешает использовать on-premise установку GitLab Community Edition, где такое ограничение отсутствует. Нежелание/невозможность размещать информацию на сторонних серверах также может стать весомым аргументом в пользу такого решения. Расскажу об использовании обоих сервисов, а выбирать вам. Чтобы ограничить объем статьи, будем исходить из того, что на GitHub документация будет храниться в публичном репозитории, а на GitLab — в приватном. Очевидно, что эти два случая не перекрывают все поле возможных вариантов и никто не может помешать вам при реализации конкретного проекта выбрать любой из двух оставшихся. Повторюсь, выбор подобных инструментов огромен, и очевидно, что широкая распространенность решения является залогом того, что в случае возникновения проблем вы не окажетесь один на один с нерешаемой задачей. Исходя из вышесказанного, предлагаю использовать MkDocs. Его популярность во многом обусловлена современной и активно поддерживаемой разработчиками и комьюнити темой MkDocs Material, которая «из коробки» предлагает неплохой функционал, а при наличии сколько-нибудь умелых рук может быть доведена до отличного состояния. В пользу выбора этого решения говорит также большое количество плагинов, с некоторыми из которых мы познакомимся. Переходя к инструментам для генерации PDF, замечу, что мне удалось попробовать два решения: одно простое и обладающее минимальными настройками, а второе более сложное в части настройки, но открывающее достаточно широкие возможности для кастомизации генерируемых документов. Увы, расплачиваться за эти возможности придется уверенными знаниями HTML/CSS, а также значительными временными затратами. Для комфортной работы пригодится интегрированная среда разработки (Integrated Development Environment, IDE) — рекомендую VS Code. Можно выбрать любую другую или даже просто текстовый редактор, но в случае с VS Code удобно использовать интеграцию с Git, встроенный терминал и большой выбор расширений. Кроме этого, встроенные среды разработки GitHub и GitLab обладают аналогичными интерфейсами и функциями и, привыкнув однажды, не придется переучиваться. Выбор ОС не принципиален — все «заводится» и работает и на Windows, и на Linux, и на MacOS, но в разных системах вы можете столкнуться с различными решаемыми трудностями — об известных мне буду по возможности предупреждать. Самым беспроблемным выбором является Linux, например Ubuntu, — при ее использовании бубен придется доставать реже. Кроме этого, наша цель — переложить сборку и публикацию на плечи CI/CD-конвейера сервиса системы контроля версий, а локально будет происходить лишь работа с исходными MarkDown-файлами, ну и графическими материалами, конечно. Если планируется размещение документации в приватном репозитории, необходимо сгенерировать SSH-ключи (об этом ниже). Кроме этого, на локальной машине должны быть установлены Python и PIP, а также Git. Безусловно, желательны базовые навыки работы со всем перечисленным, однако в известной мере их можно приобрести и в ходе работы.  Создадим репозиторий для документации на выбранном сервисе. Запустим VS Code и откроем встроенный терминал (Ctrl+Shift+`). Выполнив следующие команды, убедимся, что Python и PIP установлены. Если видим, например: Python 3.9.6 и pip 23.1.2 from…, все отлично. Установим MkDocs с темой Material.  Создадим папку для нашего проекта и перейдем в нее.  Создадим новый проект. В проектной директории появятся следующие файлы и папки:  Открыв директорию проекта в VS Code (Cmd+O), добавим в конфигурационный файл mkdocs.yml следующий раздел: Примечание: В конце статьи приведены ссылки на открытый репозиторий GitHub и конфигурационные файлы для GitLab. Это поможет сэкономить время и избежать элементарных ошибок при настройке. Запустим MkDocs локально из терминала VS Code (Ctrl+Shift+`) следующей командой:  Откроем в браузере URL http://127.0.0.1:8000/. На этом локальная установка завершена и можно определиться со структурой будущего справочного портала. Для примера создадим несколько страниц и объединим их в простую структуру. Предположим, что необходимо опубликовать два документа (Руководство по установке и Руководство администратора), каждый с парой статей. Я сознательно утрирую ситуацию, чтобы просто продемонстрировать, как работает механизм. Можно расположить документы в различных директориях или просто в папке docs. Пойдем первым путем, чтобы второй гарантировано не вызвал затруднений. Пути и названия создаваемых файлов указаны в скобках. Руководство по установке (ig/index.md). Создание репозитория. Создание репозитория в GitHub (ig/repo_creation_gh.md). Создание репозитория в GitLab (ig/repo_creation_gl.md). Установка MkDocs (ig/mkdocs_installation.md). Руководство администратора (ag/index.md). Настройки (ag/setup.md). Настройка публикации (ag/pub_setup.md). Примечание: Если локальный сервер MkDocs все еще запущен, его необходимо предварительно остановить — команда (Ctrl+C) в терминале. Создадим директории для документов в папке docs.  В каждой директории создадим файлы в соответствии с обозначенной структурой. Примечание: Для работы с папками и файлами удобно использовать проводник VS Code.  В конфигурационном файле mkdocs.yml создадим раздел nav, который интерпретирует созданную файловую структуру в разделы справочного портала.  Перенесем верхний уровень заголовков в горизонтальное меню и выполним еще пару полезных настроек, добавив в раздел theme секцию features со следующими параметрами:  В каждом файле укажем соответствующий ему заголовок первого уровня. Примечание: В VS Code рекомендую активировать функцию автосохранения (File › AutoSave). Запустим MkDocs-сервер локально, выполнив в терминале (Ctrl+Shift+`) уже знакомую команду mkdocs serve. Открыв в браузере URL http://127.0.0.1:8000/, увидим, что заданная структура соответствующим образом реализована. Примечание: Отметим, что при изменении исходных MarkDown-файлов автоматически изменяется и содержимое нашего портала — это позволяет отслеживать изменения в режиме реального времени, например при редактировании. Однако при изменении конфигурационного файла почти всегда требуется перезапуск сервера уже хорошо известной нам командой mkdocs serve. Выполним еще несколько полезных настроек в файле mkdocs.yml. Изменим название портала.  Изменим логотип и favicon: Создадим директорию docs/assets. Скопируем в нее файлы логотипа и favicon. Добавим в раздел theme следующие параметры: Изменим язык интерфейса, добавив параметр language в раздел theme.  Активируем поиск на русском и английском языках, создав раздел plugins со следующим параметром:  Активируем переключатель режимов просмотра (день/ночь), добавив в раздел theme следующие строки:  Запустим сервер MkDocs локально и посмотрим, как изменился наш портал.  На этом пока остановимся, однако разработчики MkDocs Material предлагают много интересных функциональностей и широкие возможности для кастомизации. Понимая, что требования у всех разные, с легким сердцем отправляю вас на отличный сайт с документацией, где, без сомнения, можно найти много интересного. Мы установили MkDocs Material локально, создали структуру нашего портала и выполнили ряд предварительных настроек. Настало время перенести файлы в репозиторий системы контроля версий и настроить автоматическую сборку и публикацию. Примечание: Прежде чем продолжить, убедитесь, что на вашей машине установлен Git. Примечание: После установки Git вероятно потребуется перезапустить VS Code. GitHub Примечание: В примере будем использовать публичный репозиторий на GitHub. Чтобы не делать настройки самостоятельно, можете просто клонировать его и использовать в качестве шаблона вашего проекта. Примечание: Все команды Git, которые мы выполняем в интерфейсе VS Code, безусловно могут быть выполнены и через CLI. В VS Code перейдите на вкладку Source Control (Ctrl+Shift+G) и нажмите на кнопку Initialize Repository. На вкладке Source Control нажмите … › Remote › Add remote…, а затем выберите Add remote from GitHub. После успешной авторизации в браузере и возвращения в VS Code выберите ранее созданный репозиторий и назначьте ему имя. В поле Message вкладки Source Control введите комментарий, например init, и нажмите на кнопку Commit. Примечание: Если попытка выгрузки коммита закончилась неудачно, выполните в терминале две следующие команды, указав в кавычках свои данные, и опубликуйте коммит вновь. На вкладке Source Control нажмите на появившуюся кнопку Publish Branch. Примечание: В некоторых ОС на этом этапе можно столкнуться с затруднениями, но их легко преодолеть, следуя рекомендациям разработчиков VS Code и GitHub, а также многоуважаемого сетевого комьюнити. Открыв в браузере соответствующий репозиторий, убеждаемся, что файлы успешно загружены. В GitHub переходим на вкладку Actions и нажимаем на кнопку Configure на карточке Simple workflow. Переименуем файл в main.yml, вставим следующие строки и нажмем на кнопку Commit changes…. В открывшемся окне просто нажимаем на кнопку Commit changes. Переходим на вкладку Actions и убеждаемся, что пайплайн отработал без ошибок. Переходим на вкладку Settings. Выбираем пункт меню Pages. Выбираем ветку для публикации (в нашем случае gh-pages). Нажимаем на кнопку Save. Спустя минуту нужно перезагрузить страницу (Cmd+R) и нажать на кнопку Visit site, появившуюся в ее верхней части. Теперь после размещения в репозитории каждого нового коммита будет автоматически запускаться сборка и публикация справочного портала на GitHub Pages. На мой взгляд, описанный подход вполне подойдет для небольших Open Source проектов и не только. GitLab Немного усложним задачу и предположим, что в силу тех или иных причин необходимо разместить документацию в приватном репозитории GitLab и опубликовать ее оттуда. Выполним настройку SSH-ключей: Генерируем пару RSA-ключей в терминале (все параметры по умолчанию).  Копируем публичный ключ в буфер обмена: Ubuntu  MacOS  В GitLab нажмем на иконку профиля в правом верхнем углу и выберем пункт Edit Profile. Слева в меню выберем пункт SSH Keys, вставим публичный ключ из буфера обмена в поле SSH Fingerprints, установим срок действия ключа и нажмем на кнопку Add Key. Перейдем в репозиторий и скопируем его SSH-адрес, нажав кнопку Clone. В VS Code перейдем на вкладку Source Control (Ctrl+Shift+G) и нажмем на кнопку Initialize Repository. В правой части вкладки Source Control нажмем … › Remote > Add remote… и вставим скопированный адрес репозитория. В поле Message вкладки Source Control введем комментарий, например init, и нажмем на кнопку Commit. Примечание: Если попытка выгрузки коммита закончилась неудачно, выполните в терминале две следующие команды, указав в кавычках свои данные, и опубликуйте коммит вновь.  На вкладке Source Control нажмем появившуюся кнопку Publish Branch. Вернемся в GitLab и убедимся, что все файлы успешно выгружены. В меню GitLab выберем CI/CD › Editor и нажмем на кнопку Configure Pipeline. В открывшемся окне заменим все строки следующими и нажмем на кнопку Commit changes внизу.  Спустя пару минут, перейдя на страницу Settings › Pages, можно обнаружить ссылку на наш портал, опубликованный с помощью сервиса GitLab Pages. Примечание: Я исхожу из того, что вы работаете в корпоративном аккаунте GitLab и среда выполнения задач (runner) уже настроена для вашей группы, в противном случае обратитесь к DevOps-специалисту, который выполнит необходимые настройки. Теперь при размещении каждого нового коммита будет происходить автоматическая сборка и публикация справочного портала. Таким образом, задача-минимум по публикации онлайн документов выполнена. При необходимости вы можете настроить домен и сертификат для GitLab Pages и размещать  документацию публично, но разумнее использовать для этого отдельный сервер, а GitLab Pages оставить для ревью и тестирования документации. При необходимости доступ к GitLab Pages может быть ограничен только для членов проекта (Settings › General › Visibility). Предположим, что клиенты используют разные версии вашего продукта и необходимо обеспечить поддержку каждой из них. Примечание: Есть одно ограничение — следует исходить из того, что если мы переходим к работе с новой версией документации, изменения в старую уже не вносим. Технически это возможно, но затруднительно и нетехнологично. Такой подход вполне соответствует реальному положению дел — в предыдущие версии продукта функциональные изменения, как правило, тоже не вносятся. Чтобы отличать одну версию от другой, предлагаю в каждый наш md-файл сразу после заголовка добавить строку «Это первая версия». Примечание: Напоминаю, что сейчас пайплайны настроены таким образом, что портал собирается и публикуется каждый раз после размещения нового коммита.  В VS Code переходим на вкладку Source Control (Ctrl+Shift+G). В поле Message вводим комментарий для коммита (в нашем случае — 1st version). Нажимаем на кнопку Commit (Cmd+Enter). Нажимаем на кнопку Sync Changes. Реализовать версионирование нам поможет утилита Mike. В конфигурационный файл mkdocs.yml добавляем раздел extra со следующими параметрами:  Вносим изменения в пайплайны: GitHub Меняем содержимое файла docops/.github/workflows/main.yml следующим образом и размещаем коммит. Примечание: Здесь, как и ранее, важно указать свое имя и адрес электронной почты в параметрах git config --global user.name = "Your Name" и git config --global user.email = "your@mail", а также каждый раз при изменении версии документации менять ее номер в последней строке. Например, сейчас указано - run: mike deploy --push --update-aliases -b gh-pages 1.0 latest, где 1.0 — это номер версии. Если вы хотите опубликовать документацию версии 2.0, необходимо это значение заменить на 2.0, т. е. строка будет выглядеть следующим образом: - run: mike deploy --push --update-aliases -b gh-pages 2.0 latest. Подчеркну, что это необходимо делать только при изменении версии. Если вы публикуете изменения в рамках одной версии, просто размещайте коммиты и они будут автоматически собираться с текущей версией.  Чтобы открывалась последняя версия документации, на GitHub в корне ветки gh-pages создадим файл index.html со следующим содержимым:  Это можно сделать как в интерфейсе GitHub, так и в VS Code — в любом случае важно не забыть разместить коммит. Теперь при переходе по ссылке на GitHub Pages будет происходить редирект на последнюю версию документации (https://docopshabr.github.io/docopshabr/latest/), а рядом с названием портала появится переключатель версий. Представим ситуацию, когда у нас несколько версий документации, и пользователь приходит на старую по ссылке, например из поисковой системы. Неплохо бы уведомить его об этом и предложить ссылку на актуальную версию. Создадим в корневой директории проекта папку overrides, а в ней файл main.html.  Вставим в main.html следующий блок:  В раздел theme файла mkdocs.yml добавим параметр custom_dir: overrides:  В файле .github/workflows/main.yml изменим номер версии, например на 2.0, см. примечание выше. Примечание: В нашем примере, чтобы отличать версии, в каждый md-файл можно добавить строку «Это вторая версия». Размещаем коммит, ждем пока отработает пайплайн и переходим на GitLab Pages. Примечание: Если после обновления версии что-то работает неправильно, с большой долей вероятности нужно просто очистить кэш браузера. Видим, что открылась новая версия. Переключив версии, можно убедиться, что старая  также сохранилась. Кроме этого, вверху страниц старой версии появилось соответствующее предупреждение. GitLab Примечание: Для реализации версионирования в GitLab выберем несколько другой подход. Номер версии будем не указывать в конфигурационном файле, а передавать с помощью механизма тегирования. Кроме этого, сам пайплайн выстроим немного по-другому. Заменяем содержимое файла .gitlab-ci.yml:  Для запуска пайплайна создаем токен (Settings › Access Tokens) с указанными на рисунке правами. Скопировав созданный токен в буфер обмена, переходим на страницу Settings › CI/CD › Variables и добавляем переменную CICDTOKEN со значением сгенерированного токена, установим флаги, как на рисунке. Создадим в корневой директории проекта папку overrides, а в ней файл main.html: Вставим в main.html следующий блок:  В раздел theme файла mkdocs.yml добавим параметр custom_dir: overrides:  Опубликуем коммит и, перейдя на страницу Repository › Tags, создадим новый тег, имя которого соответствует публикуемой версии, например — 1.0. Примечание: За работой пайплайна можно проследить на странице CI/CD › Pipelines. Чтобы убедиться, что настроенный механизм работает нормально, добавим в каждый md-файл строки «Это вторая версия» и, разместив коммит, создадим тег 2.0, чтобы опубликовать вторую версию документа. Итак, онлайн документация опубликована, самое время подумать о PDF. Расскажу о двух плагинах. Один попроще, но с ограниченными возможностями кастомизации генерируемого документа, второй, напротив, предлагает достаточно широкие возможности настройки, но требует уверенных знаний HTML/CSS и ощутимых временных затрат. Коль скоро речь зашла о плагинах для MkDocs, хочется отметить, что их написано множество. Возможно, вы найдете что-нибудь интересное для себя. Традиционно предлагаю рассмотреть два варианта реализации на разных сервисах: более простой вариант в GitHub, а посложнее — в GitLab. Плагин mkdocs-print-site-plugin Устанавливаем плагин локально.  В раздел plugins конфигурационного файла mkdocs.yml добавляем параметр - print-site. Примечание: Разработчики обращают внимание, что параметр - print-site должен быть в списке плагинов последним.  Запускаем MkDocs локально. Открываем в браузере URL http://127.0.0.1:8000/print_page/, нажимаем Ctrl+P и выбираем формат документа Save as PDF. В файл .github/workflows/main.yml добавляем строку - run: pip install mkdocs-print-site-plugin. В файл mkdocs.yml можно добавить ряд настроек для плагина, см. комментарии в коде ниже.  Если отдельный пункт в горизонтальном меню не нужен, можно добавить соответствующую иконку на каждую страницу, просто включив следующий блок в созданный ранее файл overrides/main.html.  В целом, если этот плагин показался вам интересным и его функциональности достаточно для решения ваших задач, можете посмотреть документацию данного проекта, там есть  исчерпывающая информация. Вот такое простое и вместе с тем достаточно эффективное решение. Надеюсь, что оно найдет своих приверженцев. Если по тем или иным причинам предложенной функциональности недостаточно, можно использовать другой плагин, обладающий более широкими возможностями кастомизации публикуемого документа. Плагин mkdocs-with-pdf Рассмотрим второй более сложный, но вместе с тем более функциональный вариант. Сразу предложу ознакомиться с примером —  документацией для MkDocs Material, подготовленной с помощью этого решения. Очевидно, что уровень  здесь совершенно другой. Если необходимы более широкие возможности кастомизации, этот вариант явно предпочтительнее. В раздел plugins файла mkdocs.yml добавляем параметр - with-pdf:  В раздел before_script файла .gitlab-ci.yml в строку - apt -y install python3-pip добавляем установку еще нескольких компонентов: Размещаем коммит и добавляем/заменяем тег, чтобы опубликовать документацию. В браузере откроем наш портал и добавим к адресу /pdf/document.pdf, чтобы получилось: https://yourgroup.pages.yourdomain.com/docs/docopshabr/2.1/pdf/document.pdf.  У этого плагина гораздо больше настроек, см. комментарии ниже: Примечание: Для генерации QR-кода на задней обложке необходимо установить специальный плагин - pip install qrcode, а также добавить соответствующую строку (- pip install qrcode) в раздел before_script файла .gitlab-ci.yml.  Опубликуем изменения и, добавив Doc.pdf в адресной строке, посмотрим, как теперь выглядит наш документ: https://yourgroup.pages.yourdomain.ru/docs/docopshabr/2.1/Doc.pdf Настройка внешнего вида документа Первое, что бросается в глаза при просмотре сгенерированного PDF, — это несоответствие шрифтов. Это проблема, особенно если в компании есть брендбуки и стайлгайды, регламентирующие использование элементов оформления. Решить ее локально достаточно просто — установить необходимые гарнитуры на машину, на которой генерируется PDF, и прописать их в templates/styles.scss, о котором мы подробнее поговорим позже. Но поскольку мы стремимся к полной автоматизации публикации, необходимо указать шрифты в пайплайне GitLab, чтобы при каждом тегировании собиралась и онлайн-версия документации, и генерировался новый PDF-документ с нужным оформлением. Предположим, что для заголовков и основного текста мы хотим использовать гарнитуру Roboto, а для блоков кода — JetBrains Mono (выбор абсолютно случаен — нам просто нужен пример). В рамках решения этой задачи мы также коснемся оформления других элементов генерируемого PDF, что позволит получить общее впечатление о механизме, который в дальнейшем каждый сможет использовать в своих целях. Вспомним, что среди параметров плагина есть debug_html: true. Если это не так, раскомментируем его. Запустим сборку документации локально, выполнив команду mkdocs build. Объем информации, отображаемой в терминале, увеличится: дело в том, что в него выводится файл html со всеми страницами, подготовленными для генерации PDF. Так работать неудобно, поэтому добавим к команде имя файла, в который будет сохраняться html — mkdocs build > pdf_print.html. После ее выполнения  в корне проекта появится подготовленный для генерации файл pdf_print.html. Примечание: В некоторых ОС при попытке запустить локальную сборку с помощью команды mkdocs build могут возникать ошибки, связанные с отсутствием отдельных библиотек. Пожалуйста, следуйте инструкциям по установке, а также по поиску и устранению неисправностей, на сайте разработчика WeasyPrint (именно он используется для конвертации HTML в PDF). Открыв pdf_print.html в VS Code, заметим, что он включает интегрированные CSS и непосредственно html-разметку будущего документа. Нас, очевидно, больше интересует первая часть, поскольку, меняя стили отдельных элементов, мы сможем изменить общий вид генерируемого PDF. Примечание: К большому сожалению, говорить о полной совместимости форматов не приходится, но многие стили WeasyPrint интерпретирует достаточно точно и при определенных трудозатратах можно добиться достойного результата. Остается вопрос, каким образом мы можем менять стили. Все достаточно просто — необходимо в корне проекта создать файл templates/styles.scss и, прописывая стили в нем, мы будем переопределять их в промежуточном файле pdf_print.html, из которого, в свою очередь, и будет сгенерирован PDF-документ. Чтобы проиллюстрировать сказанное, попробуем изменить формат листа генерируемого документа. Предположим, что вместо дефолтного А4 с книжной (портретной) ориентацией и полями 25-10-25-10 мм нам нужен формат А5 с альбомной ориентацией и полями 10 мм со всех сторон. Добавим в файл templates/styles.scss следующие строки: Действуя аналогичным образом, можно переопределить все используемые в PDF-документе элементы, но я столкнулся с парой особенностей. Если после изменения стиля вы не наблюдаете соответствующих изменений в сгенерированном PDF-документе, не стоит избегать использования модификатора !important для того или иного свойства — зачастую это помогает. Мне также приходилось сталкиваться с тем, что переносы страниц находились не в тех местах, в которых хотелось бы. Здесь следует использовать конструкции такого вида: Если необходимо принудительно поставить перенос в определенном месте, находим этот фрагмент в соответствующем md-файле  и просто вставляем html-тег: В общем случае этого приема следует избегать, но иногда без него не обойтись.  Если возьметесь за настройку дизайна генерируемого документа, перед вами длинный путь «увлекательных» экспериментов, но ситуация не безнадежна — вас ждет приличный результат. Вернемся к проблеме со шрифтами. Чтобы добиться предсказуемости в отношении их использования, необходимо «скормить» их runner-у. Скачаем архивы с нужными гарнитурами, например с Google Fonts, и разархивируем их в созданную в корне нашего проекта папку fonts. В раздел before_script файла .gitlab-ci.yml добавим следующие строки: Примечание: Не забудьте заменить фрагмент your/repository/path на адрес реального репозитория. И, безусловно, необходимо прописать стили для соответствующих элементов в файле templates/styles.scss, например, так: Публикуем обновления и убеждаемся, что документ сгенерирован с использованием нужных шрифтов. Очевидно, что это лишь небольшая часть пути, который придется пройти для определения стилей всего PDF-документа, но, познакомившись с принципом работы, остальное уже вопрос времени. Примечание: Важно заметить, что при генерации PDF соответствующие шрифты внедряются в документ, и это гарантирует его неизменный вид на различных ОС. Пришло время поговорить об организации рабочего процесса в целом и о стратегии ветвления в частности. Обычно в ходе спринта проектная команда реализует несколько функциональностей, и задача технического писателя — отразить эту информацию в пользовательской документации. В рамках организации совместной работы развернутая нами система документирования может предложить интересную функциональность. Выполним еще пару настроек, чтобы познакомиться с ней. Добавим в файл mkdocs.yml следующие строки: GitHub GitLab Примечание: Не забудьте в параметре repo_url указать адрес реального репозитория. В раздел theme: features этого же файла добавим параметр content.action.edit: В результате описанных действий на каждой странице появится иконка, при нажатии на которую будет происходить переход к редактированию соответствующего md-файла в  удаленном репозитории. Примечание: GitLab сразу открывает файлы для редактирования во встроенной веб-IDE. Чтобы добиться этого же в GitHub, необходимо несколько изменить параметры repo_url и edit_uri, в противном случае файлы придется редактировать файлы просто в интерфейсе GitHub. Пользоваться настроенной функциональностью достаточно просто: Открываем страницу, на которой хотим внести правку. Нажимаем на иконку редактирования (см. выше). Авторизуемся в GitHub. Вносим изменения непосредственно в веб-IDE, которая, имеет уже привычный нам интерфейс и функционал VS Code. Переходим на вкладку Source Control (Ctrl+Shift+G). Комментируем и размещаем коммит. Даем название создаваемой ветке и соглашаемся с предложением создать Fork. Переходим на вкладку GitHub и нажимаем на иконку Create Pull Request. При необходимости изменяем параметры PR и нажимаем на кнопку Create. В открывшемся окне оставляем комментарий и нажимаем кнопку Comment справа внизу — Pull Request (PR) создан. Далее владелец репозитория или другой пользователь, наделенный соответствующими правами, сможет просмотреть предлагаемый PR, при необходимости обсудить и изменить его, а затем принять и впоследствии опубликовать. Кто может использовать этот механизм? Любой, кто хочет принять участие в разработке и улучшении документации, — а это и сотрудники компании (SME, QA, CS и т. д.), и, если модель распространения вашего продукта это допускает, обычные пользователи. Можно, например, включать описанную функциональность только на тестовой версии документации на этапе разработки, ревью и тестирования  и отключать перед окончательной публикацией. В непубличном репозитории можно ограничить доступ к тестовой версии только для участников рабочей группы (в GitLab, например, есть все необходимые для этого инструменты). Теперь, имея общее представление о работе механизма, можно адаптировать его к конкретным особенностям вашей компании/проектной команды: сформировать процессы, распределить роли и определить критерии оценки. Кроме этого, можно использовать весь богатый инструментарий, предлагаемый нам современными сервисами для работы с системами контроля версий. Мы получаем возможность не только организовать совместную работу специалистов, но и успешно пользоваться функциями управления проектом, трекинга задач, сбора обратной связи и т. д., — все это к нашим услугам. Пару слов о стратегиях ветвления. До сих пор мы обходились одной веткой main, в которую последовательно добавляли коммиты (описания функциональностей), — это самый простой и достаточно распространенный gitflow. Теперь представим ситуацию: мы добавили в ветку main описание нескольких функциональностей, разместили соответствующую версию документации на GitLab Pages, завершили ревью/тестирование, и ждем окончания релиза, чтобы все это благополучно опубликовать. Но по тем или иным причинам оказывается, что описание одной описанной функциональности нужно опубликовать незамедлительно, не дожидаясь окончания спринта и/или выпуска релиза. Учитывая, что при этом могут быть затронуты несколько файлов, а также возможны изменения в графических материалах, ситуация  не очень хорошая. Если в вашей практике это будет происходить регулярно, стоит задуматься о более сложной стратегии ветвления: выделять для описания каждой функциональности отдельную ветку и называть ее, скажем, по номеру задачи в трекинг-системе. При этом каждый раз «ветвиться» лучше от ветки main, а собирать тестовую версию документации в отдельной ветке testing. При таком gitflow можно ревьюировать и публиковать описания функциональностей в любой последовательности, независимо друг от друга. Так у нас сохраняется текущая опубликованная версия документации и описание всех функциональностей, из которых мы в любой момент можем собрать релиз, а также мы не будем лишены  возможности при необходимости оперативно публиковать HotFix-ы прямо в ветку main (с последующим дублированием в ветку testing, конечно). Проще представить этот gitflow на диаграмме — одна иллюстрация может стоить тысячи слов. У такого подхода есть свои недостатки: усложненная стратегия — верный путь к мерж-конфликтам, особенно при совместной работе нескольких специалистов. Выбор стратегии ветвления целиком зависит от особенностей ваших рабочих процессов. Со своей стороны скажу, что с некоторыми продуктами удается работать в рамках упрощенной стратегии, а для некоторых требуется более сложная. Целью данной статьи является не всестороннее изучение функциональности используемых инструментов, а, скорее, легкое знакомство с предлагаемой концепцией, которая реализована с их использованием. У читателя появляется возможность оценить, насколько данное решение применимо в его компании, и при положительном решении он сможет использовать созданную в ходе наших рассуждений инструментальную среду в качестве базы при построении собственной системы документирования. Система хорошо масштабируется — в соответствии с возникающими потребностями можно добавлять инструменты, начиная линтерами и спел-чекерами и заканчивая плагинами для публикации документации на нескольких языках. В ходе дальнейшего анализа и, возможно, опытной эксплуатации системы, рекомендую оценить ее с точки зрения следующих аспектов, которые, очевидно, можно отнести к сильным сторонам: повышение технологичности — увеличение скорости разработки и упрощение сопровождения технической документации; повышение эффективности взаимодействия команды; широкие возможности автоматизации — максимальное устранение рутинных операций; упрощение организации и контроля командной работы; глубокая интеграция с процессами продуктовой разработки; эффективное использование ресурсов. Упражнения делались в публичном репозитории GitHub. Конфигурационные файлы для GitLab можете скачать здесь (не забудьте внести изменения для вашего репозитория). Документация MkDocs. Документация MkDocs Material. Плагин mkdocs-print-site-plugin Плагин mkdocs-with-pdf   Технический писатель