【入門編】Poetryとuvを組み合わせた『ハイブリッドCI』の構築:ビルドはPoetry、テスト実行はuvの高速キャッシュを活かす適材適所の戦術 – ビルド・パッケージ管理ツール生産性向上バイブル

こんにちは!開発環境アーキテクトの先輩です。

Pythonのパッケージ管理、日々の開発で頭を悩ませていませんか?「Poetryは依存関係の解決が美しくて安心だけど、CIのビルドやインストールがちょっと遅い……」「最近話題の`uv`は爆速だけど、厳密なロックファイルの運用やビルドの標準化にはまだ少し不安がある……」そんなモヤモヤを抱えている現場は非常に多いです。

ネットを検索すれば「Poetryをこう使え」「uvがすべてを置き換える」といった極端な意見が飛び交っていますが、プロの現場で求められるのは、「それぞれのツールのいいところを極限まで引き出し、適材適所で組み合わせて開発体験とCIを最速にする」という、実利に基づいたアーキテクチャ設計です。

今回は、「依存関係の堅牢な解決とビルドはPoetry、テスト実行とパッケージの高速インストールはuv」という、いいとこ取りをした『ハイブリッドCI』の構築術を、初心者の方にもわかりやすく、かつ現場のプロが唸る深い知見とともにお伝えします。これをマスターすれば、毎日のCI待ち時間が劇的に短縮され、ストレスフリーな開発が手に入りますよ!

—

1. なぜPoetryとuvを組み合わせるのか?(アーキテクチャの思想)

まずは、今回組み合わせる2つのツールの役割を正しく理解しましょう。

  • Poetry(ポエトリー)の役割:堅牢な「頭脳」

Poetryは、PEP 517/621準拠の標準的なビルドシステムであり、`pyproject.toml` を中心としたモダンなPythonプロジェクトの標準です。特にその依存関係解決エンジンは極めて優秀で、バージョン衝突や推移的依存関係(依存の依存)の矛盾を完全に防ぎます。「絶対に壊れないロックファイル(`poetry.lock`)」を作るための頭脳として使います。

  • uv(ユーブイ)の役割:圧倒的な「筋肉」

Astral社がRustで開発した `uv` は、Pythonのパッケージインストーラーおよびリゾルバであり、驚異的な速度を誇ります(pipの10倍〜100倍以上)。C言語レベルの並行処理と洗練されたグローバルキャッシュ機構により、パッケージのダウンロードとインストールを一瞬で終わらせます。CIにおける「重労働」を担う筋肉として使います。

この2つをどう連携させるか?答えはシンプルです。
「Poetryで生成した `poetry.lock` をそのまま活かしつつ、実際の仮想環境へのインストールとテスト実行だけをuvに爆速でやらせる」のです。

—

2. 開発環境の基礎セットアップとツールの役割

それでは、実際に手を動かしながら環境を整えていきましょう。今回は最小限のサンプルプロジェクト(HelloWorldレベル)を題材にします。

ディレクトリ構成と設定ファイル

プロジェクトルートに以下の構成を作ります。

my_hybrid_project/
├── pyproject.toml # Poetryの依存関係定義とメタデータ
├── poetry.lock # Poetryが生成する厳密なロックファイル
├── src/
│ └── greeter.py # テスト対象のソースコード
└── tests/
└── test_greeter.py # pytest用のテストコード

`pyproject.toml` の記述

プロジェクトの定義とPoetryの設定を行います。

[tool.poetry]
name = “my-hybrid-project”
version = “0.1.0”
description = “Poetryとuvを組み合わせたハイブリッドCIのサンプル”
authors = [“Genius Architect “]
readme = “README.md”
packages = [{include = “greeter”, from = “src”}]

[tool.poetry.dependencies]
python = “^3.11”
依存関係の定義(例として人気のあるclickを入れる)
click = “^8.1.7”

[tool.poetry.group.dev.dependencies]
開発・テスト用の依存関係
pytest = “^8.0.0”

[build-system]
requires = [“poetry-core>=1.0.0”]
build-backend = “poetry.core.masonry.api”

【解説】ここでは通常のPoetryプロジェクトと全く同じように依存関係を定義します。開発者は普段のローカル開発では `poetry install` や `poetry run pytest` を使って安全に開発を進められます。

—

3. 精度高いHelloWorld的な動作確認

アーキテクチャの前に、まずは動くコードとテストを用意しましょう。

ソースコード (`src/greeter.py`)

def say_hello(name: str) -> str:
“””指定された名前に対して挨拶の文字列を返す関数”””
return f”Hello, {name}!”

if __name__ == “__main__”:
print(say_hello(“World”))

テストコード (`tests/test_greeter.py`)

from greeter import say_hello

def test_say_hello():
“””挨拶関数が正しく動作するか検証するテスト”””
assert say_hello(“Architect”) == “Hello, Architect!”

ローカルでPoetryを使って依存関係を確定させます。

ロックファイルを生成(または更新)する
poetry lock

この `poetry.lock` が、CIにおける唯一無二の「正解の地図」となります。

—

4. 現場で震えるほど役立つ:GitHub Actionsでの「ハイブリッドCI」構築

いよいよ本題です。GitHub Actions上で、Poetryの堅牢性とuvの爆速を融合させたワークフローファイル(`.github/workflows/ci.yml`)を構築します。

ここで重要なのは、「Poetryでロックファイルを検証しつつ、環境構築はuv pipを使って数秒で終わらせる」というテクニックです。

name: Hybrid CI (Poetry + uv)

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
test:
runs-on: ubuntu-latest
steps:
# 1. リポジトリのチェックアウト

  • name: Checkout repository

uses: actions/checkout@v4

# 2. Python環境のセットアップ

  • name: Set up Python 3.11

uses: actions/setup-python@v5
with:
python-version: “3.11”

# 3. 超高速インストーラー「uv」の公式アクションによる導入

  • name: Set up uv

uses: astral-sh/setup-uv@v5
with:
enable-cache: true # uvの強力なグローバルキャッシュを有効化
cache-dependency-stems: “poetry.lock” # ロックファイル変更時にキャッシュを破棄

# 4. Poetryのインストール(ビルドとロック検証用)

  • name: Install Poetry

run: |
pip install poetry

# 5. Poetryのロックファイルが壊れていないか検証(厳密性の担保)

  • name: Verify Poetry lock file

run: |
poetry check –lock

# 6. uvを使った爆速仮想環境の作成とパッケージインストール
# ポイント:Poetryのロックファイルを直接読ませることで、Poetryと同等の環境をuvで構築する

  • name: Install dependencies with uv

run: |
# 仮想環境を作成
uv venv .venv
# 有効化(GitHub Actionsのステップ間での環境変数引き継ぎ)
echo “$PWD/.venv/bin” >> $GITHUB_PATH
# poetry.lockから直接依存関係をuv経由で超高速インストール
uv pip sync poetry.lock –project .
# 自パッケージ(editableモード)をインストール
uv pip install -e .

# 7. テストの実行(pytest)

  • name: Run tests with pytest

run: |
pytest

—

5. アーキテクチャの核心:なぜこの構成が最強なのか?

このハイブリッドCI構成には、現場のエンジニアが思わずうなずく3つの大きなメリット(知見)が隠されています。

1. ロックファイルの信頼性とインストールの速度の完全両立

Poetryは依存関係の解決(バージョン矛盾がないかの計算)に時間がかかることがありますが、`poetry check –lock` で「ロックファイルが正しいか」のチェックだけを行えば一瞬で終わります。実際の重い処理(数個〜数十個のパッケージのダウンロードとコンパイル)は、C言語ベースで並列ダウンロードを行う `uv pip sync` が一瞬で片付けます。これにより、CIのセットアップ時間が従来の1/5以下に短縮されます。

2. キャッシュ戦略の最適化

`setup-uv` アクションの `enable-cache: true` と `cache-dependency-stems: “poetry.lock”` の組み合わせにより、`poetry.lock` に変更がない限り、パッケージのダウンロードが完全にスキップされます。GitHub Actionsのキャッシュ容量を圧迫せず、かつ極限まで無駄を削ぎ落としたビルドパイプラインが完成します。

3. ローカル開発環境との完全な互換性

開発者は普段通り手元のマシンで `poetry install` を使って安心してコーディングやパッケージ追加を行い、それをコミットするだけです。CI側は `poetry.lock` を正しく解釈してuvで高速に回すため、「ローカルでは動いたのにCIで落ちた」という絶望的なミスマッチを防げます。

—

おわりに

いかがでしたでしょうか?
「新しいツールが出たからすべてをそれに置き換える」のではなく、「それぞれのツールの設計思想(Philosophy)を見極め、いいとこ取りをして組み合わせる」ことこそが、私たち開発環境アーキテクトの真骨頂です。

このPoetryとuvのハイブリッドCIを導入すれば、毎日のプルリクエスト作成・テスト実行の待ち時間が驚くほど短くなり、開発チーム全体の心理的安全性と生産性が跳ね上がります。

ぜひ、あなたのプロジェクトでも明日から試してみてください。あなたのコーディングライフが、より快適でエキサイティングなものになることを応援しています!

タイトルとURLをコピーしました