dbt cloudでCICD環境を構築する

## 何をつくるか
dbt Cloudを利用してCICD環境を構築していきます。
DBはSnowflakeを利用します。

## Snowflakeのロール設計
Snowflakeのロールの構成は下図の通りです。
```mermaid
graph BT
    subgraph USERS
        USER_A
        USER_B
    end

    subgraph FUNCTIONAL ROLE
        FUNCTIONAL_ROLE_DIV_DEVELOP_USERS
        FUNCTIONAL_ROLE_DIV_DEVELOP_MANAGERS
    end

    subgraph ACCESS ROLE
        ACCESS_ROLE_FOR_ENV_DEV 
        ACCESS_ROLE_FOR_ENV_STG
        ACCESS_ROLE_FOR_ENV_PRD
    end

    subgraph Environment
        DB_DEV
        DB_STG
        DB_PRD
    end

    FUNCTIONAL_ROLE_DIV_DEVELOP_USERS --> USER_A
    FUNCTIONAL_ROLE_DIV_DEVELOP_MANAGERS --> USER_B

    FUNCTIONAL_ROLE_DIV_DEVELOP_USERS --> FUNCTIONAL_ROLE_DIV_DEVELOP_MANAGERS
    ACCESS_ROLE_FOR_ENV_PRD --> FUNCTIONAL_ROLE_DIV_DEVELOP_MANAGERS

    ACCESS_ROLE_FOR_ENV_DEV --> FUNCTIONAL_ROLE_DIV_DEVELOP_USERS
    ACCESS_ROLE_FOR_ENV_STG --> FUNCTIONAL_ROLE_DIV_DEVELOP_USERS

    DB_DEV -->|PRIVILEGES| ACCESS_ROLE_FOR_ENV_DEV
    DB_STG -->|PRIVILEGES| ACCESS_ROLE_FOR_ENV_STG
    DB_PRD -->|PRIVILEGES| ACCESS_ROLE_FOR_ENV_PRD
    
```
### Functional Role + Access Role
#### 1. Functional Role + Access Roleとは
公式でも推奨しているFunctional Role と Access Roleのロール構成（※）としています。

※TerraformでFunctional Role と Access Roleの構成を実装した記事もあわせてご覧いただけると嬉しいです。

https://qiita.com/s_rokuemon/items/c013143fca839151f640


#### 2. Access Role
DBを環境ごとに分けそれぞれのDBに充分な権限をもつロールを作成
|環境|ロール名|
|-----|--------------------------------|
|開発環境|ACCESS_ROLE_FOR_ENV_DEV|
|ステージング環境|ACCESS_ROLE_FOR_ENV_STG|
|本環境|ACCESS_ROLE_FOR_ENV_PRD|


#### 3. Functional Role
開発部用のロールを作成しその中で、一般ユーザと管理者を分けてロールを作成
|ユーザ分類|ロール名|
|-----|--------------------------------|
|一般ユーザ|FUNCTIONAL_ROLE_DIV_DEVELOP_USERS|
|管理者|FUNCTIONAL_ROLE_DIV_DEVELOP_MANAGERS|

#### 4. ロールの継承とユーザへのアタッチ(Access Role -> Functional Role -> Users)
* **FUNCTIONAL_ROLE_DIV_DEVELOP_USERS**
    * 開発環境とステージング環境のDBを操作可能なAccess Roleを継承します
    * USER_Aを一般ユーザと定義し、当該ロールをアタッチします
* **FUNCTIONAL_ROLE_DIV_DEVELOP_MANAGERS**
    * ACCESS_ROLE_FOR_ENV_PRDとFUNCTIONAL_ROLE_DIV_DEVELOP_USERSを継承することで、3つ全ての環境のDBにアクセス可能となります
    * USER_Bを管理者ユーザと定義し、当該ロールをアタッチします


## dbt CloudのEnvironmentとJobについて
作成するCICDジョブとデプロイ先の環境に関する構成図は下図の通りです。

```mermaid
graph BT
    subgraph Environment
        subgraph Development
            DB_DEV
        end
        subgraph Deployment
            DB_STG
            DB_PRD
        end
    end
    IDE["IDE"] -->Development
    プルリクエスト作成-->CIJob["Continious Integration Job<br>(CI-Job)"]
    マージ実行-->CDJob["Merge Job<br>(CD-Job)"]

    CIJob-->DB_STG
    CDJob-->DB_PRD

    USER_A --> IDE
    USER_A --> プルリクエスト作成
    USER_B --> マージ実行
```
### dbt Cloudの概念整理
#### 1. Environment type
Environmentは、DWH環境を切り替えるための概念です。
その中にはDevelopmentとDeploymentの二種類がありそれぞれの用途は下記の通りです。
|Environment Type|利用用途|
|-----|--------------------------------|
|Development|dbt Cloud IDEまたはdbt Cloud CLIでコマンドを実行する開発環境。|
|Deployment|定期実行やCICDジョブを実行するデプロイ先の環境|

さらにDeployment Typeには次の3つのタイプが用意されており、後述のジョブ毎に用途を切り替えられます。
|Deployment Type|利用用途|
|-----|--------------------------------|
|General|一般的な環境|
|Staging|ステージング用の環境|
|Production|本番実行用の環境|

<details>
  <summary>図式化するとこのような感じ。</summary>

```mermaid
graph BT;
    subgraph Environment
        subgraph Development
            DEV
        end
        subgraph Deployment
            PRD
            STG
            GENERAL
        end
    end
    
    IDE["IDE"] -->|Credentials参照| Development
    Development --> 開発環境

    Job["Job"] -->|手動設定参照| Deployment
    Deployment --> デプロイ環境

```

</details>

#### 2. Job
ジョブを作成することで、スケジュールや特定のアクションをトリガーとしてコマンドを実行させることができます。

|Job Type|利用用途|
|-----|--------------------------------|
|Continious Integration Job（CI-Job）|・新規のプルリクエストが開いたときに実行されるジョブを設定可能<br>・変更を本番環境にマージする前に、新しいコードをビルドしてテストします|
|Merge Job（CD-Job）|・プルリクエストをmainブランチにマージされたときにジョブがトリガー|
|Deploy Job|・スケジュールまたはイベントによってトリガーされ、クラウド データ プラットフォーム内のプロジェクトに対して dbt コマンドを簡単に実行可能|



<details>
  <summary>図式化するとこのような感じ。</summary>
  
```mermaid
graph BT
    subgraph 環境
        検証環境
        本番環境
    end

プルリクエスト作成-->CIJob["Continious Integration Job<br>(CI-Job)"]
マージ実行-->CDJob["Merge Job<br>(CD-Job)"]
スケジュール実行-->DeployJob["Deploy Job"]

CIJob-->検証環境
CDJob-->本番環境
DeployJob-->本番環境
```

</details>


## 作る
ここではdbt cloud上に作成した環境とジョブについてみていきます。

### 1. Environments
下記に示すように3つ作成しました。
![{BD809A1B-0CC4-44E6-A0FB-8D16041637D4}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833399/1b8b0925-5c6a-4670-6dca-d51d9020c893.png)

例えば、DB_PRDのEnvironmentsでは下図のように設定しています
* Environment typeがDeploymentでDeployment TypeがProductionとなります
![{068E2C9C-405F-412F-8FF5-859ACA26EB2C}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833399/77b9b70f-797a-4bc2-05ec-c12337b1c676.png)


#### 1-1. connection
Environmentsで作成した3つの環境はそれぞれ、Snowflakeの開発、ステージング、本番用のDBとの接続情報を設定しています。
![{3F4171F2-2F86-4938-969A-F37C04A0CDEF}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833399/29bb9d0c-80d2-08c4-11cf-dd4124edb5d7.png)

### 2. Job
ジョブの構成はステージング環境に実行するCIジョブと、本番環境に実行するCDジョブの2つです。
![{69B1A82C-90EB-4565-A517-99DB1987A60A}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833399/068b8a83-6fe3-0cc6-8e2a-59da998b1d49.png)

#### 2-1. CI Job
キャプチャの通り、接続先の環境はステージングDBで、ジョブのトリガーはプルリクエストが作成されたタイミングとなっています。
![{32BBC14E-0B2C-4687-88B0-1932055E1EAF}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833399/249a7e58-9553-2800-4002-f61f59654659.png)

#### 2-2. CD Job
図の通り、接続先の環境は本番DBで、ジョブのトリガーはマージ処理が実行されたタイミングとなっています。
![{B817940A-2D54-4242-A844-BD8E29FEA0A3}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833399/b9ab4bbd-1f30-fa4a-6409-a814c63e0b36.png)


## 動かす
### 1. CI Job
dbt CloudのIDEからプルリクエストを出すと、GitHubの画面でdbt jobが実行されている表示が現れます。

![{C0A498CF-B89A-49E0-9F8E-0112217FFBF9}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833399/44ff171c-04e4-bab1-6088-a1301a99e696.png)

成功か否かは、dbt CloudとGitHubの画面両方で確認できます。
![{A93A9382-3C1D-4AA5-9A34-561D345D81C0}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833399/f53bd022-e35d-5eb5-33c4-09256bc65130.png)

![{BCCFB910-2319-4B61-814D-BBF827B078AE}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833399/f0380b9e-ba2b-bdeb-c4c8-0b24be119c07.png)

#### 1-1. 結果
SnowflakeのWebコンソールから、ステージング環境のDBに向けたクエリの実行結果を確認できます。
![{00F188A1-59E7-45E3-99CC-93AF028BF851}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833399/2050c5a4-ece7-9031-5bd2-019dc54207b5.png)

### 2. CD Job
マージ後、CD Jobが実行されます。
![{3334C5E1-E38F-44EA-BF71-101F2AE40149}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833399/4da844c1-7220-1117-fa18-1f7f91cb0e6b.png)

#### 2-1. 結果
Snowflakeのコンソールからも本番DBに向けたクエリが実行されているのがわかります。
ちゃんと実行ユーザも切り替わっていますね。
![{502B4CD8-B4C9-4BB8-8AE8-31E8775B6083}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833399/48bc93ba-a2cb-8cb3-2167-4528de820381.png)


## 最後に
CICD環境を手軽に構築・試すことができました。
手作業によるデプロイの手間とエラーを目の当たりにしてきた人間からすると、たったこれだけのCICD環境でも、そのメリットを存分に感じられる開発となりました。

運用に適した形でCI/CDそれぞれのjob（データテスト含む）をどう構成するか、についてはより知識を深めていきたいと思います。

## スペシャルサンクス
dbt CloudのEnvironmentとjobに関する理解が深まりました！有難うございました。

https://knowledge.insight-lab.co.jp/bi/-dbt-cloud-cicd


## 公式リファレンス
https://docs.getdbt.com/docs/environments-in-dbt

https://docs.getdbt.com/docs/deploy/deployments

https://docs.getdbt.com/docs/deploy/jobs