dbt CloudのCIジョブで差分があるmodelだけを実行&テストしてみた #dbt

2022.07.01

さがらです。

dbt CloudのCIジョブで差分があるmodelだけを実行&テストする方法を試してみたので、その内容をまとめてみます。

dbt CloudにおけるCIについて

まず前提として、dbt CloudではCI(継続的インテグレーション)を簡単に設定可能です。詳細は下記ブログをご覧ください。

dbt CloudでのCIの基本的な実装は上記のブログの通りなのですが、CIを担うジョブで実行するコマンドにdbt rundbt testを指定すると、特にコードを変えていないmodelまで実行されてしまい、不要にストレージやコンピュートリソースを使ってしまいます。

この対策として、dbtには差分が発生したmodelだけを実行対象とする機能がありますので、その機能について次章以降で書いていきます。

差分だけを実行するCIジョブの設定方法

事前準備:本番デプロイ用のジョブの設定

差分だけを実行するCIジョブを設定するには、本番デプロイ用のジョブを設定し、一度でも実行しておく必要があります

後で設定するCIジョブは、この本番デプロイ用のジョブにより生成されるArtifactsとの差分を確認する必要があるからです。

下図は私が設定したジョブの内容です。

CIジョブの設定

続いて、CI用のジョブを設定していきます。

CIジョブを設定する時のポイントは3点あります。

DEFER TO PREVIOUS RUN STATE?の設定

まず1つ目、dbt Cloudのジョブの設定にDEFER TO PREVIOUS RUN STATE?という項目があります。

この設定項目で指定したジョブのArtifactと、CIジョブにより生成されるArtifact、この2つの差分を確認できるようになります。 先程、本番デプロイ用のジョブを先に設定して実行したのは、この差分を検知するためです。

設定出来るジョブはドロップダウンのリストで表示されるので、本番デプロイ用のジョブを指定します。

実行するコマンド

次に2つ目、実行するコマンドなのですが、--select state:modified+とオプションを指定する必要があります。

このオプションはどういう意味かというと、

  • state:modifiedにより、先程DEFER TO PREVIOUS RUN STATE?で設定したジョブと差分があるmodelだけを実行対象とする
  • 末尾に+をつけることで、差分があったmodelより下流に位置するmodelも全て実行する

ということが可能になります。

dbt ver1.0.0からbuildが使えるようになったので、dbt build --select state:modified+とCIジョブを指定しておきます。

Pull Requestsが発行されたときに実行するように設定

最後に3つ目、このCIジョブはPull Requestが発行された時のみ実行するようにしたいです。

Pull Request発行➟CIジョブが回る➟問題ないことを確認しPull Request承認➟本番用のブランチにマージ、という一連のプロセスを行うためです。

設定方法としては、TriggersのRUN ON PULL REQUESTS?にチェックを入れればOKです。

この3つの設定が出来たら、Saveを押してジョブを保存します。参考までに、設定したCIジョブの設定全体の画像をポイント3点赤枠で囲んだ上で載せておきます。

実際の挙動

先程設定したCIジョブが上手く動くのか、確認していきます!

対象のmodel

まず、検証に使うのはdbtチュートリアルでも使用するjaffle_shopです。(DWHはSnowflakeで若干カラム構成を変えていますが)

リネージは下図のようになっています。

この時、stg_customers.sqlにだけ、下図のようにlast_nameに対してtrimする処理を入れてみます。

これにより本番環境で動いているジョブとの差分が、生まれました。この上でCIジョブを回してみます。

一度コミットした上で、dbt CloudからPull Requestを開きます。

Pull requestを作ります。

少し時間が経つと、dbt Cloudを介してCIジョブが走ります。

CIジョブが無事に終わると、下図のように表示されます。

ちなみに、接続先のSnowflakeではCIジョブ用のスキーマが作られるのですが、今回変更を行ったstg_customers.sqlとその下流に位置するcustomers.sqlだけが実行されていることがわかると思います。

ここで「あれ、customers.sqlstg_orders.sqlも参照しているはずだけど、大丈夫なの?」と思った方いると思います。私も思いましたw

なんと、変更を加えていないmodelを参照する場合は、DEFER TO PREVIOUS RUN STATE?で指定したジョブ(つまり本番デプロイ用ジョブ)で作成されたテーブルを使用しているのです。上手いこと出来ていますね~。

最後に

DEFER TO PREVIOUS RUN STATE?などの機能を用いて、CIジョブでは変更を加えたmodelだけを実行対象とする方法についてまとめてみました。 この機能を使えば、CIジョブにおけるDWHのストレージとコンピュートリソースの使用を抑えることが出来ますね!

私個人としては「dbt Cloudユーザーはみんな入れるべきでは?」と感じた機能なので、ぜひこの機能を活用していきましょう!