Sphinxとgithub actionsを使ってドキュメントを自動で生成する

python

{{ page.title }}

普段使っているツールを再利用できるようにパッケージにまとめる作業をしている。

コードをまとめていると合わせてドキュメントもまとめたくなるが、それぞれの関数を全部手でまとめるのはとても面倒くさい。

なので、Sphinxを使って自動化したい。

Sphinx は reStructureedText という記法でドキュメントを書いたものを html へ変換するツールのようだ。

これに sphinx-apidoc の CLI コマンドがついていて、Python のコードにつけている docstring をもとに reST を生成できる。

$ sphinx-apidoc ./source/package ./package

これでプロジェクトルート下の package に含まれる Python コードのドキュメントが source/package 下に生成される。

さらに、source 下にあるディレクトリをもとに HTML を docs 下に生成させるには次のコマンドを実行する。

$ sphnx-build -b html ./source ./docs

これを手元でやって GitHub に push するのは面倒くさいので GitHub actions で自動化する。

name: CI/CD

on:
  push:
    paths:
      - "package/**"
      - "tests/**"

jobs:
  build:  deploy:
    needs: build
    runs-on: $\{\{ matrix.os \}\}
    strategy:
      matrix:
        os: [ubuntu-latest]
    steps:
      - uses: actions/checkout@v2
      - name: Create new branch and merge main
        env:
          GITHUB_TOKEN: $\{\{ secrets.GITHUB_TOKEN \}\}
        run: |
          git checkout -b docs
      - name: Set up Python
        uses: actions/setup-python@v2
        with:
          python-version: 3.8
      - name: Install sphinx and depends
        run: |
          python -m pip install --upgrade pip
          pip install pipenv
          pipenv install --dev --skip-lock
      - name: Build HTML by Sphinx
        run: |
          pipenv run sphinx-apidoc -f -o source/package./package
          pipenv run sphinx-build -b html ./source ./docs
      - name: deploy
        run: |
          git config user.name = "github-actions"
          git config user.email = "github-actions[bot]@users.noreply.github.com"
          git add docs -f
          git commit -m "auto build by github actions" --allow-empty
          git push --set-upstream origin docs -f

これで packagetest に変更があったときに自動でドキュメントを更新し、docs ブランチに変更内容を push する。

ただ、git push --force をしている都合上、docs ブランチの変更は追えない。

加えて、pytest でのカバレッジもドキュメント内に含めたい。

pytest だけではカバレッジの計測はできないみたいなので追加で pytest-cov を導入する。
(setup.py test で pytest を使うには追加で pytest-runner も必要)

$ pip install pytest pytest-cov

pytest のカバレッジを html で出力させるには以下を実行する。

$ pytest ./tests --cov=tests --cov-report=html:report

これで、report 下に生成される。

これを Sphinx での生成に含めたい。

Sphinx で .md ファイルを使うための方法はあるが、直接 HTML ファイルをレイアウトを共有して使う方法が見つからなかった。
なので、力技で対処する。

documentation
========================================

.. toctree::
   :maxdepth: 2
   :caption: Contents:

   ./package/modules



Indices and tables
==================

* :ref:`genindex`
* :ref:`modindex`
* .. raw:: html

   <a href="coverage/index.html">Coverage Report</a>
.. * :ref:`search`

pytest での html 出力先を docs/coverage にして、reST 内で HTML を書いてリンクを作る方式だ。

Sphinx のテーマのレイアウトは引き継げないが、GitHub pages 上で見ることはできる。

最終的に GitHub actions の yml ファイルは以下のようになった。

name: CI/CD

on:
  push:
    paths:
      - "mizlab_tools/**"
      - "tests/**"

jobs:
  deploy:
    needs: build
    runs-on: $\\{\\{ matrix.os \\}\\}
    strategy:
      matrix:
        os: [ubuntu-latest]
    steps:
      - uses: actions/checkout@v2
      - name: Create new branch and merge main
        env:
          GITHUB_TOKEN: $\{\{ secrets.GITHUB_TOKEN \}\}
        run: |
          git checkout -b docs
      - name: Set up Python
        uses: actions/setup-python@v2
        with:
          python-version: 3.8
      - name: Install sphinx and depends
        run: |
          python -m pip install --upgrade pip
          pip install pipenv
          pipenv install --dev --skip-lock
      - name: Compute coverage
        run: |
          pipenv run pytest --cov=package --cov-report=html:docs/coverage
      - name: Build HTML by Sphinx
        run: |
          pipenv run sphinx-apidoc -f -o source/package ./package
          pipenv run sphinx-build -b html ./source ./docs
      - name: deploy
        run: |
          git config user.name = "github-actions"
          git config user.email = "github-actions[bot]@users.noreply.github.com"
          git add docs -f
          git commit -m "auto build by github actions" --allow-empty
          git push --set-upstream origin docs -f

yaml 中の{{}}はすべて\のない形だが、jekyll のパーサがうまくパースしてくれないのでつけている。