OpenAPI定義書レビューの効率化: プルリク時にブランチ名をパスとしたURLでプレビューする

2023.09.23

はじめに

OpenAPI定義書のレビュー、どうしていますか?

OpenAPI定義書の修正を含んだコードレビューでは、以下のような方法が一般的かと思います。

  • プルリク作成時にyamlのコードを見る
  • ローカルでソースを取り込み、VSCodeの拡張機能などでプレビューする

今回は作業の手間を減らすため、プルリク作成時にブランチ名をパスとしたURLでAPI定義書のプレビューが見れる構成を作ってみました。

達成したいイメージ

OpneApiToS3Branch

実際の動作を紹介

1. OpenAPI定義書の修正のプルリクを作成

以下のようなOpenAPI定義書の修正を行い、 ブランチ名 feature/add-users でプルリクを作成します。

openapi: 3.0.0
info:
  version: 1.0.0
  title: Sample API
  description: A sample API to illustrate OpenAPI
tags:
  - name: users
    description: User API
paths:
  /users/{id}:
    get:
      tags:
        - users
      description: User情報を取得
      parameters:
        - name: id
          in: path
          description: User ID
          required: true
          schema:
            type: string
            example: 80eee574-d798-a7b7-2292-855fa19e8fc5
      responses:
        "200":
          description: Successful response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/User"
+  /users:
+   get:
+     tags:
+       - users
+     description: User情報の一覧を取得
+     responses:
+       "200":
+         description: Successful response
+         content:
+           application/json:
+             schema:
+               type: array
+               items:
+                 $ref: "#/components/schemas/User"
components:
  schemas:
    User:
      type: object
      properties:
        id:
          type: string
          description: User ID
          example: 80eee574-d798-a7b7-2292-855fa19e8fc5
        name:
          type: string
          description: User Name
          example: John Doe
        email:
          type: string
          description: User email
          example: john.doe@example.email.jp
        age:
          type: number
          description: User age
          example: 21

2. ブランチ名のURLパスにOpenAPI定義書のプレビューが見れる

以下画像のように、ブランチ名のパスでプルリクで修正後のOpenAPI定義書を見ることが出来ます。

OpenAPI-users

3. ブランチ削除後は該当ブランチ名のOpenAPI定義書が削除される

GitHub リポジトリ側の設定で、マージ後に自動でブランチが削除されるようにしておきます。

マージ後ブランチが削除されると、該当のOpenAPI定義書が削除されアクセスできなくなります。

AccessDenied

実装

実装についても軽く紹介します。

今回のソースは以下リポジトリにあげてあります。

GitHub Actionsのワークフローの実装

以下の3つを実装しました。

  • メインブランチにプッシュされた際にOpenAPI定義書をアップロードする
  • プルリク作成時にOpenAPI定義書をアップロードする
  • ブランチ削除時にOpenAPI定義書を削除する

こちらのソースを少し解説。プルリク作成時にOpenAPI定義書をアップロードする

ブランチ名のS3にアップロードするGitHub ワークフローの全体です。

name: Upload Open API to S3 with branch name
on:
  pull_request_target:
    branches:
      - main
    paths:
      - "design/**"

jobs:
  upload-open-api-to-s3:
    permissions:
      id-token: write
      contents: read
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: ./design
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.head_ref }}
      - uses: actions/setup-node@v3
        with:
          node-version: 20
      - name: Install dependencies
        run: npm ci
      - name: Build Open API
        run: npm run build
      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/${{ secrets.AWS_ROLE_NAME }}
          aws-region: "${{ vars.AWS_REGION }}"
      - name: Upload Open API to S3
        run: |
          aws s3 cp ./dist/index.html s3://${{ secrets.S3_BUCKET_NAME }}/${{ github.head_ref }}/index.html
on:
  pull_request_target:
    branches:
      - main
    paths:
      - "design/**"

メインブランチへのプルリクのみを対象にします。また、 design 配下に変更があった場合のみ実行するようになっています。

      - uses: actions/checkout@v4
        with:
          ref: ${{ github.head_ref }}

actions/checkout@4 でワークフローの作業ブランチを指定しています。

変更したOpenAPI定義書をアップロードしたいので、作業ブランチをプルリク作成側のブランチにしています。

github.head_ref について: https://docs.github.com/ja/actions/learn-github-actions/contexts#github-context

AWSの構成

CDKでインフラを作成しました。

CloudFront, S3 の一般的な構成です。

こちらも軽く紹介。

import { CloudFrontToS3 } from "@aws-solutions-constructs/aws-cloudfront-s3";

const cloudFrontAndS3 = new CloudFrontToS3(this, "CloudFrontToS3", {
  bucketProps: {
    removalPolicy: cdk.RemovalPolicy.DESTROY,
  },
  cloudFrontDistributionProps: {
    cachePolicy: {
      defaultTtl: cdk.Duration.seconds(0),
    },
  },
  // NOTE: redocから生成されるhtmlが cdnのscript, inline style を使っており、セキュリティヘッダを付与していると弾かれてしまうため無効化
  insertHttpSecurityHeaders: false,
});

@aws-solutions-constructs/aws-cloudfront-s3 を初めて使ってみました。

その他

  • 久しぶりにスナップショットテストを試したいのでついでに入れてみた
  • npm workspaces で monorepo 構成を試してみた
  • HTML生成をredoc-cliで行っているが、普段 VSCode でSwagger UIを使っているので、そちらで生成してみたかったが方法が分からなかったため断念
  • S3のみで静的ウェブサイトホスティングをしてIP制限を掛ける構成でも良かったが、CloudFront FunctionでBasic認証をかけた方が良さそうなので、S3のみでの構成とはしなかった

感想

使った技術に目新しいものは無いですが、GitHub Actions と少し仲良くなれた気がします。

もし利用した方がいたら、感想教えてくれると嬉しいです!