API仕様を展開する方法について考える

# はじめに
本記事は、Swaggerにて作成したOpanAPI仕様を展開する方法について考えた時のメモです。

# 用語解説
SwaggerとOpenapiについて簡単に解説します。
## Swagger
Swaggerは、RESTful APIの設計、開発、ドキュメント化を支援するオープンソースツール群です。
以下のようなツールがあります。

https://swagger.io/

* Swagger Editor
API仕様を作成・編集するツール
* Swagger UI
API仕様をビジュアル化してインタラクティブに操作可能なドキュメントを生成
* Swagger Codegen
API仕様からサーバーやクライアントコードを自動生成
* SwaggerHub
API設計とコラボレーションのためのクラウドプラットフォーム。

個人的に一番なじみのあるのは、"Swagger Editor"と"Swagger UI"です。

## OpenAPI
RESTful APIを記述するための標準フォーマットです。
APIのエンドポイント、リクエスト/レスポンス、認証などをYAMLやJSON形式で定義できます。

# 利用する上でのメリット／デメリット

## メリット
* フォーマットを統一できる
* YAMLやJSONで定義可能なため、バージョン管理が容易
* 開発効率向上（Swagger Codegenのようにコードを自動生成できるようなツールの利用が可能）

## デメリット
* 学習コストがかかる
* RESTful APIに特化しているため、GraphQLやgRPCなどの別のAPIモデルには適用しづらい

## 個人的な所感
自分で調べていく中で、"学習コスト"がかかる。という部分が一番課題になると思いました。
API開発する側も、利用する側もOpenapi仕様を理解していればなんの問題もないのですが、
そうでない場合もあるのではないでしょうか。
そのために、Swagger UIのようなツールがあると感じています。

# 展開する方法について考える
前置きが長くなりましたが、ではどうやって一番のデメリットと感じている"学習コストがかかる"部分に対応していくのか考えたいと思います。
Swagger UIを使うという方法も一案としてあると思うのですが、手っ取り早く展開できる方法を考えてみました。
私が考えた方法は **Redocly CLI**を利用する方法です。

## Redocly CLI
OpenAPI仕様に基づいた静的HTML形式のAPIドキュメントを生成するためのCLIツールです。

https://redocly.com/docs/cli

こんな感じで静的なHTML形式のAPIドキュメントを生成してくれます。
<img width="700" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2638718/7273ad14-01b6-6e0c-235e-a0de9b14392c.png">

https://redocly.github.io/redoc/

:::note warn
検索するとよく"redoc-cli"というのが出てきますが、現在こちらは非推奨になっているので注意してください。
https://www.npmjs.com/package/redoc-cli
:::

ローカルで利用する場合は、このコマンド１つで利用できます。

```Bash
# --output は指定せずとも利用できます
npx @redocly/cli build-docs (YAMLファイル名) --output (出力先ファイル名)
```
:::note warn
前提として、NodeJSのインストールは必要です。
ここでは本題とそれるので割愛します。
:::

## AzurePipelineとの組み合わせ
とはいえ、ローカルで設計書更新するたびに、いちいちコマンド実行するのは面戸くさいと思います。
そこで、私は最近利用しているAzurePipelineでHTML生成から保存までできないか考えてみました。
絵にするとこんな感じです。
※今回は6と7の手順にフォーカスして解説します。
<img width="700" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2638718/ee0ca079-8255-d33d-eb92-a59bee376a5e.png">

**HTML化する仕様**
```YAML
openapi: 3.0.0
info:
  version: 1.0.0
  title: Swagger sample
paths:
  /users:
    get:
      summary: Usersを取得するAPIです。
      responses:
        '200':
          description: HTTPステータスコード200と以下の情報を含むJSONオブジェクトを返します。
          content:
            application/json:
              schema:
                type: object
                properties:
                  user_id:
                    type: string
                    example: 1234567
```

**実行するPipeline**
```YAML
trigger:
  branches:
    include:
      - main # mainブランチに変更があった場合にパイプラインを実行

pool:
  vmImage: 'ubuntu-latest'

steps:
  # Node.jsのセットアップ
  - task: NodeTool@0
    displayName: 'Install Node.js'
    inputs:
      versionSpec: '22.13.0' # 使用するNode.jsのバージョンを指定
  
  # ドキュメント生成
  - task: Bash@3
    displayName: 'Generate Documentation'
    inputs:
      targetType: 'inline'
      script: |
        cd $(Build.SourcesDirectory)/docs # ドキュメントのディレクトリに移動
        npx @redocly/cli build-docs demo-api.yml --output $(Agent.TempDirectory)/demo-api.html # ドキュメントを生成
        cp -r $(Agent.TempDirectory)/demo-api.html $(Build.ArtifactStagingDirectory)/demo-api.html # 生成したドキュメントをArtifactStagingDirectoryにコピー
        echo "Documentation generated"

  - task: PublishBuildArtifacts@1 # ドキュメントをアーティファクトとして公開
    displayName: 'Publish pipeline artifact'
    inputs:
      PathtoPublish: '$(Build.ArtifactStagingDirectory)' # 公開するファイルのパス
      ArtifactName: 'export-doc' # アーティファクト名
      publishLocation: 'Container' #成果物の公開場所
```

こうすることで、mainブランチへのPUSH or MARGEの際にpipelineを動かして、
HTMLドキュメントを生成することができます。

実際に動かした結果は以下の通りです。右側のオプションボタンを押してダウンロードすることができます。
<img width="700" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2638718/585f4e61-1fb6-fe70-5fd4-3a7251c860fb.png">
<img width="700" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2638718/158f8561-86e3-da1f-1654-9583636b6006.png">

**ダウンロードしたHTMLファイル**
<img width="700" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2638718/a50d8610-f543-2fff-4179-16bcaf3611c2.png">

# まとめ
今回は、API仕様を展開する方法について考えてみました。
全員が全員Openapi仕様のYAMLファイルを読み解ければ問題ないですが、実際問題そうはいかないと思います。
今回の手順を使って、HTMLを作成すれば展開も容易になるのではと思いました。
また、こういったツールが利用できるところも、標準フォーマットで記述することのメリットにもなるとも感じました。

# 参考URL
* https://swagger.io/
* https://redocly.com/docs/cli
* https://redocly.com/docs/cli/commands/build-docs
* https://redocly.github.io/redoc/
* https://learn.microsoft.com/en-us/azure/devops/pipelines/tasks/reference/publish-build-artifacts-v1?view=azure-pipelines&viewFallbackFrom=azure-devops