Safie Engineers' Blog!

Safieのエンジニアが書くブログです

コードドキュメントの作成をGitHub ActionsとDoxygenで自動化する

はじめに

こんにちは。AI Vision グループでリードエンジニアを務めている橋本です。この記事では、コードドキュメントの生成を GitHub ActionsDoxygen で自動化することで、手間をかけずにドキュメントを作成する仕組みを紹介したいと思います。以下のスクリーンショットは作成するドキュメントのイメージです。今回はC++で実装されたアプリケーションを対象に実施していますが、その他の言語であってもこの手法が参考になると思います。

みなさんは、ドキュメントが整備されておらず、コードの理解や、チームメンバーとのコミュニケーションに難しさを感じたことはありませんか?例えば、新たにプロジェクトに配属され、適切なドキュメントがないために既存の実装を解読しなくてはならず、キャッチアップに骨が折れる思いをしたなど。

そんなときに、ドキュメントが整備されていると、コードの理解がとても容易になります。実装仕様書などのドキュメントを別途作成することもできますが、コードは更新したのにドキュメントの更新を忘れてしまい、実装とドキュメントが乖離するいった問題が発生しがちです。また、毎回手作業でドキュメントを更新するのは面倒ですね。

そこで、ソースコードから自動的にドキュメントを生成するDoxygenというツールを使うと効率的です。Doxygen は、C++、Java、Python等、多数の言語をサポートし、コード内のコメントを抽出して、構造化された形式で参照ドキュメントを生成することができます。ドキュメントには、クラスやメソッドの使用方法、インターフェース、クラスの継承関係、ヘッダファイルの依存関係、コールグラフなどを含めることができます。

ソースコードから自動的にドキュメントを生成すると、最新のコードと対応したドキュメントが常に維持できるのでとても便利です。コードとドキュメント(docstring)が一体になっているので、コードレビューと同時にドキュメントがチェックできるという利点もあります。

今回の自動化で処理される内容は、次の通りです。

  • ブランチがmainにマージされたことをトリガーにして GitHub Actions workflow を起動する
  • Doxygen を使ってソースからHTMLを生成する
  • 生成した HTML を AWS S3 にアップロードし、S3の静的webサイトのホスティングを利用して公開する

次のセクションから、構築手順を具体的に説明していきます。

Doxygen実行用コンテナの作成

このセクションでは、Doxygen を実行してHTMLを生成するDockerコンテナの作成について説明します。Dockerfile は こちら から閲覧できます。

はじめに、必要なaptパッケージをインストールします。Doxygenでグラフを描画するために、graphviz パッケージが必要です。

# Install apt packages
RUN apt-get update && apt-get install -y --no-install-recommends \
    graphviz wget git make \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

次に、Doxygen をインストールします。今回は、Ubuntu 22.04 LTS のパッケージリポジトリでインストール可能な最新バージョン 1.9.1 ではなく、より新しいバージョン 1.9.3 をGitHubから直接取得しています。Doxygen 1.9.1 では、一部の可視化(数式、ツリー表示)が非対応となっているので、ここでは1.9.3を選択しています。

# Install Doxygen 1.9.3
RUN wget -q --no-check-certificate \
    https://github.com/doxygen/doxygen/releases/download/Release_1_9_3/doxygen-1.9.3.linux.bin.tar.gz \
    && tar -zxvf doxygen-1.9.3.linux.bin.tar.gz \
    && cd doxygen-1.9.3 && make install && cd .. \
    && rm -r doxygen-1.9.3.linux.bin.tar.gz doxygen-1.9.3

最後に、カスタム CSS をクローンします。カスタムCSSを適用することで、モダンでオシャレなドキュメントを生成することが可能です。ここでは、doxygen-awesome-css を利用します。

# Clone CSS for Doxygen
RUN git config --global http.sslVerify false \
    && git clone https://github.com/jothepro/doxygen-awesome-css.git

Dockerfile を使用してイメージをビルドし、作成したイメージを ECR にプッシュします。

AWS S3を使った静的ウェブサイトのホスティング

このセクションでは、生成したHTMLドキュメントをS3にホストする方法について説明します。

S3バケットを新しく作成し、静的ウェブサイトホスティングの設定に移動し、次のように設定を行います。記載されていない項目についてはデフォルトのままで問題ありません。

設定項目
静的ウェブサイトホスティング 有効にする
ホスティングタイプ 静的ウェブサイトをホストする
インデックスドキュメント index.html

次に、アクセス許可の設定をします。今回は、社内ネットワークからのみ閲覧できるようにするため、特定のIPアドレスからのみ明示的にアクセスを許可し、それ以外のIPアドレスからは暗黙に拒否するようにします。以下のJSONをバケットポリシーとして適用します。

{
    "Version": "2012-10-17",
    "Id": "AccessToDoxygenBucket",
    "Statement": [
        {
            "Sid": "AllowIP",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::your-doxygen-bucket",
                "arn:aws:s3:::your-doxygen-bucket/*"
            ],
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": "xxx.xxx.xxx.xxx/xx"
                }
            }
        }
    ]
}

バケットポリシーの設定が完了したら、ブロックパブリックアクセスの設定に移動し、「パブリックアクセスをすべてブロック」のチェックを外すことで、バケットへのパブリックアクセスを許可します。これで、webサイトを公開するための設定は完了です。

次に、GitHub Actions が ECRからDockerイメージをpullできるように、以下のようにポリシーを作成します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowECRAuthorization",
            "Effect": "Allow",
            "Action": [
                "ecr:GetAuthorizationToken"
            ],
            "Resource": "*"
        },
        {
            "Sid": "AllowPullFromECR",
            "Effect": "Allow",
            "Action": "ecr:*",
            "Resource": "arn:aws:ecr:your-region-name:xxxxxxxxxxxx:repository/your-repos-name"
        }
    ]
}

加えて、GitHub Actions が S3にリソースをアップロードするためのポリシーも作成します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowS3Sync",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:ListBucket",
                "s3:DeleteObject",
                "s3:GetBucketLocation"
            ],
            "Resource": [
                "arn:aws:s3:::your-doxygen-bucket/*",
                "arn:aws:s3:::your-doxygen-bucket"
            ]
        }
    ]
}

上記で作成した2つのポリシーをIAMロールにアタッチします。IAMロールのARNを次のセクションで説明する GitHub Actions workflow で使用します。

GitHub Actions

このセクションでは、GitHub Actions の処理について説明します。ここで紹介するスクリプトはこちらから閲覧できます。

まず、GitHubのworkflow が実行される条件を設定します。今回は、featureブランチがmain ブランチにマージされたときに実行したいため、push をイベントトリガーに設定します。また、featureブランチの変更を一時的に確認することをを想定して、手動でイベントをトリガーできるように workflow_dispatch も設定します。

on:
  push: 
    branches:
      - main
  workflow_dispatch:

続いて、ジョブの定義を行います。OpenID Connect トークンを発行し、それを用いてAWSの認証を行うため、id-token スコープには write 権限が必要です。また、contents スコープについては、read 権限があれば十分です。

jobs:
  doxygen:
    permissions:
      id-token: write
      contents: read

ここからは、steps の内容を順番に見ていきましょう。リポジトリのチェックアウト、AWSとECRの認証を済ませ、Docker イメージのpull や S3へのアップロードを行う準備をします。

   steps:
     - name: Checkout
       uses: actions/checkout@v3

     - name: Configure AWS credentials 
       uses: aws-actions/configure-aws-credentials@v2
       with:
         aws-region: your-aws-region
           role-to-assume: ${{ secrets.YOUR_ARN_FOR_DOXYGEN_ROLE }}
               role-session-name: PublishDocsWithDoxygen

     - name: Login to ECR
       id: login-ecr
       uses: aws-actions/amazon-ecr-login@v1

次の、Pull image ステップでは、ECRから Docker イメージを取得します。このときのイメージ名と場所は環境変数で定義されています。取得したイメージ名を後続の処理で利用するため $GITHUB_OUTPUT ファイルに追加しておきます。

    - name: Pull image
      id: pull_image
      env:
        ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
        ECR_REPOSITORY: $YOUR_ECR_REPOSITORY_NAME
        IMAGE_NAME: $ECR_REGISTRY/$ECR_REPOSITORY:latest
      run: |
        docker pull ${{ env.IMAGE_NAME }}
        echo "IMAGE_NAME=${{ env.IMAGE_NAME }}" >> $GITHUB_OUTPUT

その次の、Build document ステップでは、Doxygenを実行してHTMLを生成します。

    - name: Pull image
      id: pull_image
      env:
        ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
        ECR_REPOSITORY: $YOUR_ECR_REPOSITORY_NAME
        IMAGE_NAME: $ECR_REGISTRY/$ECR_REPOSITORY:latest
      run: |
        docker pull ${{ env.IMAGE_NAME }}
        echo "IMAGE_NAME=${{ env.IMAGE_NAME }}" >> $GITHUB_OUTPUT

ここでは、カレントディレクトリが your-repo-name となっているため、一つ上のディレクトリに移動し、ディレクトリ構造を次のように整形します。リポジトリで管理しているDoxyfile(Doxygen設定ファイル)とリポジトリのロゴ(.png)をリポジトリと並列になるように移動します。

.
├── repo_logo.png   # リポジトリのロゴ
├── Doxyfile        # Doxygen設定ファイル
└── your-repo-name  # チェックアウトしたリポジトリ

ホストのディレクトリ構造が準備ができたら、Dockerコンテナを起動して doxygenを実行します。カレントディレクトリをコンテナにマウントすると、コンテナのディレクトリ構造は次のようになります。Doxygenを実行すると、HTMLが /workspace/data/html 配下に生成されるようにDoxyfileで出力先を設定しています。

/workspace
├── data
│   ├── repo_logo.png   # リポジトリのロゴ
│   ├── Doxyfile        # Doxygenの設定ファイル
│   └── your-repo-name  # チェックアウトしたリポジトリ
└── doxygen-awesome-css # カスタムCSS

最後のステップとして、生成したドキュメントをS3にアップロードします。

     - name: Push document
       run: |
          cd ..
          aws s3 sync --delete --region ap-northeast-1 ./html s3://repo-document/

むすび

この記事では、GitHub Actions と Doxygen を活用し、コードドキュメントを自動生成する方法を詳細に解説しました。使用したスクリプトは、こちらで公開していますのでご活用ください。また、出力されるドキュメントの例としては、Doxygen Awesome の Examples が参考になると思います。

紹介した方法によって、コードの理解が容易になるほか、ドキュメンテーションの維持管理も効率化できるため、開発チームがコーディングにより多くの時間を割くことが可能になり、製品開発のスピードと品質が向上することを期待しています。今後も、さまざまなツールや技術を活用した結果を紹介できればと思います。

© Safie Inc.