worktree に降りると .env を見失うスクリプトを共通ローダに寄せた

  • #Python
  • #worktree
  • #環境変数
  • #自動化

今回やったこと

Git worktree から無人スクリプトを起動したとき、メインリポジトリにある .env を見失う問題を解決するため、設定の探索・読み込み処理を共通ローダへ集約した。対象は認証情報や通知設定を読む処理である。worktree はソースコードの作業場所が変わるため、スクリプト自身の位置から .env を探す実装は、その場所に設定ファイルが無ければ失敗する。

解決策は scripts/lib/env.pyload_env()env_path() に探索と読み込みを寄せることだった。記事では、設定を読み込む処理と、その配線が本当に全体へ届いているかを検査するテストを分けて説明する。

なぜ worktree でだけ壊れるのか

従来のスクリプトは、自分のファイル位置からリポジトリのルートを計算し、そこに .env がある前提で load_dotenv() を呼んでいた。メイン checkout で動かす限り、設定が見えるので問題は表面化しない。しかし worktree では計算されたルートが一時的な作業コピーになる。.env は gitignore 対象なので、そのコピーへ自動で持ち込まれず、認証情報が未設定のまま処理が始まる。

この差は、コードのテストをメイン checkout だけで行うと見落としやすい。無人レーンでは、実行場所の違いが設定探索の違いに直結する。したがって「コードが動いたか」だけでなく「どの checkout から起動したか」も検査対象になる。

探索先を一つの実装にする

env.py はまず worktree 側の .env を確認し、無ければ git rev-parse --git-common-dir から共有 Git 管理領域を求め、メインリポジトリ側の .env を候補に加える。明示的に環境変数が渡されている場合は壊さないよう、既定では既存値を上書きしない。

def candidates() -> list[Path]:
    return [
        REPO_ROOT / ".env",
        (_main_repo_root() or REPO_ROOT) / ".env",
    ]

def load_env(override: bool = False):
    path = env_path()
    # 既存の環境変数を優先して KEY=value を読む

この設計では、設定の探索場所を各スクリプトが個別に決めない。worktree 固有の設定を使いたい場合はそれを優先でき、通常の無人実行ではメイン側の設定をフォールバックにできる。パーサも一つにまとまるため、引用符や空行、コメントの扱いがスクリプトごとにずれない。

共通化だけでは再発を止められない

ローダを作っても、新しいスクリプトが以前の書き方を写経すれば同じ事故が戻る。そこで scripts/test_env_loading_wiring.py は、禁止された load_dotenv(REPO_ROOT / ".env") の形と、直接の python-dotenv 利用を検出する。検査対象から env.py 自身を除外するのは、そこが探索の正本だからである。

検査対象見ること失敗時の意味
scripts/lib/env.py探索と KEY=value 読み込み共通ローダの不具合
各スクリプトload_env() の利用旧方式の再混入
test_env_loading_wiring.py禁止パターンの残存配線漏れをCIで停止

移行途中には、検査対象の文字列を自分で消してしまい、何も検出できないテストになる危険もあった。そのため、禁止パターンを含む対照群をテストへ通し、意図した違反を実際に赤くできることを確認する必要がある。テストは「違反が今ゼロ」という結果だけでなく、「違反が入ったら検出する能力」を持たなければならない。

やってみてわかったこと

設定ファイルの解決は、各スクリプトの小さな補助処理に見える。しかし worktree、CI、launchd のように起動場所が変わる運用では、ここが共通の基盤になる。個別修正の本数を減らすことより、次のスクリプトが同じ誤りを追加できない状態にすることが重要だった。

また、.env の内容をリポジトリへ移す必要はない。必要なのは秘密をコピーすることではなく、Git の共有管理領域を手がかりに、実行時だけ正しい設定を解決することだ。認証情報そのものをコードや記事へ書かず、探索ロジックと配線だけを版管理する境界が保守上の要点になる。

試した環境・更新履歴

  • 試した環境: Python 3 系の scripts/lib/env.py と配線検査スクリプト
  • 更新履歴: 2026-09-01 初稿
  • 訂正履歴: なし