面倒なdbt v1.10/Fusionへの移行をdbt-autofixで自動化する方法
こんにちは。stable株式会社でデータエンジニアをしているmyshmehです。
dbt-core v.10で、yaml形式の厳密化などの変更により、さまざまなwarningが出るようになりました。このwarningは、Fusionを含む将来のdbtバージョンでエラーになるため、早めの対応が必要です。
本記事では、dbt-autofixという公式CLIツールを使って、dbt-core v1.10、Fusionへの移行を自動化する方法を紹介します。
移行に必要なこと
dbt-core v1.10では、主にYAMLの形式について、以下のようなwarningが出るようになりました。
- 独自のプロパティ - yamlファイルにdbtの予期しないプロパティが含まれている場合、将来的にmeta設定下でネストする必要があります
models:
- name: my_model
description: A model in my project.
config:
meta:
grace_is_cool: true # 自前のプロパティはここでしか定義できない
- 重複YAMLキー - 同一ファイル内で同じキーが複数存在する場合、v1.10までは最後の設定が使用されますが、将来的にはサポートされなくなります
my_profile:
target: my_target
outputs:
# ...
my_profile: # dbtはこちらを採用してきた
target: my_other_target
outputs:
- いくつかのプロパティのconfigへの移行 -
freshness、meta、tags、docs、group、accessプロパティをconfigセクション下に移動する必要があります
- などなど。。
これらはv1.10ではwarningなので、解決が必須ではありませんが、v1.11やFusionからはerrorになります。つまり、Fusionに移行するには、上記warningを全て解決する必要があります。
したがって、将来のdbtバージョン移行をスムーズにするために、なるべく早く対応しておくことが重要です。
v1.10で出るwarningの詳細については、以下を参照ください。
なぜYAML形式にうるさくなったの?
問題
従来のdbt-core (v1.9まで)では、dbtプロジェクト中のYAMLファイルは何でもありの状態でした。
例えば、以下のように勝手なプロパティを加えても、dbt-coreは無視して処理を続けます。
models:
- name: my_model
description: A model in my project.
grace_is_cool: true # a custom property
この仕様は、以下の問題を引き起こします。
- スペルミスを見逃す
- 例えば、desciption: → description: のタイポがあってもdbtは無視するので、設定の誤りに気づくのが遅れます。
- 公式のプロパティと名前衝突する
- dbtが将来同名の予約プロパティを導入した場合に、開発者やOSSコミュニティが移行作業に苦しみます。
つまり、YAMLファイルの仕様が厳密でないことで、何が有効な設定なのかを厳密に判定できず、意図しない設定ミスを事前に検出できないのです。
解決策
dbt-core v1.10とFusionでは、jsonschemaによって各プロパティの型を定義し、YAMLファイルの仕様をより一層厳密にしました。例えば、自前のプロパティはmeta configでしか定義できなくなります。
models:
- name: my_model
description: A model in my project.
config:
meta:
grace_is_cool: true # a custom property
現状のFusionのYAML仕様については、以下から確認できます。
これをもとに、OSSや自分が勝手に作り上げたYAMLプロパティに関して、dbt-core v1.10ではwarningが、Fusionでは(将来的に)errorが出るようになります。したがって、Fusionを使うには、これらの独自プロパティやその他の設定を、所定の仕様で定義する必要が出てきたのです。
より詳細な経緯については、以下のDiscussionsページを参照ください。
手動移行の課題
実務のプロジェクトでは、数百から数千のモデル、テスト、ソースが定義されていることも少なくありません。これらすべてに対して重複キーの削除、独自プロパティのmetaへの移動、対象プロパティのconfigセクションへの移行などを手動で行うことは面倒です。
Claude Codeにやらせるにしても、途中で変に値を変更していないかなどの確認をするコストがあります。。
dbt-autofixで自動移行!
dbt-autofixとは
dbt-autofixは、dbt Labsが提供する公式CLIツールで、dbt-core v1.10でwarningになったdeprecationの多くを自動修正するものです。前述の独自のプロパティ、YAML重複キー、プロパティのconfig移行に関しては、このツールで自動修正できます!
具体的にどのdeprecationを自動修正してくれるかに関しては、以下を参照ください。
インストールはuvが推奨されていて、uvx dbt-autofixで最新バージョンを利用することができます。
コマンド
dbt-autofixは、以下のコマンドを提供しています。
-
list-yaml-duplicates: YAMLの重複キーを検知します(キーの削除自体は手動で実行する必要があります) -
deprecations: 独自プロパティの移動などを自動実行します -
jobs: dbt Cloudのjobs設定について、各種修正をします(本記事では割愛)
deprecationsコマンドは、そのまま使うとYAMLファイルを書き換えてしまいます。これは、例えば、typoによって結果的に独自プロパティができてしまった時に、当該typoのプロパティもconfig > metaプロパティに移動されてしまう問題があります。
よって、まずは--dry-runフラグをつけて、意図しないプロパティ定義が隠れていないか確認すること良いと思います。
したがって、ワークフローとしては、基本的に以下の順序で進めるのが良いと思います。
-
dbt parseでwarningが出ることを確認 -
list-yaml-duplicatesで重複キーを解決する -
deprecations --dry-runで影響範囲を確認 and 適宜修正する -
deprecationsでYAMLファイルを自動修正する -
dbt parseでwarningが消えていることを確認する
デモ
jaffle-shopのmainブランチ(commit hash: bb3ecd2)を使って、実際にdbt-autofixを使ってみましょう。
まず、dbtf parseをすると、以下のように2つのwarningが返りました。
➜ jaffle-shop git:(main) dbt parse
dbt-fusion 2.0.0-beta.44
Loading ~/.dbt/profiles.yml
Fetching packages.yml
Loading dbt_project.yml
Loading dbt_packages/audit_helper/dbt_project.yml
Loading dbt_packages/dbt_date/dbt_project.yml
Loading dbt_packages/dbt_utils/dbt_project.yml
Loading dbt_internal_packages/dbt-adapters/dbt_project.yml
Loading dbt_internal_packages/dbt-snowflake/dbt_project.yml
warning: (will error post beta) dbt1060: Ignored unexpected key `"loaded_at_field"`. YAML path: `loaded_at_field`.
--> models/staging/__sources.yml:12:9
warning: (will error post beta) dbt1060: Ignored unexpected key `"loaded_at_field"`. YAML path: `loaded_at_field`.
--> models/staging/__sources.yml:16:9
warning: dbt1000: Warnings marked (will error post beta) will turn into errors before leaving beta. Please fix them.
suggestion: Try the autofix script: https://github.com/dbt-labs/dbt-autofix
Finished 'parse' target 'dev' with 2 warnings in 2s 839ms 233us
これらを、dbt-autofixで自動修正していきます。
list-yaml-duplicates
まず、list-yaml-duplicatesを使って、YAMLファイルに重複キーがあるかチェックします。
➜ jaffle-shop git:(main) uvx dbt-autofix list-yaml-duplicates
Identifying duplicates in /path/to/jaffle-shop
重複がないことを確認できました。
重複があった場合の結果例
ちなみに、重複があった場合には以下のように検知してくれます(profileプロパティを2回定義しました)。ファイル名(dbt_project.yml)と行数(11)が記載されているので、自分で当該ファイルを確認し、どの定義を削除するか手作業で実行する必要があります。
➜ jaffle-shop git:(main) ✗ uvx dbt-autofix list-yaml-duplicates
Identifying duplicates in /path/to/jaffle-shop
There are issues in your project YML files
Please remove duplicates by hand. dbt's default behavior is to keep the last occurence of a key.
If you want to keep the same behaviour remove or comments lines found for the same key and before in the file.
Once you have done all the changes in the files, run the tool again.
/path/to/jaffle-shop/dbt_project.yml:11 -- duplication of key "profile" in mapping
deprecations
次に、deprecations --dry-runで影響範囲を確認します。
➜ jaffle-shop git:(main) ✗ uvx dbt-autofix deprecations --dry-run
Warning: Path /path/to/jaffle-shop/snapshots does not exist
-- Dry run mode, not applying changes --
DRY RUN - NOT APPLIED: Refactored /path/to/jaffle-shop/models/staging/__sources.yml:
restructure_yaml_keys
Table 'raw_orders' - Field 'loaded_at_field' moved under config.
Table 'raw_stores' - Field 'loaded_at_field' moved under config.
DRY RUN - NOT APPLIED: Refactored /path/to/jaffle-shop/dbt_project.yml:
remove_deprecated_config
Removed the deprecated field 'target-path'
loaded_at_fieldはfreshness機能に関するプロパティで、以下の__sources.ymlのように、古い定義ではcolumn名と並列で記載されます。v1.10では、configプロパティ内に定義する必要があります。
sources:
- name: ecom
tables:
# ...
- name: raw_stores
loaded_at_field: opened_at
# ...
target-pathの設定もdeprecatedな機能なので、削除する必要があります。
上記影響範囲は、dbtf parseで出たwarningをカバーしており、修正して問題なさそうです。deprecationsコマンドを実行してみましょう。
➜ jaffle-shop git:(main) uvx dbt-autofix deprecations
Warning: Path /path/to/jaffle-shop/snapshots does not exist
Refactored /path/to/jaffle-shop/models/staging/__sources.yml:
restructure_yaml_keys
Table 'raw_orders' - Field 'loaded_at_field' moved under config.
Table 'raw_stores' - Field 'loaded_at_field' moved under config.
Refactored /path/to/jaffle-shop/dbt_project.yml:
remove_deprecated_config
Removed the deprecated field 'target-path'
結果として、想定通りtargetパスの削除と、loaded_at_fieldの移動が行われました!
diff --git a/dbt_project.yml b/dbt_project.yml
index 085ef00..100e8bb 100644
--- a/dbt_project.yml
+++ b/dbt_project.yml
@@ -15,8 +15,6 @@ test-paths: ["data-tests"]
seed-paths: ["seeds"]
macro-paths: ["macros"]
snapshot-paths: ["snapshots"]
-
-target-path: "target"
clean-targets:
- "target"
- "dbt_packages"
diff --git a/models/staging/__sources.yml b/models/staging/__sources.yml
index 4f9c9a8..8ceb170 100644
--- a/models/staging/__sources.yml
+++ b/models/staging/__sources.yml
@@ -9,11 +9,13 @@ sources:
description: One record per person who has purchased one or more items
- name: raw_orders
description: One record per order (consisting of one or more order items)
- loaded_at_field: ordered_at
+ config:
+ loaded_at_field: ordered_at
- name: raw_items
description: Items included in an order
- name: raw_stores
- loaded_at_field: opened_at
+ config:
+ loaded_at_field: opened_at
- name: raw_products
description: One record per SKU for items sold in stores
- name: raw_supplies
dbtf parseを再度実行すると、warningがすべて消えたことがわかります!
➜ jaffle-shop git:(main) dbtf parse
dbt-fusion 2.0.0-beta.44
Loading ~/.dbt/profiles.yml
Fetching packages.yml
Loading dbt_project.yml
Loading dbt_packages/audit_helper/dbt_project.yml
Loading dbt_packages/dbt_date/dbt_project.yml
Loading dbt_packages/dbt_utils/dbt_project.yml
Loading dbt_internal_packages/dbt-adapters/dbt_project.yml
Loading dbt_internal_packages/dbt-snowflake/dbt_project.yml
dbt-autofixの利用Tips
dbt-autofixを使ってみて、いくつか便利な機能がありました。
部分的な修正適用
大規模dbtプロジェクトでは、一度で全ファイルについてdeprecationsコマンドを利用すると、影響範囲の確認をするのが大変かと思います。--select <path>フラグを使うと、<path>内のファイルにだけスキャン対象を絞ることができます。
dbtパッケージへの修正適用
もし、お使いのdbtパッケージがdbt v1.10やFusionに対応しておらず大量のwarningが出た場合、deprecationsコマンドに--include-packagesフラグを使うことで、当該パッケージにも修正適用することができます。
ただし、当然ながらdbt depsをし直すと、上記修正はrevertされるので注意が必要です。よって、可能ならば、当該パッケージをv1.10、Fusion対応のバージョンに更新することがベストではあります。
dbt-core v1.10、Fusion移行の注意点
そもそもの話になりますが、移行の影響は、自分のdbtレポジトリだけでなく、当該レポジトリを参照する外部ツールにもおよびます。
もし、外部ツールが新しいYAML仕様に対応していない場合、この移行によって予期せぬ動作またはエラーを引き起こす可能性があるため、対応状況を確認する必要があります。
例えば、lightdashはつい先日v1.10, Fusionへの対応を発表しています。
なお、lightdashでよく使うmetaタグは、dbt v1.10以降のYAML仕様とかぶってしまいますが、これについてケアしながら自動移行するCLIツール (MetaMove) が公式提供されていますので、ぜひ以下からご確認ください。
dbt-osmosisは、現在v1.10への対応作業中で、dbt 1.10.3のリリースを待っている状態のようです。
まとめ
本記事では、dbt-autofixを使ったdbt-core v1.10とFusionへの移行自動化について紹介しました。
- dbt-core v1.10でのYAML形式の厳密化により、独自プロパティ、重複キー、プロパティの配置場所などでwarningが出るようになり、これらはFusionでエラーになるため、修正が必要です
- dbt-autofixによって、YAML重複キー、独自プロパティの移動、非推奨設定の削除などを自動化できます
- 移行時の注意点 - 自分のdbtプロジェクトだけでなく、連携する外部ツール(Lightdash、dbt-osmosisなど)の対応状況も確認する必要です
dbt-autofixにより、v1.10やFusionへの移行作業を大幅に効率化でき、手動作業によるミスを減らしながらスムーズな移行が実現できます!早めの対応で、将来のFusion移行に備えましょう🚀
stableでは、dbt をはじめ、各種データウェアハウス・BI におけるデータ支援業務を実施しています。社内でデータ基盤に関する課題を抱えている方は、お気軽に下記からご相談ください。
また、採用も行なっているので、データエンジニアリング領域のクライアントワークにご興味がある方もぜひお声がけください。Pittaを開放しているので、よろしければ一度カジュアルに話しましょう。
Discussion