🙆

gRPC開発におけるドキュメントを自動生成する

2022/06/27に公開

gRPCのドキュメントを自動生成するための備忘録です。

GitHub Actionsで実行した場合はこちらを参照

https://zenn.dev/jy8752/articles/294dc9a64c18f3

なぜやるか

gRPCの開発におけるメリットの一つにスキーマ駆動の開発になることがあると思います。protoファイルが全てなのでrpcについて知りたければprotoファイル見ればいいじゃん勢でしたが、「このField何?」とか「このrpcはどういうエラー吐くの?」とか聞かれたときに全然protoファイル見てもわかんないなとなり、別途手動でドキュメント管理するのはやりたくなかったので何かいい方法ないかなと調べたときにprotoc-gen-docの存在を知りました。protoファイルは絶対書くことになるのでprotoファイルの情報量をコメントで増やし、そこからドキュメントを自動生成すれば実装者の負担も減るし、使う側も最新の情報を取得できるしwin-winだなと思い導入。もし、チーム内で採用するのであればprotoファイルに書き込むコメントのルールを事前に決めておくことで実際にprotoファイルを作成するときに悩まないと思います。

protocbufのインストール

brew update
brew upgrade
brew install protobuf
brew upgrade protobuf

protoc --version
> libprotoc 3.19.4

protoc-gen-docのインストール

go version
> go version go1.18.3 darwin/arm64

go install github.com/pseudomuto/protoc-gen-doc/cmd/protoc-gen-doc@latest

下記コマンドでドキュメントを生成します。
(./docフォルダは事前に作成しておく必要があります。)

protoc \
  --doc_out=./doc \
  --doc_opt=markdown,index.md \
  ./**/*.proto

問題なければ./doc/index.mdが生成されているかと思います。

push時にドキュメントを自動生成する

今回はGitLabのCI/CDを使用しますがGitHub Actionsなどでも同じ感じでできると思います。
以下のようなgitlab-ci.ymlを作成。ドキュメントを作成した後にコミットし直す必要があるのでssh, gitのインストールと設定も必要。あと、mainブランチのprotoファイルが変更あった時に条件絞ってます。

gitlab-ci.yml
# protoc-gen-docのインストールにGoを使うのでGoのdockerイメージを使用
image: golang:latest

stages:
  - build

protoc-gen-doc:
  stage: build
  script: 
    - apt-get update && apt-get install -y unzip sudo openssh-server git
    # protocolbufのインストール
    - curl -OL https://github.com/google/protobuf/releases/download/v3.19.4/protoc-3.19.4-linux-x86_64.zip
    - unzip protoc-3.19.4-linux-x86_64.zip -d protoc3
    - sudo mv protoc3/bin/* /usr/local/bin/
    - sudo mv protoc3/include/* /usr/local/include/
    # protoc-gen-docのインストール
    - go install github.com/pseudomuto/protoc-gen-doc/cmd/protoc-gen-doc@latest
    # sshのセットアップ
    - mkdir -p ~/.ssh
    - chmod 700 ~/.ssh
    - ssh-keyscan -H "$CI_SERVER_HOST" >> ~/.ssh/known_hosts
    - eval "$(ssh-agent -s)"
    - echo "$SSH_PRIVATE_KEY" | ssh-add - > /dev/null
    # gitのセットアップ
    - git config user.name $GITLAB_USER_NAME
    - git config user.email $GITLAB_USER_EMAIL
    - git remote set-url --push origin git@$CI_SERVER_HOST:$CI_PROJECT_PATH.git
    - git checkout $CI_COMMIT_REF_NAME
    # スクリプト実行
    - ./generate-document.sh
  artifacts:
    paths:
      - doc/
  rules:
    - changes: 
      - "**/*.proto"
      if: '$CI_COMMIT_REF_NAME == "main"'
      when: on_success
generate-document.sh
#!/bin/bash

# docディレクトリがなければ作る
if [ ! -d ./doc ]; then
  mkdir ./doc
fi

# ドキュメント作成(markdownとhtmlの2種類を生成)
protoc \
  --doc_out=./doc \
  --doc_opt=html,index.html \
  ./**/*.proto

protoc \
  --doc_out=./doc \
  --doc_opt=markdown,index.md \
  ./**/*.proto

# ごみ削除
if [ -d ./protoc3 ]; then
  rm -r protoc3
fi

if [ -e protoc-3.19.4-linux-x86_64.zip ]; then
  rm protoc-3.19.4-linux-x86_64.zip
fi

# 差分があればコミットし直す
if [ `git status -s | wc -l` -gt 0 ]; then
  git add ./doc
  git commit -m 'update document'
  git push --push-option=ci.skip origin $CI_COMMIT_REF_NAME
  
  echo "Success commit"
else
  echo "Exit due to no difference"
fi

protoファイルに変更がある状態でpushをし、GitLabのjobが成功していてドキュメントが生成されていれば成功。こんな感じ

おまけ(GitLab pagesで公開する)

html形式でも出力をしていたのでGitLab pagesにて公開してみる。gitlab-ci.ymlを以下のように修正。

gitlab-ci.yml
image: golang:latest

stages:
  - build
+  - deploy

protoc-gen-doc:
  stage: build
  script: 
    - apt-get update && apt-get install -y unzip sudo openssh-server git
    # protocolbufのインストール
    - curl -OL https://github.com/google/protobuf/releases/download/v3.19.4/protoc-3.19.4-linux-x86_64.zip
    - unzip protoc-3.19.4-linux-x86_64.zip -d protoc3
    - sudo mv protoc3/bin/* /usr/local/bin/
    - sudo mv protoc3/include/* /usr/local/include/
    # protoc-gen-docのインストール
    - go install github.com/pseudomuto/protoc-gen-doc/cmd/protoc-gen-doc@latest
    # sshのセットアップ
    - mkdir -p ~/.ssh
    - chmod 700 ~/.ssh
    - ssh-keyscan -H "$CI_SERVER_HOST" >> ~/.ssh/known_hosts
    - eval "$(ssh-agent -s)"
    - echo "$SSH_PRIVATE_KEY" | ssh-add - > /dev/null
    # gitのセットアップ
    - git config user.name $GITLAB_USER_NAME
    - git config user.email $GITLAB_USER_EMAIL
    - git remote set-url --push origin git@$CI_SERVER_HOST:$CI_PROJECT_PATH.git
    - git checkout $CI_COMMIT_REF_NAME
    # スクリプト実行
    - ./generate-document.sh
  artifacts:
    paths:
      - doc/
  rules:
    - changes: 
      - "**/*.proto"
      if: '$CI_COMMIT_REF_NAME == "main"'
      when: on_success

+pages:
+  stage: deploy
+  dependencies:
+    - protoc-gen-doc
+  script:
+    - mv doc/ public/
+  artifacts:
+    paths:
+      - public
+  rules:
+    - if: '$CI_COMMIT_REF_NAME == "main"'
+      when: on_success
+    - when: never

アクセス可能ユーザーも設定できて、GitLabへのアクセス権があるユーザーのみに公開もできるのでチーム内のみに公開とかもできるし、逆に誰でも見れるように公開もできる。参考までに作成したものはこちらです。
https://my-app11.gitlab.io/test-proto/

以上!

GitHubで編集を提案

Discussion