Auth0のCI/CDパイプラインをCircleCIを使って作る

## 概要

Auth0の設定やRulesやCustomeDatabaseまわりのソースコードは一元的にGitなどで管理を行い、CircleCIなどでCIを通した上で自動でデプロイしたいケースが多いと思います。特に実案件の本番環境などでは。本記事ではそのやり方をtipsとして書いています。

また、今回の内容は以下のGitHubリポジトリで公開してますので、より詳細を知りたければ確認してみて下さい
https://github.com/infaspublications/auth0-deploy

## Auth0 Deploy CLI
Auth0には[Auth0 Deploy CLI](https://github.com/auth0/auth0-deploy-cli/)というCLIでソースコードや設定のデプロイを行うツールがあります。これを使うことでCI/CDパイプラインを作っていくというわけです。

### インストール
npmで自身のPC環境にインストールを行います。

```
$ npm i -g auth0-deploy-cli
```

### 既存のテナントの設定をコード化する
Auth0 Deploy CLIが便利なのは既存のテナントの設定を抜き取ってyamlの設定やローカルのソースコードツリーに展開してくれることです。

まずは設定を抜き出したいテナント側に[Auth0 Deploy CLI Extension](https://github.com/auth0-extensions/auth0-deploy-cli-extension)をインストールします。これで自動でデプロイ用のアプリケーションを作ってくれます

次にローカルに戻って、以下のような`config.json`ファイルを作り、client_idやclient_secretはAuth0 Deploy CLI Extensionが作ったアプリケーションの値をそれぞれ入れます

```json:config.json
{
  "AUTH0_DOMAIN": "<YOUR_TENANT>.auth0.com",
  "AUTH0_CLIENT_ID": "<client_id>",
  "AUTH0_CLIENT_SECRET": "<client_secret>",
  "AUTH0_KEYWORD_REPLACE_MAPPINGS": {
    "AUTH0_TENANT_NAME": "<NAME>",
    "ENV": "DEV"
 },
  "AUTH0_ALLOW_DELETE": false,
  "AUTH0_EXCLUDED_RULES": [
    "rule-1-name",
    "rule-2-name"
 ]
}
```

そして以下のコマンドを実行しましょう

```
$ a0deploy export -c config.json  -f yaml -o ./
```

すると設定内容がすべてローカルに展開されているはずです。

### tenant.ymlに環境変数を追加する

エクスポートして自動生成された`tenant.yml`ファイルに以下のようなテナントの設定が記述されています。ただ、このファイルをエクスポートしただけの状態だとドメインなどの環境によって変えたい変数がハードコーディングされています。

```yaml:tenant.yaml
tenant:
  enabled_locales:
    - ja
  flags:
    universal_login: true
    new_universal_login_experience_enabled: true
    disable_clickjack_protection_headers: false
  universal_login:
    colors:
      primary: '#000000'
      page_background: '#e1e1e1'
clients:
  - name: mysite
    allowed_clients: []
    allowed_logout_urls:
      - 'http://localhost:8080/auth0/'
    allowed_origins:
      - 'http://localhost:8080'
    app_type: regular_web
    callbacks:
      - 'http://localhost:8080/auth0/'
    client_aliases: []
    cross_origin_auth: false
    custom_login_page_on: true
```

Auth0 Deploy CLIではymlファイル内にて`@@key@@` や `##key##`といった識別子を記載することで環境変数の値を読むことが出来ます。以下のような例です。これでデプロイ時に`SITE_URL`という環境変数の値を読んでデプロイをしてくれます。

```
allowed_logout_urls:
      - 'http://##SITE_URL##/auth0/'
```

## CI/CDパイプラインを構築する
### テストを書く

エクスポートすると`tenant.yml`以外にも、`rules`や`databases`ディレクトリ配下にRulesやCustomeDatabaseの機能で使うソースコードがダウンロードされます。

これらを元にユニットテストを書いてあげましょう。ここは単純なJSのユニットテストテストなので詳細は割愛します

### デプロイ戦略を決める

今回は、GitHubのTagでのリリース機能を使い。Tagを作ってpushすることでテストが走り、全てパスすれば本番のテナントにデプロイが走るという設定をしてみましょう

### デプロイスクリプトを書く

デプロイスクリプトは以下のようなNode.jsのスクリプトを書いてあげます。

```js:deploy.js
const auth0 = require('auth0-deploy-cli')

const config = {
  AUTH0_DOMAIN: process.env.AUTH0_DOMAIN,
  AUTH0_CLIENT_SECRET: process.env.AUTH0_CLIENT_SECRET,
  AUTH0_CLIENT_ID: process.env.AUTH0_CLIENT_ID,
  AUTH0_ALLOW_DELETE: true
}

auth0
  .deploy({
    input_file: 'tenant.yaml',
    config,
    env: process.env
  })
  .then(() => console.log('yey deploy was successful')) // eslint-disable-line no-console
  .catch((err) => console.log(`Oh no, something went wrong. Error: ${err}`)) // eslint-disable-line no-console

```

そして`package.json`に以下の設定をして`npm run deploy`でデプロイできるようにします。

```json:package.json
"scripts": {
  "deploy": "node scripts/deploy.js"
},
```

### CircleCIの設定ファイルを書く

以下のようにすると、Tagが作られたタイミングでテストとデプロイが走ります。Auth0のwebtaskの環境がNode8なのでそれに合わせて8系のコンテナを読んでます。上記のデプロイスクリプト内で呼び出している環境変数はデプロイ先の本番テナントの設定をCirclCIに環境変数として追加してあげましょう

```yaml:.circleci/config.yaml
version: 2
jobs:
  build:
    docker:
      - image: circleci/node:8.11

    working_directory: ~/repo

    steps:
      - checkout

      - restore_cache:
          keys:
          - v1-dependencies-{{ checksum "package.json" }}
          - v1-dependencies-

      - run: npm install

      - save_cache:
          paths:
            - node_modules
          key: v1-dependencies-{{ checksum "package.json" }}

      - run:
          name: Formatting coding standard by prettier
          command: npm run fmt

      - run:
          name: Check coding standard by ESLint
          command: npm run lint

      - run:
          name: Run test
          command: npm run test
  deploy-prod:
    docker:
      - image: circleci/node:8.11

    working_directory: ~/repo
    steps:
      - checkout
      - run: npm install
      - run: npm run deploy

workflows:
  version: 2
  build-deploy:
    jobs:
      - build:
          filters:
            tags:
              only: /.*/
      - deploy-prod:
          requires:
            - build
          filters:
            tags:
              only: /.*/
            branches:
              ignore: /.*/

```

### デプロイの実施

以下でTagをつくります。

```
$ git tag 1.0.0
$ git push origin 1.0.0
```

CircleCIのダッシュボードを見るとうまくデプロイが完了しました！
<img width="598" alt="スクリーンショット 2019-08-05 20.12.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65478/e2fd351f-4236-9f6e-5708-996a80265389.png">