話題の記事

私のチームで行っているドキュメント管理方法の紹介(GitHub Actions, S3, AsciiDoc)

2021.07.05

はじめに

私は、開発メンバーが4〜8名、関係者を含めると30名近い規模のチームに所属しています。チームの中でドキュメントを作成し、レビューする環境を構築おり、本記事ではその仕組みを紹介します。

AsciiDocや各種CIツールを組み合わせてドキュメントを管理する仕組みを書いた記事は、既に沢山あります。ただ、各種ツールのインストールやエディタのプレビュー設定、ホスティング設定がまとまった記事がなかったため作成しました。

また本記事は、サーバサイドシステム設計ドキュメント管理を主眼としており、フロントエンドに関しては対象外としています。

前提

  • チーム内でドキュメントを編集する人は、Gitの基本的な操作可能
  • ドキュメントを閲覧のみの人は、Gitの知識不要

採用したツール

ツール 説明/採用理由
GitHub 差分管理を行うために、Gitを利用してリポジトリでドキュメントを管理
GitHub Actions 文法チェック、ドキュメントのデプロイに利用
S3 ドキュメントのホスティングに利用
静的サイトホスティング+IP制御で任意の人が見れるように制御
PlantUML シーケンス図を独自のDSLで記述可 差分管理観点で採用
AsciiDoc/Asciidoctor 静的サイトジェネレータ 後述するPlantUMLの埋め込み 表結合など通常のMarkdownツールより表現が豊かなので採用

ドキュメントツールのインストール(Windows)

Macの場合の設定方法は、本項の後に記載

PowerShellの起動

各種ツールをインストールするため、PowerShellを管理者として実行

  1. Windowsボタンを押下
  2. powershell と入力
  3. 右クリックで管理者として実行 を選択します

img

Chocolateyのインストール

本手順は前述で起動したPowerShellを利用

1.Chocolatey のサイトにアクセスし、インストールコマンドをクリップボードへコピー

img

2.前項でコピーしたコマンドをPowerShellにペーストして実行します

Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))

3.choco --version と入力し、インストールされていることを確認

choco --version

出力を確認

0.10.15

各種ツールのインストール

本手順は前述で起動したPowerShellを利用

1.rubyのインストール

choco install ruby -y

2.graphvizのインストール

choco install graphviz -y

3.correttojdkのインストール

choco install correttojdk -y

4.PATHを読み込み直すため、PowerShellを再起動

5.asciidoctorのインストール

gem install asciidoctor

6.asciidoctor-diagramのインストール

gem install asciidoctor-diagram

7.インストールされていることを確認します

gem list --local | Select-String asciidoctor

出力を確認

asciidoctor (2.0.15)
asciidoctor-diagram (2.1.2)
asciidoctor-diagram-ditaamini (1.0.0)
asciidoctor-diagram-plantuml (1.2021.8)

Windowsの場合のツールのインストール設定は以上

ドキュメントツールのインストール(Mac)

zsh bashTerminalアプリを利用して設定

各種ツールのインストール

1.rubyのインストール

デフォルトインストールされた既存のrubyを利用するため省略

2.brew caskのインストール

brew install cask

3.oracle-jdkのインストール

brew install oracle-jdk --cask

# うまくいかな場合
brew cask install oracle-jdk

4.graphvizのインストール

brew install graphviz

5.asciidoctorのインストール

brew install asciidoctor

6.asciidoctor-diagramのインストール

gem install asciidoctor-diagram

Macの場合のツールのインストール設定は以上です。

Visual Studio Codeのプレビュー設定

1.Visual Studio Code(以降VSCode)がない場合、インストールします

windowsの場合

choco install vscode -y

デスクトップにVSCodeのショートカットが作成されます。起動して、以下の手順を行ってください

Macの場合

brew install visual-studio-code --cask
# うまくいかな場合
brew cask install visual-studio-code

2.VSCodeのAsciidocプレビュープラグインのインストール

本手順以降は基本的にWindows/Mac同じ手順となります

赤枠を押下 img

検索窓にjoaompinto.asciidoctor-vscode と入力。install ボタンを押下 img

3.Asciidocプラグインの設定

VSCodeで、Ctrl + Shift + P(Macの場合Command + Shift + P)を押すと検索窓が開く > 検索窓にOpen Settings 入力 > Preferences: Open Settings(JSON) を選択し、settings.jsonを開きます img img

下記の行を追記してください

{
  "asciidoc.asciidoctor_command": "asciidoctor -r asciidoctor-diagram",
  "asciidoc.preview.useEditorStyle": false,
  "asciidoc.use_asciidoctor_js": false,
}

4.動作確認

下記内容が記載されたファイル(今回はtest.adocとします)を作成し、VSCodeで開きます

== asciidocテスト

[plantuml]
----
@startuml
Bob -> Alice : hello
@enduml
----

img

Ctr + Shift + P(Macの場合Command + Shift + P)を押すと検索窓が開く > 検索窓にAsciidoc と入力 > AsciiDoc: Open Locked Preview to the Side を選択 img

プレビュー出来ていることを確認 img

ドキュメントのコードハイライト設定

基本使わない人多いと思いますので、本章はスルー推奨です。 AsciiDocは、highlightjsに対応しています。highlightjs.orgからhighlight.zipをDL、解凍、highlight/highlight.min.jshighlight/styles/github.min.cssをドキュメントのあるディクレトリに配置

└─ highlight
    ├── highlight.min.js
    └── styles
        └── github.min.css

対象のAsciidocに、相対パスで下記の設定を入れることでコードハイライト可能

:source-highlighter: highlightjs
:highlightjsdir: ./highlight

ハイライト設定をすると下記のような見た目になります ※ 例はVimScriptです img

ドキュメントのホスティング設定

大まかな流れ

  • 1 編集者がドキュメントを編集しコミット、プッシュ
  • 2 GitHub Actionsが起動
    • 2.1 権限のあるIAM Roleに対してassume-role
    • 2.2 AsciiDocをビルド
    • 2.3 ビルド資材(HTML)をS3へアップロード

ディレクトリ構成

リポジトリのディレクトリ構成は下記となります。それぞれ説明を後述します。

.
├── .github
│  ├── actions
│  │   └── asciidoc           // コンテナアクション定義
│  │       ├── Dockerfile
│  │       ├── action.yml
│  │       └── entrypoint.sh
│  └── workflows    
│      ├── reviewdog.yml      // reviewdog/textlint設定
│      └── deploy.yml         // デプロイ設定
├── documents                 // 管理するドキュメント一式を格納するディレクトリ(AsciiDoc)
│   └── document.adoc
└─ highlight                  // コードハイライトする場合
    ├── highlight.min.js
    └── styles
        └── github.min.css

GitHub Actions設定

アクション定義

AsciiDocのビルドには、GitHub ActionsのDockerコンテナアクションを利用。 サードパーティ製のアクションを幾つか試したのですが、フォント周りで期待通りにならなかったため、利用することにしました。

.github/actions/asciidoc/Dockerfile
FROM asciidoctor/docker-asciidoctor:1.2.0

RUN apk add --no-cache nodejs yarn python3 jq git py3-pip && \
  pip3 install --upgrade pip && \
  pip3 install awscli && \
  wget -O VLGothic.zip "http://osdn.jp/frs/redir.php?m=jaist&f=%2Fvlgothic%2F62375%2FVLGothic-20141206.zip" && \
  unzip VLGothic.zip && \
  mkdir -p /usr/share/fonts/VLGothic && \
  cp VLGothic/VL-Gothic-Regular.ttf /usr/share/fonts/VLGothic && \
  gem install asciidoctor-pdf-cjk-kai_gen_gothic && \
  asciidoctor-pdf-cjk-kai_gen_gothic-install

COPY entrypoint.sh /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]
.github/actions/asciidoc/action.yml
name: 'asciidoc'
description: 'build asciidoc'
inputs:
  command:
    description: 'build commands'
    required: true
runs:
  using: 'docker'
  image: 'Dockerfile'
  args:
    - ${{ inputs.command }}
.github/actions/asciidoc/entrypoint.sh
#!/bin/bash

bash -c "$@"

ワークフロー定義(デプロイ)

ビルドされたAsciiDocは、ブランチによってS3の格納場所を変更しています。これは、チームで合意したドキュメントと、プレビュー段階のドキュメントを分ける意図があります。

mainブランチの場合

  • http://{バケット名}.s3-website-ap-northeast-1.amazonaws.com/{プロジェクト名}/main/index.html

mainブランチ以外の場合

  • 常にブランチの最新が見れるリンク
    • http://{バケット名}.s3-website-ap-northeast-1.amazonaws.com/{プロジェクト名}/{ブランチ名}/head/index.html
  • 過去のバックナンバーが見れるリンク(全く活用していない...
    • http://{バケット名}.s3-website-ap-northeast-1.amazonaws.com/{プロジェクト名}/{ブランチ名}/{コミットハッシュ}/index.html

ビルド方法やS3へのアップロード方法の詳細は、下記のコードを参考にしてください

.github/workflows/deploy.yml
name: Deploy
env:
  PROJECT_NAME: document
  TZ: 'Asia/Tokyo'
on: [push]
jobs:
  deploy:
    name: Deploy
    runs-on: ubuntu-latest
    timeout-minutes: 5
    env:
      AWS_DEFAULT_REGION: ap-northeast-1
      AWS_ACCOUNT_ID: xxxxxx
    outputs:
      BRANCH_NAME: ${{ steps.setenv.outputs.BRANCH_NAME }}
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Use Node
        uses: actions/setup-node@v1
        with:
          node-version: "14.x"
      - name: Set enviroment
        id: setenv
        run: echo "::set-output name=BRANCH_NAME::${GITHUB_REF#refs/heads/}"
      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{ env.AWS_DEFAULT_REGION }}
          role-to-assume: xxxxxx
          role-duration-seconds: 3600
          role-session-name: ${{ env.PROJECT_NAME }}-session
          role-skip-session-tagging: true # See https://github.com/aws-actions/configure-aws-credentials#session-tagging
      - name: Build asciidoc
        uses: ./.github/actions/asciidoc
        with:
          command: |
            DIST_DIR="$(pwd)/dist"
            DOCUMENT_DIR="documents"

            if [ -d $DIST_DIR/images ]; then rm -Rf $DIST_DIR/images; fi
            mkdir -p $DIST_DIR/images

            for filename in $(find ./documents -type f |cut -d/ -f3- | grep .adoc); do
              asciidoctor \
                -a imagesdir@=images \
                -a imagesoutdir=$DIST_DIR/images \
                -a outdir=$DIST_DIR \
                -o $DIST_DIR/${filename%.*}.html \
                -r asciidoctor-diagram \
                -b html5 \
                $DOCUMENT_DIR/${filename}
            done

      - name: Deploy
        run: |
          if [ ${{ steps.setenv.outputs.BRANCH_NAME }} = "main" ]; then
            aws s3 sync --delete highlight s3://${{ env.PROJECT_NAME }}-${{ env.AWS_ACCOUNT_ID }}/${{ env.PROJECT_NAME }}/highlight/
            aws s3 sync --delete dist s3://${{ env.PROJECT_NAME }}-${{ env.AWS_ACCOUNT_ID }}/${{ env.PROJECT_NAME }}/main/
          else
            commithash=$(git rev-parse --short HEAD)
            aws s3 sync --delete dist s3://${{ env.PROJECT_NAME }}-${{ env.AWS_ACCOUNT_ID }}/${{ env.PROJECT_NAME }}/${{ steps.setenv.outputs.BRANCH_NAME }}/$commithash/
            aws s3 sync --delete dist s3://${{ env.PROJECT_NAME }}-${{ env.AWS_ACCOUNT_ID }}/${{ env.PROJECT_NAME }}/${{ steps.setenv.outputs.BRANCH_NAME }}/head/
          fi

ワークフロー定義(textlint/reviewdog)

textlintとreviewdogで、文言のチェックをしています。こちらは現在ルール調整中なので、別の機会に記事で書きたいと思います。

.github/workflows/reviewdog.yaml
name: 'Run textlint with reviewdog'
on: [pull_request]
jobs:
  textlint:
    runs-on: Ubuntu-latest
    container:
      image: node:current-alpine
      env:
        LEVEL: error
        FLAGS: documents
    steps:
      - uses: actions/checkout@v1
      - name: setup-reviewdog
        run: |
          mkdir -p $HOME/bin && wget -O - -q https://raw.githubusercontent.com/reviewdog/reviewdog/master/install.sh \
            | sh -s -- -b /usr/local/bin/ v0.9.13
          apk --update add git && \
            rm -rf /var/lib/apt/lists/*
      - name: installl-textlint
        run: |
          cd "$GITHUB_WORKSPACE"
          if [ ! -f "$(npm bin)/textlint" ]; then
            npm install
          fi
      - name: run-reviewdog
        env:
          REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          $(npm bin)/textlint -f checkstyle "${FLAGS:-'.'}" \
            | reviewdog -f=checkstyle -name="textlint" -diff="git diff ${{ github.event.pull_request.base.ref }}" -reporter=github-pr-review -level="${LEVEL}"

下記の画像のように、プルリクエストにコメントがつきます。reviewdogを利用すれば、CIが落ちるわけではないので、直さなくてよいところはコメントクローズ、直すべきところに集中でき、非常に便利です。

ドキュメントツールの書き方

Asciidoc

Asciidoctor 文法クイックリファレンス(日本語訳) が参考になります

AsciiDocへのPlantUMLの埋め込みは下記のコードで実現可能です

[plantuml]
----
@startuml
Bob -> Alice : hello
@enduml
----

PlantUML

シーケンス図の構文と機能 - PlantUML が参考になります

最後に

独自定義したアクションは、毎回コンテナにツールを入れている分初期化処理が遅いので、下記の方法で対処することを検討しています(今のところ許容範囲なので、ストレスはありません)

  • ツールインストール済みのイメージをコンテナレジストリにいれ利用
  • self-hosted runnerを利用(毎回同じVMが利用されるので、利用したコンテナがキャッシュされるため)

余談ですが、本記事ではVSCodeでAsciiDocプレビュー方法を紹介しましたが、私は普段Neovimを利用しているため、自作したpreview-asciidoc.nvimを利用してAsciiDocのプレビューをしています。(とりあえず動くレベルでヘルプもVim対応もしていないため、推奨しません)。Vim/Neovim両対応や安定性をあげて作り直したいところです。