Open API Specification (OAS) をCircleCI経由でherokuにデプロイする

## はじめに
APIドキュメントを`Open API Specification v3`（以下、`OAS v３`）形式で書く機会が増えてきました。
当記事では、`OAS v３`形式で書いたAPIドキュメントを`github`にプッシュするだけで自動デプロイして限られたメンバーで共有する方法を紹介します。

## tl;dr
- ボイラープレート（[imunew/oas-boilerplate](https://github.com/imunew/oas-boilerplate)）を作ったので、そのポイントを解説します
- [swagpack](https://www.npmjs.com/package/swagpack)にて、`OAS v３`形式のファイルを生成
- [swaggerapi/swagger-ui](https://hub.docker.com/r/swaggerapi/swagger-ui/) にて、`Swagger-UI`によるAPIドキュメントを生成
- 生成されたHTMLファイルを`public`ディレクトリにて保持
- `public`ディレクトリを含めて`github`にプッシュすると、`CircleCI`経由で、`heroku`にデプロイされる

## ボイラープレートのディレクトリ構成
ディレクトリは以下のような感じです。
`src`配下のソースファイルがビルドされ、`public`配下にドキュメントが生成されます。

```
├── public
├── src
│   ├── components
│   │   ├── examples
│   │   │   └── index.yml
│   │   ├── schemas
│   │   │   └── index.yml
│   │   └── index.yml
│   ├── paths
│   │   └── index.yml
│   └── index.yml
├── Dockerfile
├── Makefile
├── Procfile
├── README.md
├── docker-compose.yml
├── oas-boilerplate.iml
├── package-lock.json
├── package.json
├── server.js
└── validate.js
```

## `docker-compose.yml`、`Dockerfile`
ローカル環境は、`docker-compose`で構築しています。
以下、ポイントです。

- `swagpack`を使って、`src`配下の`yml`ファイルから`apispec.yml`をビルド
- `swaggerapi/swagger-ui`にて、`Swagger-UI`ドキュメントを表示
- 出力されたHTMLファイルなどは、`public`ディレクトリに出力される

```docker-compose.yml
version: '3'
services:
  swagger-ui:
    image: swaggerapi/swagger-ui
    ports:
      - 3020:8080
    volumes:
      - public_html:/usr/share/nginx/html/
    environment:
      API_URL: ./apispec.yml
    depends_on:
      - swagpack
  swagpack:
    build: .
    volumes:
      - ./src:/app/src
      - ./validate.js:/app/validate.js
      - public_html:/app/dist
    working_dir: /app

volumes:
  public_html:
    driver_opts:
      type: none
      device: $PWD/public
      o: bind
```

```dockerfile
FROM node:10.15.1

WORKDIR /app

RUN yarn init -y
RUN yarn add swagpack@^0.0.5
RUN yarn add oas-validator
RUN yarn add js-yaml

CMD [ "yarn", "run", "swagpack", "build", "./src/index.yml", "-o", "/app/dist/apispec.yml", "-w", "./src" ]
```

## `heroku`で動かすための設定
`heroku`の環境変数にて、BASIC認証のユーザー名（`USER`）とパスワード（`PASS`）を設定しておいてください。

あとは、[heroku-static-provider](https://github.com/nulltask/heroku-static-provider)を参考に、`nodejs`アプリとして、`Swagger-UI`を公開します。

```package.json
{
  "name": "heroku-static-provider",
  "version": "0.0.1",
  "private": true,
  "dependencies": {
    "express": "^3.21.2"
  },
  "scripts": {}
}
```

```server.js
var express = require('express');
var app = express();

var user = process.env.USER;
var pass = process.env.PASS;

app.set('port', process.env.PORT || 3000);

if (user && pass) {
  app.use(express.basicAuth(user, pass));
}

app.use(express.logger('dev'));
app.use(express.compress());
app.use(express.static(__dirname + '/public'));

app.listen(app.get('port'), function() {
  console.log('Server listening on port %s', app.get('port'));
});
```

```
// Profile
web: node server
```

## `CircleCI`からのデプロイ
`CircleCI`の環境変数に以下の変数をセットしておいてください。

- `HEROKU_API_KEY`: `heroku`のAPIキー
- `HEROKU_APP_NAME`: `heroku`アプリの名前

あとは、下記の設定ファイルがあれば、任意のherokuアプリにソースがデプロイされ、`public`ディレクトリ以下が公開されます。

```yml
# .circleci/config.yml
version: 2
jobs:
  deploy:
    docker:
      - image: buildpack-deps:trusty
    steps:
      - checkout
      - run:
          name: Deploy master branch to heroku
          command: |
            git push https://heroku:$HEROKU_API_KEY@git.heroku.com/$HEROKU_APP_NAME.git master
workflows:
  version: 2
  build-deploy:
    jobs:
      - deploy:
          filters:
            branches:
              only: master
```

## 公開イメージ
デプロイされると、BASIC認証付きでアクセスできるようになります。
例えば、以下のようなイメージです。

URL: https://oas-boilerplate.herokuapp.com
BASIC認証: `oas` / `oas`

## おわりに
`OAS v３`でAPIドキュメントを書いて、サーバー・クライアント間のコミュニケーションをスムーズにしましょう。
ではでは。