リモート Mac で Python/データ/ML の CI を回すチーム向けに、uv を軸に wheels/sdist の跨境一括取得を安定させるための比較表・パラメータマトリクス・検証コマンドをまとめました。ミラー切替・タイムアウト・ロックファイルの「契約」まで、コピペ運用を前提にしています。

① シナリオ界定:pip・uv・conda はいつ uv を選ぶか

判断は「解像度の単位」と「キャッシュ再利用」です。単一リポで pyproject.toml または requirements 系列を CI の正にできるなら uv が最も扱いやすいです。

ツール向くケース跨境一括取得注意
pipレガシースクリプトのみ逐次が多く遅くなりがち並列・ロックは手動
uvプロジェクト+CI 再現性並列 DL・ロック統合インデックス方針の文書化が必須
condamamba科学計算スタック全体チャネル設計が重いPyPI との二重管理

uv を優先する条件(チェックリスト):(1)uv.lock または requirements.lock をリポジトリにコミットできる。(2)Runner が Apple Silicon/x86_64 のどちらかに固定できる。(3)社内 PyPI ミラーまたはプロキシ方針がチームで共有されている。

② 実行パラメータマトリクス(並列・タイムアウト・再試行・キャッシュ・ミラー)

デフォルト(読取 30s・再接続 10s・再試行 3)は跨境ジョブでは短めです。帯域とジョブ wall-clock を見ながら まず HTTP を伸ばし、次に並列数を上げます。

目的環境変数/フラグ開始値の目安備考
同時ダウンロードUV_CONCURRENT_DOWNLOADS8〜16共有 Runner ではディスク I/O と競合
展開・インストール並列UV_CONCURRENT_INSTALLS2〜4CPU バウンドになりやすい
sdist 同時ビルドUV_CONCURRENT_BUILDS1〜2跨境+ビルドはタイムアウトしやすい
HTTP 読取タイムアウトUV_HTTP_TIMEOUT120〜300HTTP_TIMEOUT も同等
接続タイムアウトUV_HTTP_CONNECT_TIMEOUT30〜60高 RTT 回線で有効
HTTP 再試行回数UV_HTTP_RETRIES5〜10指数バックオフは uv 側
キャッシュ場所UV_CACHE_DIR例: ~/Library/Caches/uv-ciジョブ ID をパスに含めると汚染しにくい
主インデックスUV_DEFAULT_INDEX公式 or ミラー URL古い UV_INDEX_URL も可
追加インデックスUV_INDEXスペース区切り名前付きは pyproject 推奨
シェルにそのまま貼れる例(URL は組織のミラーに差し替え)
export UV_CACHE_DIR="$HOME/Library/Caches/uv-ci/$CI_PIPELINE_ID"
export UV_DEFAULT_INDEX="https://pypi.org/simple"
export UV_HTTP_TIMEOUT=180
export UV_HTTP_CONNECT_TIMEOUT=45
export UV_HTTP_RETRIES=8
export UV_CONCURRENT_DOWNLOADS=12
export UV_CONCURRENT_INSTALLS=4
export UV_CONCURRENT_BUILDS=2
uv --version
ミラーへ一時切替(切り分け用)
export UV_DEFAULT_INDEX="https://mirrors.aliyun.com/pypi/simple/"
# 検証後、公式へ戻す
export UV_DEFAULT_INDEX="https://pypi.org/simple"

③ 跨境ネットワークの失敗モードと排障(TLS・証明書・プロキシ)

1

TLS 検査プロキシ: ブラウザは通るが uv だけ失敗 → UV_NATIVE_TLS=1 または UV_SYSTEM_CERTS=1(macOS キーチェーン)を試し、ダメなら SSL_CERT_FILE=/path/to/ca.pem

2

プロキシ: HTTPS_PROXYHTTP_PROXYNO_PROXY(社内インデックス・localhost)を揃える。ALL_PROXY を使う場合は二重設定に注意。

3

ミラー遅延/不整合: 429 や欠損ファイルは公式 UV_DEFAULT_INDEX=https://pypi.org/simple に一時切替えて再現性を確認。

export HTTPS_PROXY="http://proxy.example.com:8080"
export NO_PROXY="localhost,127.0.0.1,pypi.internal.example"
export UV_NATIVE_TLS=1

requirements.lockpyproject との整合と CI 再現ステップ

ロックは「更新 PR」と「インストールジョブ」を分離します。CI 本番は 常に frozen、バンプは開発者マシンまたはボットで uv lock だけが書き換わるようにします。

  • 1. Python 版固定:uv python pin 3.12 または .python-version をコミット。
  • 2. ロック鮮度:pyproject.toml 変更は uv lock 専用 PR に限定し、CI 本番は uv sync --locked のみ(齟齬があれば失敗)。
  • 3. 同期:uv sync --locked --no-dev(本番相当)。
  • 4. requirements 派生:uv pip compile pyproject.toml -o requirements.lockuv pip sync requirements.lock
  • 5. ログに uv --versionUV_DEFAULT_INDEX のホスト名のみ(認証情報は出さない)を出す。
GitHub Actions の env
env:
  UV_HTTP_TIMEOUT: "180"
  UV_HTTP_RETRIES: "8"
  UV_CONCURRENT_DOWNLOADS: "12"
  UV_CACHE_DIR: /tmp/uv-cache-${{ github.run_id }}

⑤ FAQ(キャッシュ汚染・プラットフォーム wheel・私有インデックス併用)

キャッシュ汚染: 共有 Runner では UV_CACHE_DIR をパイプライン ID で分離。異常時のみ UV_NO_CACHE=1 で切り分け。

プラットフォーム wheel: ロック生成環境と CI の OS/アーキテクチャ/Python を一致させる。Apple Silicon リモート Mac なら arm64 前提でドキュメント化。

私有インデックス混在: UV_DEFAULT_INDEX を社内ミラーにし、公開パッケージは UV_INDEX で PyPI を追加するか、tool.uv.index で名前と URL を宣言。UV_INDEX_STRATEGYfirst-index など監査に合う値に固定し、unsafe-best-match は必要最小限に。

構造化データの FAQPage と同内容を短く要約しています(検索snippet 用)。

まとめ:跨境 Python CI は「インデックス契約+ロック一本化」が最短

並列数を上げる前に UV_HTTP_TIMEOUTUV_HTTP_RETRIES を伸ばし、UV_CACHE_DIR でキャッシュ境界を決めると、リモート Mac でも再現性とスループットの両立がしやすくなります。同系列の Rust・Cargo マトリクスGit/Homebrew/npm プル安定性 FAQと併せて運用ルールを揃えると、パイプライン全体が安定します。

英語の関連読み物(ログイン不要):Git/Docker プル加速ガイド(英語)Git・npm・CI キャッシュ戦略(英語)ブログ一覧MacPull ホームからも辿れます。料金・ヘルプはログイン不要で料金ページヘルプセンターをご確認のうえ、チームの帯域と並列度に合うプランで購入ページからお試しください。

Python・ML CI

跨境でも uv sync --locked を安定させるなら、ノード位置とキャッシュ設計が鍵です

MacPull のリモート Mac(Apple Silicon)でビルド環境を揃え、低遅延回線側で wheels をまとめて取得しやすくできます。プラン比較とドキュメントはページ上でご覧いただけます。

24時間以内デリバリー 複数リージョン いつでも解約可