0032 — Sphinx Multiversion

Содержимое страницы

Sphinx Multiversion

Если вы работаете с системой документирования Sphinx, то, наверное, рано или поздно столкнётесь с проблемой поддержки документации для нескольких версий продукта.

Для решения этой проблемы существует несколько расширений Sphinx:

  • sphinx-versions

    • Уже 4 года не получает обновлений.
    • 17 звёзд на GitHub.
  • sphixcontrib-versioning

    • Уже 4 года не получает обновлений.
    • 116 звёзд на GitHub.
  • sphinx-multiversion

    • Уже 3 года не получает обновлений.
    • 126 звёзд на GitHub.

Во время поиска подходящего решения для своего проекта, я делал выбор из 2-х последних. В итоге остановился на sphinx-multiversion как более актуальном. Также в его пользу сыграло то, что описано решение некоторых типовых проблем, например, с темой оформления ReadTheDocs.

В этой статье рассказывается как установить и настроить расширение sphinx-multiversion, а также дан обзор некоторым его возможностям.

Установка

  1. Установите пакет Python sphinx-multiversion:

    pip3 install sphinx-miltiversion
    
  2. В каталоге source/_templates/ создайте файл versions.html, содержащий шаблон для отображения списка версий в боковой панели навигации:

    {% if versions %}
    <h3>{{ _('Versions') }}</h3>
    <ul>
      {%- for item in versions %}
      <li><a href="{{ item.url }}">{{ item.name }}</a></li>
      {%- endfor %}
    </ul>
    {% endif %}
    

    Если используется тема ReadTheDocs, шаблон должен иметь такой вид:

    {%- if current_version %}
    <div class="rst-versions" data-toggle="rst-versions" role="note" aria-label="versions">
      <span class="rst-current-version" data-toggle="rst-current-version">
        <span class="fa fa-book"> Other Versions</span>
        v: {{ current_version.name }}
        <span class="fa fa-caret-down"></span>
      </span>
      <div class="rst-other-versions">
        {%- if versions.tags %}
        <dl>
          <dt>Tags</dt>
          {%- for item in versions.tags %}
          <dd><a href="{{ item.url }}">{{ item.name }}</a></dd>
          {%- endfor %}
        </dl>
        {%- endif %}
        {%- if versions.branches %}
        <dl>
          <dt>Branches</dt>
          {%- for item in versions.branches %}
          <dd><a href="{{ item.url }}">{{ item.name }}</a></dd>
          {%- endfor %}
        </dl>
        {%- endif %}
      </div>
    </div>
    {%- endif %}
    

    Другие шаблоны можно посмотреть на странице проекта.

  3. Сделайте правки в конфигурационном файле source/conf.py:

    • Добавьте в список extensions модуль sphinx_multiversion:

      extensions = [
          'sphinx_multiversion',
      ]
      
    • Добавьте в список templates_path каталог _templates:

      templates_path = [
          '_templates',
      ]
      
    • Чтобы использовать созданный ранее шаблон на всех страницах проекта, добавьте в словарь html_sidebars строки:

      html_sidebars = {
          '**': [
              'versions.html',
          ],
      }
      
  4. Добавьте файлы проекта в индекс и зафиксируйте изменения:

    git add . && git commit -m "<message>"
    

    где <message> — сообщение коммита.

    Этот шаг обязателен, так как для управления версиями документации расширение sphinx-multiversion использует возможности Git.

Сборка

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

sphinx-multiversion \
   -c <PATH> \
   -C \
   -D <setting>=<value> \
   <sourcedir> \
   <targetdir>

Здесь:

  • -c — путь к каталогу с файлом conf.py. По умолчанию используется значение, указанное в параметре <sourcedir>.
  • -C — указание не использовать настройки из файла conf.py.
  • -D — указание настроек в формате <settings>=<value>. Позволяет переопределить значения параметров из файла conf.py, либо вовсе избежать его использования, если ключ используется совместно с ключом -C.
  • <sourcedir> — путь к каталогу с исходными файлами проекта.
  • <targetdir> — путь к каталогу, в котором следует разместить результаты сборки.

В самом простом случае команду можно сократить до такой:

sphinx-multiversion source/ build/

В каталоге build/ в этом случае будут созданы подкаталоги с версиями документации.

Сборка ветки master

Допустим, в проекте сейчас есть только ветка master. Даже с ней проект можно собрать. Зафиксируйте изменения и соберите проект. В каталоге build/ будет создан подкаталог master/, в котором будет размещена версия проекта для ветки master.

Чтобы проверить результаты сборки:

  1. Запустите локальный хостинг, например:

    python3 -m http.server -d build/ -b 127.0.0.1 8080
    
  2. Откройте в браузере ссылку http://127.0.0.1:8080/master/.

  3. Убедитесь, что в панели навигации слева отображается блок Versions, который сейчас содержит всего одну запись — ссылку на версию master.

Версионирование проекта

Есть несколько подходов к версионированию, но я считаю самым удобным использование тегов Git. В этом случае история коммитов выглядит так:

Линейная история коммитов

Возможно, нам никогда не придётся вносить изменения в версию 1, и пока нет смысла заводить отдельную ветку. Но если вдруг такая необходимость появится, можно сделать так:

  1. Переключиться на нужный тег:

    git checkout v1
    

    Git переместит указатель HEAD на коммит с привязанным к нему тегом.

  2. Создать новую ветку:

    git checkout -b v1
    

    Это предотвратит ситуацию с «detached HEAD».

  3. Сделать правки и зафиксировать изменения.

  4. Удалить старый тег:

    git tag -d v1
    
  5. Воссоздать тег на текущем коммите, в новой ветке:

    git tag v1
    

    История коммитов примет вид:

    История коммитов с ветками

Настройка

По умолчанию расширение собирает версии проекта, перебирая все имеющиеся теги и ветки. С учётом вышесказанного имеет смысл ограничить доступные версии только тегами. Для этого в source/conf.py следует добавить строки:

smv_tag_whitelist= r'^.*$'
smv_branch_whitelist = r'^(?!master).*$'
smv_released_pattern = r'^tags/.*$' # только теги

Другие возможные варианты описаны в документации проекта.