Что такое Docs as Code классно описано в статье Docs as Code: введение в предмет.
В двух словах: это ведение документации на языке разметки (Markdown, AsciiDoc) с хранением в репозитории.
Плюшки — все вытекающие от работы с репозиторием.
Минусы — в этой статье.

На осенних Analyst Days прошлого года добрая четверть докладов была посвящена теме Docs as Code. На тот момент конклав аналитиков на моём прежнем месте работы уже 9 месяцев решал, нужен ли на проекте модный-стильный-молодёжный Docs as Code или всё же остаться в дышащем на ладан Confluence. К чему пришли — не знаю. На новом месте работы мы внедрили Docs as Code за неделю — было чёткое понимание проблематики, подход казался выигрышным решением. Используем полгода.

Какие были требования к системе документирования

Обязательные

  1. Развёртывание во внутреннем контуре. Ввиду корпоративной тайны внешние облака были исключены.

  2. Возможность параллельной работы над документом.

  3. Автоматическое отображение дел��ты изменений.

  4. Автоматическое формирование PDF для представления заказчику.

  5. Возможность переиспользования конкретных блоков из одних документов в других (include).

  6. Возможность согласования документации конкретными людьми.

  7. Отображение документации в полностью скомпилированном виде.

Желательные

  1. Автоматическая подвязка изменений документации к задачам на разработку в системе управления задачами.

  2. Доступ к документации для разработчиком непосредственно из IDE.

  3. Сохранение имеющихся документов, которые были написаны в Markdown и AsciiDoc.

  4. Opensourse для возможности самостоятельной доработки.

  5. Использование PlantUML.

Docs as Code закрывает все эти потребности. И вот как мы это сделали.

Решение

На проекте используются:

  • Система контроля версий Gitea.

  • Система управления проектами и задачами Redmine.

  • Ранее документация велась в Wiki.js. Эта вики поддерживает Markdown, некоторые коллеги предпочитали использовать именно его.

Что выбрали для Docs as Code

  • Язык разметки AsciiDoc. В отличии от Markdown он поддерживает include и переменные "из коробки".

  • IDE PyCharm. У него есть бесплатная версия, официальные плагины для AsciiDoc и PlantUML, а заодно неплохая встроенная проверка орфографии и пунктуации русского языка. Субъективно он более дружелюбен к непродвинутому пользователю, чем VS Code.

  • Hugo для отображения полной документации.

  • Для использования PlantUml-диаграмм внутри AsciiDoc-документов развернули во внутреннем контуре серверы Kroki и PlantUML.

  • Сборкой документации после коммита занимается Drone.

Внешний вид документации в Hugo с темой Lotus Docs
Внешний вид документации в Hugo с темой Lotus Docs

Как организовали хранение документации

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

Отдельно завели репозиторий архитектуры. В нём хранится документация, которая затрагивает несколько сервисов: архитектурная схема, перечень очередей сообщений, верхнеуровневые описания межсервисных взаимодействий, proto-моделей (используем gRPC), какие-то общие правила и т.д.

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

Как организовали процесс работы

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

Также изначально была идея ��оддерживать две постоянные ветки документации:

  1. prod — с описанием функциональности системы в состоянии на проде;

  2. dev — с описанием функциональности системы в состоянии реализованных, но ещё не выпущенных доработок.

Документация с учётом отдельных доработок должна была лежать во временных ветках, соответствующих эпикам по бизнес-запросам.

Предполагалось, что пока документация по фиче будет сливаться в ветку dev одновременно с влитием кода в общую ветку, а в prod одновременно с выносом функциональности на прод.

От этих идей мы отказались быстро.

Во-первых, важно было поддерживать ссылочность внутри документов. Причём эти ссылки должны были работать в Hugo. Соответственно мы стали указывать в документах ссылки на предполагаемую страницу документа в Hugo, причём зачастую на этот момент страницы в Hugo не существовало, так как оба документа создавались в рамках одной задачи.
Соответственно если бы разработчик решил читать документацию в IDE, то первая же ссылка перебросила бы его в Hugo. Если бы целевой документ был старым! А если новым, то ссылка вела бы на страницу 404, потому что настраивать сборку Hugo для каждой ветки эпика нецелесообразно.

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

В-третьих, во время проектирования решения аналитик должен учитывать все актуальные требования. Долгое пребывание документации в ветках эпиков неизменно привело бы к тому, что аналитик не учёл бы требования, которые находятся в ветках других эпиков и ещё не слиты в dev.

В итоге мы остановились на такой схеме:

  1. Аналитик проектирует решение в ветке эпика, после чего презентует его команде разработки на общей встрече и формирует пачку пулреквестов в dev (по 1 в каждом репозитории с изменениями).

  2. Пулреквесты согласуют архитектор, ведущие разработчики затронутых сервисов, тестировщики, ведущий аналитик.

  3. В dev таким образом хранятся все требования, которые были реализованы, уже находятся в разработке, и которые только планируется взять в разработку.

  4. А ветка prod оказалась не нужна, потому что Gitea не позволяет переносить отдельные коммиты, только все накопленные разом. При этом некоторая готовая функциональность может не пойти в релиз сразу. Оставалось править документацию ветки prod вручную, но для этого я недостаточно самоотвержена.

  5. Разработчики видят полную и актуальную документацию в Hugo.

Схема сократилась до:

Казалось бы, всё заработало. Что могло пойти не так?

Грабли

Шишка первая, ожидаемая. Аналитиков пришлось учить работать с git и IDE, писать на языке разметки. Решали проблему пачкой гайдов, блужданием по документации AsciiDoc и иногда методом тыка.

Шишка вторая, о которой все умалчивают. Нагрузка на глазки аналитиков возросла в разы. Мало что садит зрение так же, как код. В бытность программистом я потеряла две диоптрии вопреки всем гимнастикам. Поверьте, заполнение таблички с WYSIWYG резко отличается от контроля количества вертикальных палочек в строке 213. Добавьте сюда повторные правки, когда палочки всё же недосчитали, и таблица превратилась в фарш. А ещё билды, поломанные лишним слешем. Кстати, представьте себе лицо аналитика, который всю жизнь спокойно жал кнопочку "Сохранить" в Wiki, и вдруг уронил билд.

Шишка третья, макулатурная. Количество документов Х2 просто потому, что PlantUML схемы рисуются в отдельном файле, а ещё потому, что в каждой папочке Hugo должен лежать index-файл этой папочки. Представьте себе лицо разработчика, который для согласования единственного метода получает пять файлов.

Шишка четвёртая, эстетическая. Оказалось, что ни Hugo, ни Gitea не поддерживают AsciiDoc из коробки в полной мере. В частности в Hugo некорректно отображаются большие и сложные таблицы — сбоит определение ширины, объединение ячеек, выравнивание в ячейке. Giteа не показывает схемы PlantUML.

Шишка пятая, коммуникационная. В Hugo нельзя просто выделить текст с ошибкой и написать к нему комментарий, как в Confluence. А это значит, что в чаты к аналитикам летит поток со скриншотами или ссылками на текст с указаниями, что исправить.

Шишка шестая, техническая. С разрастанием документации её билд начал собираться медленнее, ещё медленнее, совсем медленно. Причину искали некоторое время, но, честно говоря не особо усердно, потому что уже было ясно, что проблем у нас больше, чем выигрыша.

Шишка седьмая, основная. Согласование документации превратилось в ад.
Представьте: на согласование прилетает пачка X2 документов, ссылающихся друг на друг, но ссылки не работают; при этом схемы вы не можете посмотреть — они не отрисовываются, вы читаете файлы PlantUML и рисуете схему в голове; возможно, неправильно, потому что вы разработчик и никогда на PlantUML не писали; кроме того, вы можете видеть дельту изменений только в формате языка разметки, и пытаетесь сопоставить прочитанное и посчитанное количество палочек с не очень ровной табличкой, которую видите в предпросмотре.

А теперь представьте, что через это проходят сразу десять человек.

Чего мы только ни делали! Мы читали документацию онлайн с шарингом экрана её автором; мы кидали друг другу собранные из всей пачки документов PDF; мы выкачивали ветки эпиков, чтобы читать в IDE; мы заливали документацию без согласования, чтобы дать возможность прочитать в сносном виде с работающими ссылками.

Но все эти костыли не позволяют увидеть дельту изменений и документацию в целом единовременно.

Решение отказаться от Docs as Code было принято после того, как на согласование улетела пачка из пятидесяти документов по одному небольшому эпику. Мы планируем по-прежнему хранить документацию в репозитории, но для чтения, редактирования и согласования использовать Confluence-подобную систему. Интеграция с git была одним из критериев выбора.