dbt × BigQueryでCICDパイプラインを実装してみる
dbt CloudとBigQueryで実現するデータ開発のCI/CDパイプライン
dbt(data build tool)は、SQLによるデータ変換を効率化する強力なツールですが、その真の強みは、開発プロセスにソフトウェア開発の手法、特にテスト機構(CI/CDパイプライン)を組み込める点にあります。
しかし、自社ではCI/CDパイプラインを構築しておらず、開発時には気づかなかったエラーが本番環境で見つかるという状態に陥っていました。
そこで、社内でのCI/CDパイプライン構築を提案するため、まずは私用のdbtアカウントで簡単に実装方法を検証しました。
CI/CDとは何か? なぜデータ開発に必要なのか?
CI/CD(Continuous Integration / Continuous Delivery, 継続的インテグレーション/継続的デリバリー)とは、コードの変更を頻繁かつ自動的にビルド、テスト、およびデプロイすることで、開発の効率化と品質の向上を図るソフトウェア開発の手法です。
データ基盤の文脈においては、特に以下の2つのフェーズが重要です。
| フェーズ | 役割 | データ開発における具体的な意味 |
|---|---|---|
| CI (継続的インテグレーション) | 開発者がプルリクエスト(PR)を作成するたびに、自動テストを実行し、問題を早期に検出する。 | データモデルが正しく変換されるか、そしてデータの品質要件(NULLがないか、一意であるかなど)を満たしているかを自動で検証する。 |
| CD (継続的デリバリー) | テスト済みのコードを本番環境へ自動でリリースする。 | CIテストを通過した信頼性の高いデータモデルのみを、手動操作なしでSnowflakeやBigQueryなどの本番データセットに反映し、利用者に提供する。 |
本番環境に反映する前に、エラーやデータ品質の問題に気づけるため、データエンジニアリングの領域で必須のプラクティスです。
前提とプロジェクト準備
■ 前提環境・準備
- dbt: dbt Cloud
- DWH: BigQuery
-
BigQuery内のデータセット:
-
prod: 本番データセット -
dbt_(名前): 個人の開発用データセット(dbt Cloudのデフォルト設定)
-
-
サンプルデータ:
dbt-tutorial.jaffle_shopのパブリックデータを使用。
以下の通り、超シンプルなモデル構成を採用しました。

以下の記事を参考に、dbtとBigQueryの接続、モデルの作成を行いました。
■ 環境の作成と分離
CI/CDを実装する上で、開発・テスト用の設定と、デプロイ用の設定に分けておくことが必要です。
私のdbtプランの制約上、プロジェクトは1つしか作成できないため、1つのプロジェクト内に開発用とデプロイ用の2つの環境(Environment)を作成することで対応します。

Development(開発用、デフォルト)とProduction(本番用、新規作成)
- デフォルトの
Development環境を開発用として使用します。 - 新たに作成する
Production環境を本番用(デプロイ用)とします。
BigQuery側で本番用データセット(例:prod)を作成した後、dbt Cloudの左側バーの Orchestration > Environments から、以下の設定でProduction環境を作成しました。

BigQueryへのConnection情報と、本番環境のデータセット(スキーマ)を指定
CI/CDジョブの作成
環境が整ったので、CIとCDの2つのジョブを作成します。
1. CIジョブの作成 (Continuous Integration)
Orchestration > Environments > + Create Job から 「Continuous Integration Job」 を選択します。これはプルリクエスト(PR)をトリガーとするジョブになります。あとは以下のようにジョブの作成を行います。

CIジョブの設定。Production環境を選択し、PRをトリガーとしている。
-
Environment:
Development環境を選べなかったため、Production(本番環境)を選択しています。しかし、CIの結果はデフォルトでは一時的なスキーマに作成され、かつテストが終われば自動で削除されるため、本番環境のデータに影響はありません。 -
Execution settings:
dbt build --select state:modified+を採用しました。-
--select state:modified+オプションによって、変更されたモデルとその子孫モデルのみを実行します。これにより、ジョブ実行時間が短縮され、BigQueryの使用料(処理スキャン量)も削減できます。
-
-
Compare changes against an environment (Deferral):
Production環境を選択します。- CIテストをする際に、「比較対象となる直前の状態はどれか」を定義します。今回はproduction環境のジョブが最後に「成功」したときの状態を比較対象として使用します。これにより、変更のないテーブルについては、
Production環境の既存のテーブルを参照する(Deferral: 据え置き)ことが可能になります。
- CIテストをする際に、「比較対象となる直前の状態はどれか」を定義します。今回はproduction環境のジョブが最後に「成功」したときの状態を比較対象として使用します。これにより、変更のないテーブルについては、
2. CDジョブの作成 (Continuous Delivery)
CIジョブと同様に + Create Job から 「Merge Job」 を選択します。これはGitHub上でのマージをトリガーとして本番へのデプロイを行うジョブです。

CDジョブの設定。マージをトリガーとし、Production環境にデプロイする。
設定の考え方はCIジョブとほぼ同じですが、こちらはPRではなくマージをトリガーとします。
初回実行とManifestエラーの解決
2つのジョブの設定後、プルリクエスト、マージを行うと、以下のエラーメッセージが出てジョブがスキップされてしまいます。
This job is configured to use the manifest of another job's previous run, which could not be located.

Manifestファイルがないためジョブが実行できないエラー
これは、dbt build --select state:modified+ コマンドが、比較対象となる「前回成功した本番デプロイ時のManifestファイル」をdbt Cloud上にまだ見つけられないことが原因です。
解決策:CDジョブの手動実行
スキップを防ぐには、最初だけCDジョブをdbt Cloudの画面から手動で実行し、成功履歴(Manifestファイル)を作成する必要があります。
- 失敗したCDジョブ(
CD / Production Deploy)を手動で再実行します。 - ジョブが成功すると、
Production環境の成功履歴としてManifestファイルが作成され、dbt Cloud上に保存されます。


初回の手動実行により、Manifestファイルが生成され、本番データセットにモデルがデプロイされた。
パイプラインの動作検証
Manifestファイルの準備ができたので、実際にエラーを検出し、修正してデプロイするCI/CDのフローを検証します。
1. 依存関係エラーの埋め込み
stg_customers.sqlのカラム名を意図的に変更(first_nameという名前からf_nameに変更)し、依存するモデルに影響が出るようにします。

ローカルの開発環境でこのモデルだけを dbt run してもエラーにはなりませんが、依存している customers.sql では古いカラム名を参照し続けるため、全モデルに対して dbt run を実行するとエラーになります。
2. CIジョブによるエラー検出
上記の変更をプルリクエストすると、CIジョブが自動で動き、依存モデルのエラーを検出してくれます。

CIジョブが失敗し、customersモデルでのカラム参照エラーを指摘している。
3. 修正とCD成功
CIジョブのエラーを確認し、customers.sql のカラム名も修正して再度プルリクエストを更新します。
-
customers.sqlのカラム名を修正し、GitHubへプッシュ。 - CIジョブが再実行され、成功。
- CI成功後、GitHubでマージを実行。
- CDジョブが自動実行され、成功。
結果: CIパイプラインによって開発段階でエラーを検出し、修正してから本番環境へデプロイすることができました。これで無事、本番環境にエラーのない状態で、データモデルを反映することができました。


結び
dbt Cloudのジョブと環境設定を組み合わせることで、プロジェクト制限のある無料プランでも、安全で効率的なCI/CDパイプラインを簡単に構築できることが確認できました。
この検証結果をもとに、今後は社内での本格的なCI/CD導入を進め、データ品質と開発スピードの向上を目指します。
(本記事は一部生成AIによって文章の作成を行っております)
Discussion