| @技術/プログラミング
autodoc-generation-flow.png

autodoc を導入して Rails プロジェクトで Request Spec を書くと自動的にドキュメントが更新されるようにした。 autodoc 自体は前々職の頃から利用していて大変お世話になっていた。ただ最初の頃は手元で AUTODOC=1 bundle exec rake spec:requests して手動でドキュメント更新していた。ドキュメントが更新されるかどうかは担当者の心がけ次第なのでよくなかった。

前職では CircleCI を使っていて、デプロイや Asset Precompile など CI でいろいろやるのが当たり前だったので、 Pull Request が Merge されたタイミングでドキュメント生成するように .circleci.yml をカスタマイズしてた。

いま仕事しに行ってるところでは .circleci/config.yml を version 2 にしていて、 version 2 からは workflow の概念が導入されたので、頑張ってシェルスクリプトで条件分岐させたりする必要がなくなった。 .circleci/config.yml は以下のような感じになってる。

version: 2

shared: &shared
  working_directory: ~/app
  docker:
    - image: circleci/ruby:2.4.1-node
      environment:
        PGHOST: 127.0.0.1
        PGUSER: username
        RAILS_ENV: test
        REDIS_HOST: localhost
    - image: circleci/postgres:9.6-alpine
      environment:
        POSTGRES_USER: username
        POSTGRES_PASSWORD: pasword
    - image: redis:3.2-alpine

jobs:
  build:
    <<: *shared
    steps:
      - checkout
      # Restore bundle cache
      - &restore_cache
        type: cache-restore
        key: app-{{ checksum "Gemfile.lock" }}
      # Bundle install dependencies
      - &bundle_install
        run: bundle install -j4 --path vendor/bundle
      # Store bundle cache
      - &save_cache
        type: cache-save
        key: app-{{ checksum "Gemfile.lock" }}
        paths:
            - vendor/bundle
      # Database setup
      - &db_setup
        run:
          name: Database Setup
          command: |
            sudo apt install postgresql-client
            bundle exec rake db:create
            bundle exec rake db:structure:load
      - type: shell
        command: bundle exec rubocop
      # Run rspec in parallel
      - type: shell
        command: |
          mkdir coverage
          COVERAGE=1 bundle exec rspec --profile 10 \
            --format RspecJunitFormatter \
            --out /tmp/test-results/rspec.xml \
            --format progress \
            $(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)
      # Save artifacts
      - type: store_test_results
        path: /tmp/test-results
      - type: store_artifacts
        path: coverage

  generate-doc:
    <<: *shared
    steps:
      - checkout
      - *restore_cache
      - *bundle_install
      - *save_cache
      - *db_setup
      # Generate document
      - type: shell
        command: |
          AUTODOC=1 bundle exec rake spec:requests
      - run:
          name: Setup GitHub
          command: |
            export USERNAME=$(git log --pretty=tformat:%an | head -1)
            export EMAIL=$(git log --pretty=tformat:%ae | head -1)
            git config --global user.email "${EMAIL}"
            git config --global user.name "${USERNAME}"
      - run:
          command: |
            git add doc
            git commit --quiet -m "[ci skip] API document Update

            ${CIRCLE_BUILD_URL}"
            git push origin ${CIRCLE_BRANCH}

workflows:
  version: 2
  build-and-generate-doc:
    jobs:
      - build
      - generate-doc:
          requires:
            - build
          filters:
            branches:
              only:
                - master

master ブランチでのビルドのときだけ generate-doc という job が実行されるようになっている( master ブランチ以外のビルドではドキュメント生成がスキップされる)。buildgenerate-doc で重複してる部分が多いので YAML のアンカー機能を使って重複を整理しているけど結構長い。 generate-doc ジョブでドキュメントが生成されると勝手に GitHub の master ブランチに対して push する。このときコミットメッセージに [ci skip] という文字列を付けておけば、 CircleCI はビルドをスキップするので延々とドキュメントの自動更新ビルドが走り続けることはない。

おかげでいまはテストさえ書けば、実際の API と同じフォーマットのドキュメントが自動生成されるのでとても便利になったと思う。

ちなみに JSON Schema というのもあって、これは JSON に仕様を書くとドキュメントやらモックサーバーを作ってくれるものらしい。めっちゃ便利そうだけど、ちゃんと使うのにはそれなりに仕組みを整える必要がありそうで手を出していない。 autodoc の作者の r7kamura さんのブログにも書いてある通り、 autodoc の便利なところは以下だと思う。

実際にアプリが生成した内容からドキュメントを生成するため、実装とドキュメントの乖離が少なく抑えられる。 また、テストを書くことの見返りが増えるため開発者がテストを書くのを推進しやすい。

全てがJSONになる - ✘╹◡╹✘

autodoc で master ブランチへの Merge をトリガーにしてドキュメントを自動生成するというポリシーでは、 B/E 側の作業中に F/E の人が API のドキュメントを見られなくて不便だという問題は確かに存在する。しかし JSON Schema で事前に仕様を固めて実装前にモックサーバーやドキュメントを提供できたとして、果たして事前に決めたとおりに B/E も F/E も実装できるのだろうか。きっと作っていく途中で「やっぱりアレはコレに変えたい」みたいのが双方から出てくると思う。

↑の r7kamura さんの記事では他に外の API をモックするダミーサーバーを JSON Schema で作ったりしてる。確かにすでに仕様が固まった外部の何かをモックするサーバーのセットアップなどには便利なのかもしれない。ただいまのところは autodoc での後追いドキュメント自動生成で自分は事足りるかなという感じがしている。