BigQueryEmulatorを使ってdbt-coreを動かす検討(monkeypatchを当てて)
dbt-coreでBigQueryを使う時、
BigQuery Emulatorが使えると便利なのですが、
次のPullRequestにあるように利用することができません。(2024年9月時点では)
Allow Bigquery Emulator settings to be set | dbt-labs/dbt-bigquery | GitHub
https://github.com/dbt-labs/dbt-bigquery/pull/1017
BigQuery Emulator | GitHub
https://github.com/goccy/bigquery-emulator
なので、このPullRequestを参考にmonkeypatchを当てて、
動かしてみることを検討してみます。
次のCommitにMonkeyPatchを作成しました。
patch for bigquery emulator | takemikami/dbt-bigquery | GitHub
https://github.com/takemikami/dbt-bigquery/commit/4c84de2e72e876b3c4ed0307c36cfb5a97ac4e75
特に、
GitHubActions上でsqlfluffによるフォーマットチェックだけのために、
GCPの認証を設定するのは避けたいのでEmulatorが使えると便利だと思います。
ひとまず、このエントリで試した範囲では動いてはいるようですが。
細かく試していないですが、
条件によって動かなかったり、できる機能範囲も限られていると思われます。
BigQuery Emulatorを動かす
まずはBigQuery Emulatorを動かしてみます。
以下のBigQueryのREADMEを参照します。
BigQuery Emulator | GitHub
https://github.com/goccy/bigquery-emulator
dockerを使って動かす場合は、
次のコマンドのように起動します。
$ docker pull ghcr.io/goccy/bigquery-emulator:latest
$ docker run -p 9050:9050 -p 9060:9060 -it ghcr.io/goccy/bigquery-emulator:latest --project=test --dataset=dataset1
以下のコマンドのようにして、
BigQueryクライアントから接続確認します。
$ bq --api http://127.0.0.1:9050 query --project_id=test "SELECT 1 as key"
dbtのプロジェクトを作る
動作確認用に、dbtのプロジェクトを作ります。
まずはgitリポジトリを準備して、dbt-bigqueryをインストールします。
$ mkdir dbt-bqemu-study && cd $_
$ git init
$ python -m venv venv
$ . venv/bin/activate
$ pip install dbt-bigquery==1.8.2
dbtの初期化します。
$ dbt init study
Which database would you like to use?
[1] bigquery
(Don't see the one you want? https://docs.getdbt.com/docs/available-adapters)
Enter a number: 1
[1] oauth
[2] service_account
Desired authentication method option (enter a number): 1
project (GCP project id): test
dataset (the name of your dbt dataset): dataset1
threads (1 or more): 1
job_execution_timeout_seconds [300]:
[1] US
[2] EU
Desired location option (enter a number): 1
dbtをBigQuery Emulatorに接続する
次に、dbtをBigQuery Emulatorに接続できるようにします。
MonkeyPatchを当てる
雑ですが、以下のようにMonkeyPatchを当てます。
$ wget https://raw.githubusercontent.com/takemikami/dbt-bigquery/4c84de2e72e876b3c4ed0307c36cfb5a97ac4e75/dbt/adapters/bigquery/connections.py
$ cp connections.py venv/lib/python3.11/site-packages/dbt/adapters/bigquery/
BigQuery Emulatorへの接続を設定する
この状態で、~/.dbt/profiles.yml
は、次のようになっています。
study:
outputs:
dev:
dataset: dataset1
job_execution_timeout_seconds: 300
job_retries: 1
location: US
method: oauth
priority: interactive
project: test
threads: 1
type: bigquery
target: dev
当然、dbt debug
を実行すると接続エラーになります。
$ cd study
$ dbt debug
~/.dbt/profiles.yml
を、次のように変更します。
(methodの変更、api_endpointを追加)
study:
outputs:
dev:
dataset: dataset1
job_execution_timeout_seconds: 300
job_retries: 1
location: US
method: emulator
priority: interactive
project: test
threads: 1
type: bigquery
api_endpoint: http://127.0.0.1:9050
target: dev
dbt debug
で接続OKとなることを確認します。
$ dbt debug
動作確認
dbt run
を実行すると、テーブルが作成されます。
$ dbt run
04:17:55 Running with dbt=1.8.6
04:17:56 Registered adapter: bigquery=1.8.2
04:17:56 Found 2 models, 4 data tests, 478 macros
04:17:56
04:17:56 Concurrency: 1 threads (target='dev')
04:17:56
04:17:56 1 of 2 START sql table model dataset1.my_first_dbt_model ....................... [RUN]
04:17:57 1 of 2 OK created sql table model dataset1.my_first_dbt_model .................. [SELECT in 0.20s]
04:17:57 2 of 2 START sql view model dataset1.my_second_dbt_model ....................... [RUN]
04:17:57 2 of 2 OK created sql view model dataset1.my_second_dbt_model .................. [SELECT in 0.16s]
04:17:57
04:17:57 Finished running 1 table model, 1 view model in 0 hours 0 minutes and 0.88 seconds (0.88s).
04:17:57
04:17:57 Completed successfully
04:17:57
04:17:57 Done. PASS=2 WARN=0 ERROR=0 SKIP=0 TOTAL=2
$ bq --api http://127.0.0.1:9050 query --project_id=test "SELECT * from test.dataset1.my_first_dbt_model"
+------+
| id |
+------+
| 1 |
| NULL |
+------+
$ bq --api http://127.0.0.1:9050 query --project_id=test "SELECT * from test.dataset1.my_second_dbt_model"
+----+
| id |
+----+
| 1 |
+----+
dbtのプロジェクトにsqlfluffを導入する
sqlfluff, sqlfluff-templater-dbtをインストールします。
pip install sqlfluff==3.1.1 sqlfluff-templater-dbt==3.1.1
次のように.sqlfluff
を作成する。
.sqlfluff
[sqlfluff]
dialect = bigquery
templater = dbt
[sqlfluff:templater:dbt]
project_dir = study
profiles_dir = ~/.dbt
target = dev
BigQueryEmulatorでsqlfluffが実行できることを確認します。
$ sqlfluff lint study/models/
=== [dbt templater] Sorting Nodes...
=== [dbt templater] Compiling dbt project...
=== [dbt templater] Project Compiled.
== [study/models/example/my_first_dbt_model.sql] FAIL
L: 1 | P: 1 | LT13 | Files must not begin with newlines or whitespace.
| [layout.start_of_file]
== [study/models/example/my_second_dbt_model.sql] FAIL
L: 1 | P: 1 | LT13 | Files must not begin with newlines or whitespace.
| [layout.start_of_file]
All Finished 📜 🎉!
pre-commitでsqlfluffで実行する
pre-commitからsqlfluffを実行できるように設定します。
次のように.pre-commit-config.yaml
を作成する。
.pre-commit-config.yaml
repos:
- repo: https://github.com/sqlfluff/sqlfluff
rev: 3.1.1
hooks:
- id: sqlfluff-lint
additional_dependencies:
- sqlfluff-templater-dbt==3.1.1
- git+https://github.com/takemikami/dbt-bigquery.git@4c84de2e72e876b3c4ed0307c36cfb5a97ac4e75
pre-commit経由で、BigQueryEmulatorでsqlfluffが実行できることを確認します。
$ pre-commit run --files study/models/example/my_first_dbt_model.sql
[INFO] Initializing environment for https://github.com/sqlfluff/sqlfluff.
[INFO] Initializing environment for https://github.com/sqlfluff/sqlfluff:sqlfluff-templater-dbt==3.1.1,git+https://github.com/takemikami/dbt-bigquery.git@4c84de2e72e876b3c4ed0307c36cfb5a97ac4e75.
[INFO] Installing environment for https://github.com/sqlfluff/sqlfluff.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
sqlfluff-lint............................................................Failed
- hook id: sqlfluff-lint
- exit code: 1
=== [dbt templater] Sorting Nodes...
=== [dbt templater] Compiling dbt project...
=== [dbt templater] Project Compiled.
== [study/models/example/my_first_dbt_model.sql] FAIL
L: 1 | P: 1 | LT13 | Files must not begin with newlines or whitespace.
| [layout.start_of_file]
All Finished 📜 🎉!
GitHub Actionsでsqlfluffを動かす
最後に、GitHubActionsからsqlfluffを動かします。
GitHubActionsのWorkflow、dbtのprofiles.ymlを準備します。
.github/workflows/ci.yaml
name: ci
on: push
jobs:
test:
runs-on: ubuntu-latest
services:
bigquery:
image: takemikami/bigquery-emulator:latest
ports:
- 9050:9050
- 9060:9060
env:
PROJECT: test
DATASET: dataset1
steps:
- uses: actions/checkout@v4
- run: |
mkdir -p ~/.dbt
cp .github/workflows/.dbt/profiles.yml ~/.dbt/profiles.yml
- uses: pre-commit/action@v3.0.1
.github/workflows/.dbt/profiles.yml
study:
outputs:
dev:
dataset: dataset1
job_execution_timeout_seconds: 300
job_retries: 1
location: US
method: emulator
priority: interactive
project: test
threads: 1
type: bigquery
api_endpoint: http://127.0.0.1:9050
target: dev
BigQuery Emulatorはサービスコンテナを利用して起動します。
サービスコンテナについて | GitHub Actions
https://docs.github.com/ja/actions/use-cases-and-examples/using-containerized-services/about-service-containers
Dockerから起動する時に、
環境変数からプロジェクトとデータセットを渡したかったので、
以下のような変更を行って、独自のDockerImageを作っています。
https://github.com/takemikami/bigquery-emulator/commit/a6e1a55fa16ba4eefc29ea2ee78ff1aef727a600
これらのファイルをcommitしてGitHubにpushすると、
GitHubActionsでsqlfluffを動かすことができます。
$ git add .sqlfluff .pre-commit-config.yaml .github/workflows study/
$ git commit -a -m "initial commit"
以上。