如何にしてdbt-osmosisを自作CLIへ移行したか
この記事はdbt Advent Calendar 2025の11日目の記事です。
大遅刻でスミマセン。
はじめに
ナレッジワークでエンジニアをしている @_sisisin です。
前回の記事「アプリケーションDBのメタデータをデータ基盤に自動で伝播させる仕組みを構築しました」内で、dbt-osmosisの更新が止まっている点に悩まされている、という話を書いていました。
色々検討した結果、結局dbt-osmosisの利用をやめて、自作CLIに置き換えることが出来たので、その過程を紹介したいと思います。
dbt-osmosisとは
リポジトリ: https://github.com/z3z1ma/dbt-osmosis
dbt-osmosisは、主にdbtのmodelのyamlを自動生成したり、メタデータ継承をしてくれるツールです。
テーブルの列の説明や型情報などを、stagingモデルからmartモデルへ自動で伝播させることが出来ます。
移行を検討するに至った背景
- dbt-core 1.10へのアップデートのブロッカーになっている
- dbt-osmosisの開発状況が芳しくない
- 実行がかなり遅い
それぞれ説明していきます。
dbt-core 1.10へのアップデートのブロッカー
まずdbt-osmosisがdbt-core 1.10に対応していないです(2025年11月時点)。
そして、1.10の前のマイナーバージョンである1.9のサポートは2025年12月で終了するというアナウンスがされていました。
dbt-osmosisの開発状況
前回の記事でも触れた内容なんですが、dbt-osmosisのリポジトリの開発状況は以下のような状態でした。
- 最新版(v1.1.17)のリリース日が2025年4月24日
- 最終リリースから改修が入っていたが、リリースされていない
- 最終commitも進んでいない
前回の記事から少し時間が経っていたのであらためて確認してもさほど状況は変わっていませんでした。
とまあこういう状況だったので、貢献 or 更新待ちは引き続き難しそうだなあという感じでした。
実行がかなり遅い
GitHub Actions上での実行に全体で30分程度かかってました。これはキツい。
手元で実行するにしてもかなりの時間がかかっており、dbtのmodel開発上で割と辛かったんですよね。
地味に挙動も読めないところがあるし・・・。
移行の検討からツール自作の決断へ
というわけで、移行先を検討し始めました。
・・・が、代替ツールが見当たらなかった(はず)[1]
じゃあまあ自作の検討かなあ・・・最近はAI使えばまあ割と実装は楽にできちゃうしなあ・・・、で自作を検討してみました
自作の検討
さて、ナレッジワークにとってdbt-osmosisのコアバリューはメタデータ継承でした。
前回の記事でも触れたように、列レベルのデータ閲覧ポリシー制御に欠かせない存在であるためです。
そして、dbt-osmosisの機能として再実装が難しそうなのもこのメタデータ継承だろうと思っていました(yaml自動生成なんかはやれば明らかに実装できることがわかるため)。
ゆえに「再実装可能か?」は、ほぼ「メタデータ継承を再現できるか?」という問いになるだろうと当たりをつけました。
事前知識としてdbt-osmosisのメタデータ継承が単なる列名の文字列マッチングで行っていることは知っていたんですが、実際どう実現しているかまでは知らなかったので、調べてみないとわからないな、というのが検討当時の感覚でしたね
また、特殊な事情として、TypeScriptで実装したかったというのがありました[2].
「TypeScriptでの実装が可能か?」の判断については、「dbt-osmosis内でdbtをimportして呼び出している箇所が、どのような処理になっているか」を調べる必要があるだろうと考えました。
コードリーディング
というわけで、調査方針が決まったのでコードリーディングしていきます。
コードリーディングにはClaude Codeを利用しました。
こんな流れでやっていきました
- どのメソッドがメタデータ継承の処理のエントリポイントかを探させる
- そのメソッドの処理を分析するように指示してレポートを書かせる
- contextをclearしてからそのレポートの妥当性を評価させる
- その上でサマリを作らせて自分はそれを読む
- 2~4を何度かやって、結果が大体収束しているようならOKとする
このプロセスで得たサマリーから、
- メタデータ継承のロジックは十分再実装可能な複雑さであること
- 要はDAGのグラフを並べ替えて、列名の文字列マッチングをしているだけであること
- dbtのライブラリとしての利用箇所は限定的(loadMetadataを使ってるぐらい)であること
- つまり、dbt compileで
target/manifest.jsonを用意してそれを読み込めば同等の処理ができそう
- つまり、dbt compileで
ということがわかり、結論として再実装が出来そうだと判断しました。
実際に再実装・移行の段取りを検討
やることが決まったので、次は段取りを考えました。
こういうツール置き換えはビッグバンリリースしたくないので、上手いこと軟着陸出来るように段階的に進められるように検討しました。
まず、うちで利用しているdbt-osmosisの機能は少なく、かつ、独立して定義できることに着目しました。
dbt-osmosisの機能のうち、利用していたものを整理すると以下のようになりました。
- sources.ymlの追記(存在するsourceに対してDWHから取れる情報を追記する)
- model properties yamlを生成(DWHの情報・modelのSQLとmanifest.jsonの情報を元に0から生成する)
- column documentation inheritance(メタデータ継承)(staging→martへメタデータを伝播)
このうち、sources.ymlに関しては既に自動生成の仕組みを作っていたので、考えなくてOK。
であれば、あとはmodel properties yamlの生成とメタデータ継承を独立した処理として実装すれば良いな、と判断出来ました。
そして幸いなことに、dbt-osmosisの機能はyamlを生成・書き換えをする、冪等な処理です。
従って、それぞれの機能を実装したら実行を二重にしても同じ結果になるようにすれば、既存のdbt-osmosisからシームレスに移行が可能です。
満を持して実装
実装方針・段取りが決まったので、実際の実装に入っていきます。
事前にロジックも調査済み・検証手順も確立して、何やるかがはっきりさせられました。
こうなると、AIにかなり任せやすい状態になっているので、実装が一番軽いまであります。
実装は全てClaude Codeにやってもらいました。
実際に実装してみると、大体↓ぐらいの規模感で実装できました。
- model properties yamlの生成処理: plan 200行、実装 900行
- メタデータ継承処理: plan 1200行、実装 1000行
こんなもんだと、AI使っていればほんとにすぐ出来ちゃうのがありがたい時代になったものだと感じます。
こぼれ話 - メタデータ継承のアルゴリズム
dbt-osmosisはテーブルリネージのDAGに対して、上流からノードごとに世代をラベリングする、というロジックで実装されています(ref. https://z3z1ma.github.io/dbt-osmosis/docs/tutorial-yaml/inheritance#how-it-works )。
しかし、これって単にDAGをトポロジカルソートして上流から処理するだけで良さそうだよなあ、と思ったのでAIに相談して、それで問題なさそうと結論づけて、今回の実装ではトポロジカルソートで上流から処理するロジックにしました。
結果、スクリプトがかなりシンプルになって良かったなと思っています。
結果
30分 → 3分未満(10倍以上の高速化)を達成して、dbt-core 1.10に無事移行できました。 🎉
まとめ
というわけで、無事にdbt-osmosisの利用をやめて、dbt-coreも1.10にアップデートできました。
出来れば自作CLIも公開したかったんですが、時間が取れずなかなかそこまで手が回っておりませんね。いつか公開したいです。
というわけで、dbt-osmosisから自作CLIへの移行の話でした。
Discussion