Swaggerをオシャレに公開したい！ on GitLab Pages

# はじめに
この記事は [富士通クラウドテクノロジーズ Advent Calendar 2023](https://qiita.com/advent-calendar/2023/fjct) の 15 日目の記事です。

昨日は @tomonai さんの [Google ColaboratoryでChat GPTをやってみた話](https://qiita.com/tomonai/items/9230c36fb1b93bbebea6) でした。
OpenAIを使ったプログラミングを気軽に試してみたい場合にとても参考になりますね :rocket: 

Swagger(OpenAPI)形式で記述した仕様書をもとに、APIドキュメントをWEB公開する方法の1つを紹介します。
記事の最後にコピペだけで実行可能な状態の`.gitlab-ci.yml`も記載します。

## 成果物

サイト

https://tanopanta.gitlab.io/slate-sample/#books-api

キャプチャ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245298/fdd0c31a-3c27-45b4-8ada-7181a9de1598.png)



## モチベーション
[社内GitLabの大型マイグレーションをした話](https://qiita.com/aokuma/items/1797a233b50a0379aed2) でも紹介されてるようなGitLabにおいて、Pages機能を自チームで何か活用できてないかなと思っていました。

[jamstack.org](https://jamstack.org/generators/) で静的サイトジェネレーターのトレンドをあさっていたところ、[Slate](https://github.com/ianstormtaylor/slate)というAPIに特化したツールがあるようです。ただし利用するにはSlate形式のマークダウンが必要でした。

手元にはSwagger、そして [widdershins](https://github.com/mermade/widdershins) というSwaggerをSlate互換形式に変換するツールも見つけました。

そして出来上がったものがこの記事になります。

# ビルドとデプロイ

## 必要なもの
- Swagger または OpenAPI形式で記述したAPI仕様書
- GitLabのアカウント（gitlab.comの無料アカウントでも可）
  - 以下説明のため各種コマンドを記述していますが、それらの実行は最後に紹介するGitLab のパイプライン上で完結できます

## 静的サイトのビルド
今回はサンプルとして作った[BooksAPIのSwagger](https://gitlab.com/tanopanta/slate-sample/-/blob/main/books-swagger.yaml?ref_type=heads&plain=1)をもとにサイトを作ってみます。

```yaml:books-swagger.yaml
swagger: "2.0"
info:
  version: 1.0.0
  title: Books API
  description: 本の登録を行うAPIです
host: books.example.com
basePath: /v1
schemes:
  - http
consumes:
  - application/json
produces:
  - application/json
paths:
  /books:
    get:
... 省略
```
### 1. Swagger(OpenAPI)をSlate形式に変換
まずはSwagger形式のYAMLをマークダウンに変換します。Node.js製の[widdershins](https://github.com/mermade/widdershins) というツールを使います。
> OpenAPI / Swagger / AsyncAPI / Semoasa definition to Slate / ReSlate compatible markdown

とあるように、ドキュメント生成ツールであるSlateと、互換のある形式にSwaggerを変換できます。

コマンドのオプションは色々とありますが、以下のように入力と出力だけ指定できれば生成できます。

```sh
npm install widdershins
npx widdershins books-swagger.yaml -o generated.slate.md
```

### 2. 静的サイトとして生成
サイト生成には [Slate](https://github.com/slatedocs/slate) を利用します。
StripeやPayPalのAPIドキュメントからインスパイアを受けたとの記述もあり、洗練されたデザインとコードサンプル付きなドキュメントが生成できそうです。

公式ドキュメント [Using-Slate-Natively](https://github.com/slatedocs/slate/wiki/Using-Slate-Natively) が参考になりますが、概要としてはSlateのリポジトリをcloneして、`source/`配下にあるコンテンツをもとに生成するという仕組みです。

#### Slateのclone
まずは先ほど生成したマークダウンを`source/`配下に配置します。Slateはシングルページのため、index.html.mdだけ上書きすれば配置は完了です。

```sh
git clone https://github.com/slatedocs/slate.git
mv generated.slate.md slate/source/index.html.md
```

#### ビルド
マークダウンの配置までできたら、最後に静的サイトとして生成すれば完成です。

方法はいくつかありますが、middleman(Ruby製)でビルドする方法が簡単でした。

以下のようにbundle execすることで`build/`配下に生成できます。 

※ [Using-Slate-Natively](https://github.com/slatedocs/slate/wiki/Using-Slate-Natively)に書いてあるように、OSによっては追加でインストールが必要な依存がある場合もあります。

```sh
cd slate
bundle install
bundle exec middleman build
```

## GitLab Pagesに公開
せっかく生成できたので、WEB上に公開したいです。ホスティングする方法はいくつかありますが、今回ははじめに触れたようにGitLab Pagesで公開してみます。

とは言っても簡単でこの記事に今まで張られているコマンドをCI上で実行すれば終わりです。

具体的にはリポジトリの `.gitlab-ci.yml` に以下のようなジョブを追加します。(リポジトリがない場合はプロジェクトを新規作成し、`.gitlab-ci.yml` とSwagger形式のYAMLをコミットします)

```yaml:.gitlab-ci.yml
pages:
  image: cimg/ruby:3.2-node
  stage: deploy
  variables:
    SWAGGER_PATH: "books-swagger.yaml"
  script:
    # Slate形式に変換
    - npm install widdershins
    - npx widdershins $SWAGGER_PATH  -o generated.slate.md
    # 静的サイトとして生成
    - git clone https://github.com/slatedocs/slate.git
    - mv generated.slate.md slate/source/index.html.md
    - cd slate
    - bundle install
    - bundle exec middleman build
    - mv build ../public
  artifacts:
    paths:
      - public
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
```

ポイントはjob名を`pages`にする点と、`public`という名前でartifactsに登録する点です。

（こだわりポイントとしては、nodeとrubyが必要なので、両方最初から入った [cimg/ruby](https://hub.docker.com/r/cimg/ruby) のnodeタグをイメージとして使った点です）

※ Pages機能の有効化やページの公開範囲は、プロジェクトの Settings -> General で設定できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245298/db80704b-b9bd-58b5-029c-01530efd8827.png)

jobが無事成功したらプロジェクトの左側のペインから`Deploy -> Pages`にいけば、
以下の画像のようにAccess pagesに生成されたURLが記載されています。

※ ここで `Use unique domain` をオフにすればURLが毎jobで固定になります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245298/8dd44bc0-1a50-450a-724a-3f2f8aa18694.png)


## 完成

そしてできたのがこちらになります :rocket: 

https://tanopanta.gitlab.io/slate-sample/#books-api

キャプチャ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245298/fdd0c31a-3c27-45b4-8ada-7181a9de1598.png)

APIドキュメントが無事公開できました！

## 補足

- favicon等カスタマイズしたい場合は [Slateのwiki](https://github.com/slatedocs/slate/wiki) が参考になりそうです。

- 本記事で紹介したBooks APIのドキュメントは以下のリポジトリで生成してますので参考にしていただければ幸いです。
  - https://gitlab.com/tanopanta/slate-sample


# まとめ

この記事は [富士通クラウドテクノロジーズ Advent Calendar 2023](https://qiita.com/advent-calendar/2023/fjct) の 15 日目の記事でした。

今日はAPIドキュメントをWEB公開する方法を紹介しました。
仕事や趣味で開発したAPIドキュメントをサクッとホスティングしたい方は、ぜひ参考にしてください。

明日は @fuku2014 さんの [Terraform小ネタ集](https://qiita.com/fuku2014/items/108d53bf7276cacbb1d3) です。
Terraformでの書き方に悩むこともあると思うのですがそんなときに役立つTipsが知りたい方はぜひご覧ください🤸