Привет, Хабр! Меня зовут Артём Зеленкин, приятно познакомиться! Я работаю техническим писателем около 20 лет, сейчас занимаюсь документированием в подразделении ARMA компании Infowatch. Для создания и поддержки актуальности документации по продуктам линейки ARMA мы используем docs-as-code. Что из этого получается, можно посмотреть на сайте с документацией (там же можно скачать pdf-версию, чтобы сравнить, как оно выглядит в разных форматах при тех же исходных данных).
В данной статье я не пытаюсь рассказать, что такое docs-as-code (думаю, статей по теме достаточно), а рассказываю, как этот принцип реализован у нас. Может, вам тоже пригодится.
Чтобы сэкономить ваше время, сначала потрачу его, добавив ниже краткое описание параграфов. Всё-таки это не научная статья, поэтому не обязательно читать целиком.
«История» — лично-историческая часть, которую можно было не писать, но с неё всё началось. Полезно для понимания контекста.
«Процессы» — подход к документированию в команде и что можно найти общего в работе техписа по docs-as-code с работой программиста
«Технические моменты» — немного наблюдений по процессу установки и настройки Sphinx, структуре проекта и работе с reStructuredText, а ещё тут я разбираю небольшой пример. Выполнив эти несколько простых шагов, вы сможете добавить в резюме «Опыт работы с docs-as-code». Наверное
«На прощание» — небольшое заключение
История
Начну с начала. С начала 2025 года, когда мне повезло приступить к работе в техническом департаменте ARMA компании Infowatch. Кроме обязательных задач по документированию, мне регулярно напоминали, что у меня есть замечательная возможность написать статью на Хабр. Компания поощряет хабротворчество, поэтому это и правда была возможность. Но я всё откладывал и откладывал. Всё-таки, Хабр открытая площадка, которую посещают разные люди, и не факт, что кому-то зайдёт мой стиль, или сама реализация, или ещё чего. Я делаю документацию и никого не трогаю. А ещё трудно описать что-то, с чем только начинаешь знакомиться. А вдруг я не так понял? А вдруг это очевидно и поэтому не стоит упоминания? Или наоборот, всё будет настолько сложно, что я не смогу объяснить? Вот в документации всё чётко. Понятно, для кого и чего мы её пишем (для комплекта поставки, шутка... да?). Всё ещё не решил, вырезать рефлексию из статьи или нет. Если вы это читаете, значит, решил оставить… или забыл убрать, и ревьюеры забыли… Раз есть, значит так надо.
Справедливости ради, Sphinx и reStructuredText (rst) я уже знал. Правда, предыдущий опыт был неудачным, на одном из прошлых мест работы внедряли связку doxygen-sphinx, но, во-первых, то была внутренняя документация, а, во-вторых, не взлетело. Технически оно работало, но документировать подробными комментариями не зашло команде (интересно, почему? ?). А rst не помню, где встречал, все языки разметки плюс-минус одинаковые, так что может по этому было легко.
В любом случае именно с docs-as-code я столкнулся впервые. Всегда хотел быть программистом, но не смог в абстрактное мышление и стал техписом. А тут всё как у взрослых программистов: есть репозиторий, построчно правим исходники, собираем локально для проверки, коммитим, пушим, можно делать ревью, ребейзить, черри-пикать, сташить и другие умные слова. В общем docs-as-code — любовь с первого взгляда. Больше не хочу делать документацию никак иначе (а придётся, эту вот статью я начал писать конечно же в ворде, — для разных задач разные инструменты, да и статейки на Конфлюенс тоже приходится писать, но это другое).
Тут же я «пришёл» на своё удалённое рабочее место, прочитал пару инструкций, выслушал несколько советов, настроил окружение и… всё. Работаю по docs-as-code больше года. И сейчас попробую рассказать как.
Процессы
Для меня docs-as-code — это не только sphinx и git, но и то, как мы работаем с текстом в рамках задачи по разработке, когда документация — это часть продукта наряду с его функциональностью, так что и дорабатывается она так же.
Как это выглядит в общем процессе разработки (упрощённо):
Разработчик (или несколько) сверяется с аналитикой и делает реализацию.
Собирается тестовый стенд.
QA сверяется с аналитикой и здравым смыслом, тестирует задачу в целом, если всё в порядке, передает на документирование.
Технический писатель сверяется с аналитикой, смотрит реализацию, вносит правки в документацию.
Документация собирается на тестовом (внутреннем) стенде.
QA проверяет соответствие документации, реализации и аналитики (для облегчения нагрузки на QA можно проверять документацию в рамках регрессионного тестирования и только по произошедшим изменениям, т.е. без полной вычитки).
Замечаете сходство? Воооот. Специалисты вносят построчные изменения в исходники, затем может быть локальная сборка для самотестирования и/или передача в тестирование, после которого всё сливается в основную ветку (aka master), и на выходе получаем работающий продукт с приростом функциональности и полную документацию с учётом этого прироста. Есть ли ценность этой схожести процессов, или это просто забавный факт?
Ценность есть. Во-вторых, техпис, работающий с подобным инструментарием, чуть лучше понимает разработчиков, а во-первых, подход docs-as-code унаследовал от разработки ПО много полезного:
Размер репозитория — это сумма изменений (с рисунками, к сожалению, не работает, но всё равно это проще, чем хранить все версии сборок).
Все правки абсолютно прозрачны, мы знаем, кто, когда и что поменял (и даже почему, если коммит-сообщение толковое).
Можно откатиться на любое из прошлых состояний (например, чтобы собрать оттуда предыдущую версию документации).
Несколько «разработчиков документации» могут работать в одном репозитории (при этом разрешение конфликтов для человекочитаемого текста намного проще, чем для кода).
Сборка итоговых документов производится на основании заданных параметров, что убирает человеческий фактор при верстке.
Техпис работает в тех же инструментах, что и разработка. Девопсам и админам не нужно подстраиваться к особенностям специализированного ПО, так как хранение, сборка документации и выкладывание её в общий доступ являются достаточно обычной задачей (не обязательно простой, есть нюансы, спасибо нашим админам, что всё это подняли и поддерживают, но это не какое-то специализированное ПО, с которым без стековефлоу не разобраться).
Результат доступен сразу после сборки — онлайн (удобно обсуждать документацию, зная, что все видят одну и ту же версию).
Можно разнообразить рабочие процессы использованием функционала Git.
Всё это происходит в рамках одной задачи на разработку, где документирование является завершающим этапом разработки, а не чем-то дополнительным. В итоге меньше планирования, согласований и просто меньше задач.
Релизная документация собирается как итог мелких изменений по задачам. Закончили разработку — документация готова (есть правки по замечаниям на регрессе и нюансы с оформлением, но это часть работы, не отменяющая преимуществ подхода).
Что до комфорта конкретного технического писателя, то очень удобно добавлять мелкие правки, не прорабатывая весь документ, ведь по некоторым продуктам пакет документации насчитывает сотни страниц.
Минусы? Они есть:
В сравнении с WYSIWYG-редакторами верстка ограничена общим стилем сборки, подвигать каждый абзац и подогнать страницы и оформление в реальном времени не получится, про рамки ГОСТ страшно даже думать. И если не удаётся идеально подобрать и настроить стиль, приходится дорабатывать итоговый документ руками.
В сравнении с разработкой ПО нет автоматического тестирования. Всё нужно проверять глазами. Но это относится к любой пользовательской документации и docs-as-code не решает эту проблему полностью, хотя сильно облегчает вычитку изменений.
Возможно, я не заметил какие-то другие минусы, но общее впечатление от подхода у меня крайне положительное. Чего и вам желаю!
Технические моменты
Подготовка
Есть инструкция https://sphinx-ru.readthedocs.io/archive/win-sphinx.html . Она частично устарела, но всё равно полезна для старта. На что стоит обратить внимание:
Мне пришлось добавить путь до директории Scripts в переменные окружения системы. По умолчанию этого не произошло и команды не опознавались.
Чтобы что-то собрать из rst, Git (https://git-scm.com/install/windows) не нужен, но я не представляю, как можно использовать docs-as-code без системы управления версиями. В данной статье рассмотрим локальную сборку. Использование гитлаба и подобных систем не отличается от использования их для работы с кодом.
-
После окончания базовой установки можно смело добавить ещё пару модулей:
Тема. Визуальный стиль онлайн-документации определяется темой. Если возьмём популярную Read The Docs, нужно её установить — pip install sphinx_rtd_theme. Тему можно допилить под себя или поменять на другую. Используемая тема задаётся в конфигурационном файле conf.py, вернусь к этому позже.
Чтобы собирать документы в формате docx, устанавливаем расширение docxbuilder (https://docxbuilder.readthedocs.io/en/latest/docxbuilder.html ). Команда: pip install docxbuilder. Использование расширений тоже задаётся через conf.py.
Озаботиться наличием какого-нибудь редактора для исходных файлов. Я использую VS Code (взять можно или из MS Store, или из https://code.visualstudio.com/). Для него даже были плагины, позволяющие видеть, как будет выглядеть текст после сборки, но они устарели, ничего другого найти не удалось, и я привык предвидеть, как оно будет выглядеть после сборки. Чем дольше так работаешь, тем легче и точнее просто работать в rst (что не отменяет проверку после сборки, чтобы ничего не съехало).
На этом подготовка закончена, можно создавать структуру файлов. Самый простой способ начать — это использовать команду sphinx-quickstart, находясь в каталоге документации. Нужно будет ответить на несколько вопросов, и в результате сформируется минимальная структура. Что до самих вопросов, то для ознакомительных целей принципиальной разницы нет, но могу отметить, что мне лично комфортнее разделять каталоги исходников и сборки (ответ «y» на первый вопрос), а выбор языка определяет текст элементов интерфейса и не имеет прямого отношения к языку проекта.
Допустим, мы создали директорию docs любым удобным способом и внутри неё хотим выполнить команду. Для этого директорию нужно открыть в Командной строке или PowerShell Windows (например, выбрать «Открыть в Терминале» по правой кнопке мыши).
Выполняем sphinx-quickstart и в результате сформируется следующая структура:
docs └── build | └── html (каталог появится после сборки) | ├── ... | └── index.html (корневая страница собранной документации) └── source | ├── _templates (место для каких-то шаблонов, но мы их не используем) | ├── _static (файлы, не являющиеся исходным кодом, например, картинки) | ├── conf.py (конфигурационные параметры Sphinx для этого проекта) | └── index.rst (корневой файл проекта, от него собирается остальная структура) ├── make.bat (командный файл, для сборки через команду make, но мы используем sphinx-build, поэтому можно удалить, чтобы не смущало) └── Makefile (инструкции для сборки командой make, тоже не обязательно, в нашем случае)
Интересными являются файлы conf.py и index.rst, разберём их подробнее.
conf.py
Если пропустить все закомментированные строки, а также информацию о проекте, то окажется, что собственно конфигурация — это всего несколько строк, большинство из которых можно не трогать. В нашем проекте мы потрогали:
extensions = [ ] — здесь задействуются расширения. Например, вышеупомянутый docxbuilder, чтобы выгружать docx-файлы. Выглядит это вот так:
extensions = ['docxbuilder']
Если планируете использовать документ-шаблон, его можно добавить через параметр docx_style = 'имя_файла_шаблона.docx', через шаблон можно задать форматирование, стили, титульный и так далее. Но это уже вордовская тема.
html_theme = 'alabaster' — выбор визуальной темы. Вместо дефолтной 'alabaster' можно поставить Read The Docs, вот так: html_theme = 'sphinx_rtd_theme'
Вот и вся конфигурация. Теперь перейдём собственно к документации.
index.rst — это уже rst-формат, и наполнение файла должно соблюдать синтаксис языка разметки reStructuredText. Кратко о языке тут: Стандартный синтаксис разметки reStructuredText — Генератор документации Sphinx 1.0 documentation (sphinx-ru.readthedocs.io). Дополнительно используется разметка от самого Sphinx, кратко тут: Конструкции разметки Sphinx — Генератор документации Sphinx 1.0 documentation (sphinx-ru.readthedocs.io). Чтобы не погружаться в детали, разберём пример построчно.
Если убрать комментарии из полезного в файле, останется вот это:
Название проекта ================= .. toctree:: :maxdepth: 2 :caption: Contents:
Текст над линией из «=» заголовок всей документации. В rst «=» показывает заголовок первого уровня (для каждого уровня своё).
Структура под .. toctree:: позволяет задать подраздел документации, где :maxdepth: указывает уровень вложенности содержания, а :caption: заголовок содержания (может быть несколько содержаний, именно так сделано у нас https://docs.iwarma.ru/, где на одной странице собрана документация по нескольким продуктам).
Разбор примера
Прежде чем разбирать правки по этапам, давайте соберём пустой проект.
Для этого откроем директорию docs в Командной строке или PowerShell Windows и выполним команду:
sphinx-build -b html source build/html ,
где sphinx-build – собственно, команда;-b – параметр сборки. -b обычная сборка. Ещё можно использовать -M, чтобы имитировать make-сборку;html – тип сборки (если захотим собрать, например, вордовский документ, здесь будет docx);source – путь до каталога исходных текстов (так как выполняем команду из родительского каталога, можно указать имя, но можно использовать и полный путь, хоть от c:\);build/html – аналогично путь до каталога, где будет формироваться результат сборки документации.
Чтобы открыть собранную документацию, переходим в build, там в html и открываем index.html
Если ранее в conf.py включили тему Read The Docs, получим примерно такое:

Если тема другая, внешний вид будет отличаться, но наполнение будет таким же. Правда, вы упустите приятную (для начинающих) особенность темы — ссылку «Посмотреть исходный код страницы» в правом верхнем углу.
Как я уже упоминал, использование docs-as-code без контроля версий я себе плохо представляю. Поэтому создадим репозиторий:
Правой кнопкой на каталог source
Выбрать Open git bash here
git init
В каталоге появится набор файлов Git (скорее всего, скрытых от пользователя), но нас интересует только пара файлов, состояние которых хотим отслеживать с помощью Git. Это всё те же conf.py и index.rst. Добавим их в репозиторий:
git add --all
(можно было «git add .» или ещё чего, но в «--all» наглядности больше)
И теперь:
git commit -m "Начальное состояние проекта"
Готово. У нас есть репозиторий с некоторым базовым состоянием.
Не закрывайте окно git bash, оно нам ещё пригодится.
Теперь можно перейти к созданию текста. Ничего не мешает добавить текст прямо в index.rst, хотя для сложных проектов это не очень удобно. У нас тут проект минимальный, так что добавим текст прямо под заголовком проекта. Например, «Съешь же ещё этих мягких французских булок, да выпей чаю», так как люблю набирать панграммы на клавиатуре. Каждому своё. Не забудьте сохранить изменения.
Повторим сборку sphinx-build -b html source build/html (мы уже дважды выполняем эту команду, и дальше будем, так что для кого-то может быть удобно создать и использовать пакетный bat-файл).
Открываем index.html и видим, что поменялось.
Если результат нас устраивает, можно добавить изменения в репозиторий:
git add index.rstgit commit -m "Добавлен текст про булки"
Мы добавили второй коммит, и благодаря Git мы сможем отменить изменения, посмотреть, что было добавлено, переключиться на состояние конкретного коммита и многое другое, что делается при работе в репозитории, например, с программным кодом. Люблю эту тему, но не хочу зависать на работе с Git, поэтому движемся дальше.
Я бы сказал, что для первого знакомства с docs-as-code этого достаточно, но не скажу, а отмечу ещё пару-тройку моментов:
Создание структуры документации, когда кроме заглавной страницы существуют подразделы.
Добавление рисунков и ссылок.
Сборка в docx и публикация вовне.
Подразделы
Когда выше разбирали файл index.rst , подразделы показывались там в блоках toctree. Позже мы имели возможность убедиться, что эти блоки никак не отражаются в итоговом тексте. Действительно, что бы вы ни писали в toctree, оно не имеет смысла, пока там нет ссылки на подраздел. Что ж, давайте создадим подраздел.
В директории source создадим директорию, скажем, chapters, а внутри неё создадим файл chapter_1.rst
(чтобы создавать файлы с расширением rst из Проводника Windows, может понадобиться включить отображение расширений файлов)
В chapter_1.rst добавим какой-нибудь текст, например:
«Эй, жлоб! Где туз? Прячь юных съемщиц в шкаф.»
Обратите внимание (а если хочется – проверьте), хотя в проекте есть файл с текстом, он не попадёт в сборку, пока не будет упомянут в «вышестоящем» файле (в нашем случае это index.rst).
Откроем index.rst и в разделе toctree под строкой caption добавим:
chapters/chapter_1
Здесь расширение rst указывать не обязательно, а вот отступ от края обязательно должен соответствовать вложенным строкам toctree, чтобы sphinx понял, что это не просто случайный текст:
.. toctree:: :maxdepth: 2 :caption: Раздел документации: chapters/chapter_1
Если теперь собрать sphinx-build -b html source build/html, как мы делали ранее, текст попадёт в документацию (чтобы его увидеть, придётся нажать кнопку «Следующая» в правом нижнем углу), но он не отобразится в дереве страниц слева (кроме того, при сборке будет несколько красных сообщений о ссылке на документ без заголовка).
Чтобы это исправить, добавим в начало файла chapter_1.rst заголовок:
Панграмма
==========
И повторим sphinx-build -b html source build/html.
Теперь ссылка на подраздел должна появиться в структуре слева.
Не забываем добавлять изменения в репозиторий:
git add index.rstgit add chapters/chapter_1.rstgit commit -m "Добавлена ещё одна панграмма"
Тут читатель, не привыкший к Git с рождения, подумает: «А нет ли другого интерфейса для выполнения рутинных операций?». Конечно! Кто-то любит fork, кто-то tortoise, а кто-то и встроенным Git GUI пользоваться умеет, но это уже дело вкуса.
Рисунки и ссылки
Разумеется, ссылаться на разделы можно не только через toctree. Да и не только на разделы, а и на другие элементы. Разберем всё это на пример добавления рисунка, так как в rst все ссылки работают схожим образом.
Для начала найдём какой-нибудь файл с изображением, которое мы хотим добавить в текст. В рабочих проектах используем только png, но другие форматы тоже поддерживаются (jpeg точно).
Файл можно как просто положить в _static, так и создать структуру для рисунков. В любом случае, нужно будет указывать путь до файла от корня проекта (где лежит index.rst).
Я нашел какой-то бесплатный файл с манулом и длинным названием, переименовал его в manul.jpg и положил в _static.
После чего внёс изменения в chapter_1.rst, и теперь он выглядит так:
Панграмма =============== Эй, жлоб! Где туз? Прячь юных съемщиц в шкаф. Ссылка на рисунок :ref:Рисунок -- Сам рисунок <manul>. .. _manul: .. figure:: /_static/manul.jpg :width: 700 :align: center :alt: Рисунок -- Сам рисунок
Тут есть ссылка (:ref:Рисунок -- Сам рисунок <manul>), идентификатор раздела (.. _manul:), на который можно сослаться, и внутри раздела свойства добавляемого рисунка (.. figure:: и далее).
На всякий случай, index.rst выглядит так:
Пример документации ======================== Съешь же ещё этих мягких французских булок, да выпей чаю. .. toctree:: :maxdepth: 2 :caption: Раздел документации: chapters/chapter_1
А файловая структура вот такая:
docs └── build | └── html | ├── остальные файлы сборки | └── index.html └── source ├── chapters | └── chapter_1.rst ├── _static | └── manul.jpg ├── conf.py └── index.rst
Ну и раз на то пошло, вот так выглядит минимальный conf.py
project = 'Пример документации' copyright = '2026, Имя проекта' author = 'Имя автора' # -- General configuration --------------------------------------------------- extensions = ['docxbuilder'] templates_path = ['_templates'] exclude_patterns = [] language = 'ru' # -- Options for HTML output ------------------------------------------------- html_theme = 'sphinx_rtd_theme' html_static_path = ['_static']
Снова sphinx-build -b html source build/html , и в итоге у меня получилось вот так:

Размер рисунка можно задавать как width, так и scale в процентах от исходного. Но рисунок всё равно будет вписан в документацию по ширине. Лично мне width больше нравится. Более предсказуемо.
Итого, ссылки (на что угодно) оформляются как
:ref:текст_ссылки <идентификатор> ,
если текст ссылки не нужен (например, ссылка на раздел, где текст берётся из названия раздела), можно оставить
:ref:идентификатор .
Обратите внимание, идентификатор в ссылке задаётся без «_» (нижнего подчеркивания) в начале, тогда как в тексте он всегда начинается с «_», точнее даже с «.. _» (две точки, пробел, нижнее подчеркивание).
Ссылки на параграфы внутри текста создаются аналогичным образом.
Ну и, конечно, не забудьте добавить изменения в репозиторий:
git add --allgit commit -m "Добавлен один манул"
Вордовский документ и внешняя документация
Сборка всего этого добра в docx не требует больших усилий (если установили расширение docxbuilder, конечно), ведь необходимо и достаточно в команде сборки поменять html на docx и найти собранный файл в соответствующем каталоге.
Пара слов о публикации на внешнем сайте. У нас это автосборка в Гитлабе и авторазмещение на сервере, но для начала можно физически копировать результат сборки в структуру веб сайта. Впрочем, это как будто выходит за рамки данной статьи.
На прощание
Я был удивлён, насколько комфортно реализуется подход docs-as-code. Перенос имеющейся документации в новый формат — процесс непростой, зато работать так одно удовольствие. Если специалист хоть немного знаком с Гитом и каким-либо языком разметки/программирования, вопросов не возникнет, но даже если нет, можно работать, не погружаясь в детали реализации (например, создать пакетные файлы для основных операций со Sphinx).
Единственное, что может смутить техписа, привыкшего к WYSIWYG-редакторам, это писать на языке разметки, а результат смотреть после сборки. Есть решения, близкие к WYSIWYG, но мы в команде быстро привыкли: изменил исходник -> собрал и проверил локально -> коммит-пуш-MR -> еще раз проверил на стенде -> задача закрыта.
Спасибо за внимание!