[dbt] CI(継続的インテグレーション)を取り入れる

人生はContinuous
2021.07.09

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

大阪オフィスの玉井です。

dbtは(基本はSQLとはいえ)コードを開発して実行するツールです。そういう意味では、アプリケーション開発とやることが似ています。故に、dbtには「アプリケーション開発では当たり前にやること」な機能がデフォルトで盛り込まれています。例えば、Gitと連携してコードをバージョン管理することができます。何らかのシステムを開発する際、コードをバージョン管理するのは当たり前のことです。それがdbtにも取り入れられています。

今回紹介するのは、dbt Cloudの「Environment」と「Job」という機能です。これらを使うと、(これまたアプリ開発では当たり前な)「本番環境と開発環境の分割」や「CI(継続的インテグレーション)」を行うことができます。

dbtにおけるCI

そもそもCIとは何でしょうか。例えば下記の記事ではこのように解説しています。

CI/CD の「CI」は継続的インテグレーションを指すのが常で、開発者向けの自動化プロセスを意味します。CI が正常に機能すると、アプリケーションへの新しいコード変更が定期的にビルド、テストされ、共通リポジトリに統合されます。CI により、アプリケーション開発において同時に生じるブランチが多すぎて互いに競合するという問題を解決できます。

これをdbt風に言い直すのであれば、「(CIが正常に機能すると)dbt Projectの新しいデータモデルの変更が定期的にビルド、テストされ、共通リポジトリに統合されます」…といったところでしょうか。

dbt Cloudでは、既存機能を設定するだけで、プリルク時に自動で任意のジョブを走らせることができます。今回は、その機能を使用して、CI環境を設定してみます。

やってみた

環境

  • dbt Cloud v1.1.30.8
  • Snowflake v5.25.0

dbtのProjectには、既にGithub(プライベートリポジトリ)を接続しています。

また、ユーザーレベルでGithubアカウントを認証しています。

データウェアハウス側に開発環境と本番環境をそれぞれ用意する

色々なパターンがあるかと思いますが、今回は、開発者用の個人的なDBと本番用DBの2つを用意します。

開発作業はTAMAI_SANDBOX下で行い(つまり、開発中のデータモデルは全てこのスキーマの中に生成される)、開発を終えたら(プルリクがマージされたら)、DBT_SANDBOX下のPRODスキーマに開発したデータモデルをデプロイする、という流れを想定しています。

dbt側でEnvironmentを設定する

dbt CloudにはEnvironmentという概念があります。その名の通り、開発したデータモデルの実行を行う環境を設定します。後で設定するJobは、このEnvironment単位で実行するため、開発用と本番用にEnvironmentを分けておけば、それぞれ個別にJobを実行することができます。

ちなみに、デフォルトで必ずDevという開発用のEnvironmentが用意されます。このEnvironmentは、Typeがdevelopmentとなっており、実行先は、Projectの作成時に設定したDBやスキーマが使われます。

では、Environment画面を開いて、Environmentの作成画面にいきます。

本番環境用のEnvironmentを設定します。設定は下記のようになりました。Snowflake Connectionという部分で、本番用のDBを指定します。

dbt側でJobを設定する

続いて、Jobを設定します。こちらはイメージしやすいと思いますが、dbt Cloud上で、自動でdbtコマンドを実行させることができます。

Jobの新規作成画面にいきます。

ここで作成するJobが今回のキモなのですが、スケジュール駆動ではなく、(コードが)プルリクされたらdbtコマンドを実行するという設定にします。そして、実行するコマンドにdbt rundbt testを設定します。こうすることで、データモデルの開発や変更が行われる度に、自動で実行とテストが走るため、そのコードが問題ないかどうか非常にチェックしやすくなる=品質向上になります。

また、Jobの実行先として、先程用意したEnvironmentのProdを指定しました。

実際にdbtで開発を行う

それでは、実際に動作を検証してみましょう。

テキトーにデータモデル等を作成してコミット

何でもいいので、コードを書いてコミットしておきます。

プルリクをする

開発を一通り終えたら(コミットし終えたら)、いよいよプルリクします。

Github連携してるので、そのままGithubのプルリク画面にとびます。

プルリクします。

プルリクされました。直後は何も有りませんが…

しばらく画面を見ていると、下記のようになりました。dbtのJobがプルリクを検知してコマンドを実行しています。

特に問題がなければ正常終了の表示がされます。当然、テストが通過しなければ、ここで検知できるので、変なコードをマージしてしまうリスクはかなり減ります。

ちなみに、dbt側でもJobの詳細を確認することができます。

生成されたデータモデルを直接確認する

今回のJobにはdbt runを入れていますが、トリガーを「プルリク時」をしている場合、専用の一時スキーマを作成し、そこにデータモデルを生成してくれます。

つまり、プルリクのレビュー側は、コードだけでなく、そのコードで生成されたデータモデルを(開発者の環境を見に行かずとも)直接確認することができる、というわけです。ドキュメントによれば、マージ後、テンプスキーマは自動で削除されるそうです(私の環境ではまだ残ってますが…)。

本番デプロイについて

CIの導入によって、効率良くデータモデルの開発ができるようになりました。

では、効率良く開発したデータモデルの「本番デプロイ」はどうすればいいのでしょうか(ここでいう本番とは、本番用のDBやスキーマを指します。BIツール等が参照するのも、大抵は本番環境のデータになっていると思います)。

いわゆるCI/CDのCD(継続的デリバリー、デプロイメント)といっていいのか不明ですが、別途、本番デプロイ用のJobを設定することで、本番環境にデータモデルを作成することができます。

本番用のEnvironmentを指定したJobを別途新規作成します。起動トリガーとして、スケジュール起動にするか、手動実行オンリーにするか、等は現場によって異なると思います。

このJobを実行すると、masterブランチのコードを元に、Jobが実行されます。Environmentに設定しているDBとスキーマ下にデータモデルが作成されます(逆にいうと、このJobを実行しない限りは、本番には何の変更も起こらない)。

おわりに

CLI版だと、完全にイチから環境を構築する必要がありますが、Cloud版だと、既存機能だけでCIが実現できるので、非常に楽でした。その代わり、CLI版ほど柔軟な設定はできません。