Musubi 開発チームおよびサーバサイド Python 研究会の加藤です。最近は冷えますね。
私のチームで開発している Musubi のバックエンドは Python で実装されていますが、そのパッケージおよびランタイム管理の変遷を追ってみると
となっていて、ここ4年ほどは変わっていません。
最近は mise や uv が流行っており 1、 しかも高速と聞いているので CI/CD の高速化も狙って導入することにしました。
Musubi バックエンドの構成
イメージが湧きやすいように Musubi バックエンドのリポジトリの中身を説明します。
# Musubi バックエンドリポジトリ中のファイル # CDK で Lambda 関数をデプロイするためのコード cdk/ bin/*.ts lib/*-stack.ts package.json package.json pnpm-lock.yaml pnpm-workspace.yaml .node-version # Lambda 関数にデプロイされる Python コード musubi_backend/ *.py tests/ test_*.py requirements.txt # Poetry と pip のバージョンをロックするため pyproject.toml poetry.lock .python-version # リポジトリセットアップ用スクリプト setup-repository
Python バックエンドのリポジトリですが、 AWS CDK のために Node も使用しているのが特徴ですね。
mise の導入
mise のインストール方法は以下のページで説明されています。
Musubi 開発チームでは、チーム共通の開発用ツールを一括インストールするスクリプトをメンテナンスしており、 mise 導入時はその中にある Brewfile に1行付け加えるのと、~/.zshrc に mise activate コマンドの実行を付け加えるようにしました。
echo "Setup mise" if ! grep -qE '^# mise$' ~/.zshrc; then # 既存コードがあればスキップ echo '# mise' >> ~/.zshrc echo 'eval "$(mise activate zsh)"' >> ~/.zshrc # mise を有効にするコマンド else echo "Skip setup mise" fi
Musubi 開発チームへの新規参画メンバーは必ずこれを実行してもらうので、後は残りのメンバーに各々インストールしてもらうように依頼しました。
(記事の趣旨から外れますが)チームサイズが大きくなってくるとこのような共通スクリプトのありがたみが増えますね
uv の導入
次に mise を使って uv をインストールするようにします。今回はバージョンを指定して uv のリリースで CI が壊れないようにしておきます。
$ mise use --pin uv uv@0.9.13 mise ~/work/musubi-backend/mise.toml tools: uv@0.9.13
mise.toml ができましたね。こんな内容です。2
[tools] uv = "0.9.13"
カケハシではサービス開発に Renovate を全面的に導入しており、 mise もアップデートの対象になっています。
そのため、新しい uv がリリースされると Renovate がアップデート用の PR を作ってくれるため、ツールの最新バージョンへの追従が楽になります。
mise.toml があるディレクトリへ初めて移動すると警告が出るので、 mise trust を実行して許可しましょう。
Poetry から uv への移行
マイグレーションスクリプトを実行して、 Poetry の設定を uv 向けに変換します。
uvx migrate-to-uv
これを実行すると pyproject.toml の Poetry 向けセクションが uv 向けに置換され、uv.lock の作成と poetry.lock の削除が行われます。
マイグレーションスクリプトで置き換えられないものもあり、これは git grep -i poetry で探して1つ1つ置き換えていきました。
poetry run->uv runpoetry export->uv exportpoetry version -s->uv version --short- 環境変数の切り替え
poetry-plugin-dotenvをインストールしたうえでPOETRY_PLUGIN_DOTENV_LOCATION=$(dirname $0)/.env.dev poetry run CMDを実行すると、.env.devで定義した環境変数が適用されたうえでCMDが実行されるので、これを利用して、開発と本番の環境変数を切り替えていたのですが、これはシンプルにMISE_ENV_FILE=$(dirname $0)/.env.dev mise exec -- CMDとして置き換えることが出来ました。文字数も少し短くなってお得ですね
Python, Node のインストール
Python, Node のインストールも、 pyenv, nodenv から mise へ置き換えていきます。
pyenv, nodenv をまだ使用しているプロジェクトもあるので、 このリポジトリだけ mise で Python と Node のインストールをするようにします。
まず環境変数で nodenv, pyenv が管理下にあるバージョンを使用させないようにします。
mise set PYENV_VERSION=system mise set NODENV_VERSION=system
次に、idiomatic_version_file_enable_tools を設定して、.python-version, .node-version に記載のランタイムバージョンをインストールするようにします。
mise settings add -l idiomatic_version_file_enable_tools python mise settings add -l idiomatic_version_file_enable_tools node mise install
無事に mise でインストールしたバージョンに置き換わっているようです。
$ which python /Users/my_name/.local/share/mise/installs/python/3.14.3/bin/python $ which node /Users/my_name/.local/share/mise/installs/node/24.13.1/bin/node
mise 以外にバージョンマネージャーを使用する見込みがなければ、 idiomatic_version_file_enable_tools を使う代わりに mise use python@VERSION として完全に mise 管理にしても良いです。
リポジトリのセットアップスクリプトも、 mise を使うように直しておきましょう。
--- a/setup-repository +++ b/setup-repository @@ -1,19 +1,11 @@ #!/bin/bash -ue -pyenv install -s || (echo "anyenv install pyenv を実行してから再度実行してください" && exit 1) -pyenv rehash -nodenv install -s || (echo "anyenv install nodenv を実行してから再度実行してください" && exit 1) -nodenv rehash +mise install # Node corepack enable corepack install pnpm install # Python +uv sync -pip install -r requirements.txt # 指定したバージョンの pip, poetry をインストール -poetry install
これで、./setup-repository を実行したときに Node, Python のインストールが mise で、 Python パッケージのインストールが uv で行われるようになります。
試してみたのですが、これまで「ぐーーーーーーん🚚」だったのが「スッ🚀」ぐらいに感じられるようになりました。いいですね!
不要になったので requirements.txt は削除します。
rm requirements.txt
One more thing ... (GitHub Actions)
これで終わり…と思ったら CI がまだ残っていました。
Musubi バックエンドの GitHub Actions ワークフローでは、以下の Action を Composite Action にラップして使用していますが、
- name: Setup Node.js uses: actions/setup-node@v6 with: node-version-file: .node-version cache: pnpm
- name: Setup Python uses: actions/setup-python@v6 with: python-version-file: .python-version cache: "pip"
これを mise-action で置き換えました。
- uses: jdx/mise-action@v3
スッキリしましたね!
記事の締め切りの都合で uv や pnpm のキャッシュをまだ適切に設定出来ていません。その点では元の構成のままにしておいて、 uv は別の Action でインストールしたほうが良さそうです。
あれ、思ったより簡単!?🤔
この記事、実は殆どが作業しながら行ったことを書いているのですが、ほとんど手戻りがなく進んでしまいました。
なぜだろうと考えてみたのですが、それは mise や uv が nodenv&pyenv や Poetry の機能を完全に受け継いでいて、置き換えるだけで動くレベルだったことと、
Musubi バックエンドが環境設定のとき以下のようにツールを直接呼び出す箇所を減らす設計から来ていると思います。
- macOS 環境は共通開発ツールリポジトリにある
setupスクリプト一本でmise,uv, それ以外にもghやjq等のツールをインストール - リポジトリ毎のランタイムやパッケージインストールは
./setup-repositoryの実行のみ - CI も環境を初期化する処理はComposite Action や Reusable Workflow で共通化してワークフローが増えても共通のまま
ツールの互換性とリポジトリの設計の両方がスムーズな移行の要因だったのですね。
まとめ
Musubi バックエンドのリポジトリへ mise と uv を導入して、 ランタイムやパッケージのインストールをモダンにしました。
単に移行しただけなら「ちょっと早くなった」ぐらいですが、このリポジトリには他にも複雑な処理が詰まっているので、今後は mise のタスク機能を使ってそれをまとめていこうと思っています。
ここまで読んでくださってありがとうございました。
この記事を見て「私も mise や uv を使ってみよう」と思ってくれる方がいたら嬉しいです。
参考
以下のサイトを参考にさせていただきました。