#monorepo (1)
関数が200個ある Cloud Functions プロジェクトで「変更ファイルから影響を受ける関数だけデプロイ」を機械化した話。grep ベースだと共通ヘルパー経由の多段依存を追えず、結局は全デプロイに流れがち。dependency-cruiser の依存グラフ JSON を使えば transitive 依存を一発で解ける。
構成
- 関数エントリ辞書の抽出:
index.tsを ts-morph で AST パースして{ 関数名 → ファイルパス }を生成。環境分岐(if (ENV === 'production')など)も追う - 依存グラフ生成:
depcruise --output-type json srcで全モジュールの依存JSONを出力(数百ファイルでも1〜2秒) - 影響範囲計算:
git diffの変更ファイル集合から逆依存グラフを BFS で辿り、エントリ集合との積集合を取る
ハマりどころ
- 全デプロイに倒すべきファイルを別途定義する:
package.json,tsconfig.json,firebase.json, エントリ辞書の構造変更(関数追加・削除)。これらは transitive 解析では検出できない - base ref の辞書は
git show <ref>:pathで一時ディレクトリに再構築して比較。worktree を切るより軽い - depcruise 結果はキャッシュ推奨(src の mtime で自動失効)
限界
静的解析なので process.env.FUNCTION_NAME 的な文字列参照や動的 import は追えない。その場合は --all で全デプロイにフォールバックできる逃げ道を残しておく。
# 実行例
ts-node scripts/affected-functions.ts --env production --base origin/main --json
# → { fullDeploy: false, affectedFunctions: [...], deployCommand: "firebase deploy --only functions:a,b,c" }