poetryマルチレポからpantsモノレポへ移行してみるときのファーストステップ
概要
本記事では、poetryで管理された複数のリポジトリを、pantsモノレポに移行する際、まずは各リポジトリのプログラムを実行・テストするところまでの方法を紹介します。
以下の内容の詳細は本記事では扱いませんが参考になる情報へのリンクを紹介しておきます。(モノレポを意義を考えると、ここからが本番だと思います。)
また、なるべく参考にした公式documentへのリンクを貼るようにしたので、より正確で最新の情報はそちらを参照してください。
本記事では開発環境を以下のように想定します。
- OS: Linux(Ubuntu 22.04)
- IDE: Visual Studio Code
本記事で扱ったサンプルコードは以下を参照してください。
pantsのインストール
Linuxなら以下のようにinstallerのスクリプトをダウンロードして、インストールを実行できます。デフォルトでは~/bin
にpantsバイナリが入るので適宜PATHを設定します。
curl --proto '=https' --tlsv1.2 -fsSL https://static.pantsbuild.org/setup/get-pants.sh | bash
各OSごとの詳細は以下を参照ください。
公式ドキュメント参考箇所へのリンク
リポジトリを構成する
初期構成
以下のような構成を想定します。内容の詳細はリポジトリを参照してください。
内製ライブラリとアプリケーションコード(単体でサービスとして機能するもの)を分けて、シンプルな依存関係を想定しています。
- libs配下に内製ライブラリ(fizzbuzzライブラリ)を入れる。
- projects配下に独立したアプリケーションコードを入れる。
- project_aではfizzbuzzライブラリを参照している。
- project_bではfizzbuzzライブラリを参照していない。
.
├── libs
│ └── fizzbuzz
│ ├── fizzbuzz/
│ ├── pyproject.toml
│ ├── README.md
│ └── tests/
├── pants.toml
├── projects
│ ├── project_a
│ │ ├── pyproject.toml
│ │ └── src/
│ └── project_b
│ ├── pyproject.toml
│ └── src/
公式ドキュメント参考箇所へのリンク
pantsの初期設定を行う
pants.tomlの設定
基本的には公式ドキュメントおよび公式のpythonサンプルリポジトリにある通りになります。
TIPS
- sourceの項目に「"pyproject.toml"」を指定する。
- [source]は、どのディレクトリをソースコードのルートして見るかを指定する項目です。
[GLOBAL]
pants_version = "2.17.0"
backend_packages.add = [
"pants.backend.build_files.fmt.black",
"pants.backend.python",
"pants.backend.python.lint.docformatter",
"pants.backend.python.lint.black",
"pants.backend.python.lint.flake8",
"pants.backend.python.lint.isort",
"pants.backend.python.typecheck.mypy",
]
[source]
marker_filenames = ["pyproject.toml"]
[python]
interpreter_constraints = [">=3.9.*"]
enable_resolves = true
default_resolve = "python_default"
[python-bootstrap]
search_path = ["<PATH>", "<PYENV>"]
[python-infer]
# 2.17 is transitioning to a new, faster parser for dependency inference:
use_rust_parser = true
公式ドキュメント参考箇所へのリンク
- https://www.pantsbuild.org/docs/python-backend
- 公式のサンプルPythonリポジトリ:https://github.com/pantsbuild/example-python/blob/main/pants.toml
BUILDファイルの設定
pantsは各フォルダにBUILDというテキストファイルを設置する必要があります。手動で行うのは大変なので、以下のコマンドで生成します。今は特に指定しませんが、BUILDファイルの内容を変更することで、パッケージ化の詳細指定などを行うことができます。
pants tailor ::
TIPS
-
:
は、「そのディレクトリ内のすべてのファイル(サブディレクトリは含めない)」という意味 -
::
は、「そのディレクトリ内およびそのサブディレクトリ内のすべてのファイル」という意味
公式ドキュメント参考箇所へのリンク
動作確認
まずは各コードを動かしてみる
poetryと異なり仮想環境を明示的に作る必要はありませんが、依存関係を解決するためにlockfile
というpants固有のファイルを作成する必要があります。
lockfile
を作成するには以下を実施します。
pants generate-lockfiles
-
project_a
のアプリケーションを動かす
pants run projects/project_a/src/main.py -- --start=0 --stop=100 --show-fizzbuzz
- FizzBuzzのコードをテストする
pants test libs/fizzbuzz::
TIPS
-
--
のあとにソースコードの実行時の引数パラメータを与えることができる。 - 3rdpartyライブラリの依存関係は、pyproject.tomlからpantsが解決する
- 内製ライブラリ(libs配下)かどうかは、pants.tomlの[source] 項目の指定で特定できるライブラリかどうかで、pantsが自動的に判断する
実行環境を確認してみる
pantsでコードを実行するとpex形式の実行環境が一時的に生成されます。デバッグとしてその実行環境を確認したい場合は、以下のように--keep-sandboxes=always
をつけて実行します。
pants --keep-sandboxes=always lint projects/project_a/src::
実行時にsandboxの場所が表示され、自動的には削除されなくなります。通常は/tmp/sandbox-xxxx
(xxxxはハッシュ値)という場所に保存されます。
公式ドキュメント参考箇所へのリンク
実行環境を出力してみる
今回は、以下のコマンドで出力できます。
pants export --py-resolve-format=symlinked_immutable_virtualenv --resolve=python-default
TIPS
-
--py-resolve-format=symlinked_immutable_virtualenv
はイミュータブルな環境として出力するOptionになります。 - 環境の切り替えを行う場合、
--resolve
キーワードで指定します。
公式ドキュメント参考箇所へのリンク
pex形式でパッケージングする
BUILDファイルに設定を追記します。例えばproject_b
直下のBUILDファイルに以下を追記します。
poetry_requirements(
name="poetry",
)
+ pex_binary(
+ name="project_b",
+ entry_point="src/app.py",
+ )
その後、以下を実行することでdist
フォルダにpex形式のファイルが出力されます。
pants package projects/project_b:project_b
公式ドキュメント参考箇所へのリンク
IDE設定
ここまででコードの動作は確認できましたが、このままではLinterやFormatterなどが効かないため不便です。
Linter・Formatterの設定
LinterやFormatterのバイナリパスを指定します。
以下を実行し、LinterやFormatterのバイナリを出力します。通常はdist
フォルダに出力されます。
pants export
Visual Studio Codeであれば、.vscode
に設定用のJSONを用意しておくとよいでしょう。
{
"python.linting.flake8Enabled": true,
"python.linting.flake8Path": "dist/export/python/virtualenvs/tools/flake8/bin/flake8",
"python.formatting.blackPath": "dist/export/python/virtualenvs/tools/black/bin/black",
"isort.path": [
"dist/export/python/virtualenvs/tools/isort/bin/isort"
],
"python.linting.mypyPath": "dist/export/python/virtualenvs/tools/mypy/bin/mypy"
}
公式ドキュメント参考箇所へのリンク
内製ライブラリへのパス
libs
内の内製ライブラリを使用する際、IDEはライブラリがどこに存在するのか分からないため、インテリセンスが効かず不便です。その際は、PYTHONPATHを上書きするファイル.env
を用意します。
ROOTS=$(pants roots)
python3 -c "print('PYTHONPATH=\"./' + ':./'.join('''${ROOTS}'''.split('\n')) + ':\$PYTHONPATH\"')" > .env
なお、このままだとisortによるimport順序修正の際、内製ライブラリがアプリケーションコードと同じ階層にあると判断され、import順序が本来想定しない形になります。そのため、.isort.cfg
に以下の設定を追記しておくとよいです。
known_first_party=fizzbuzz
公式ドキュメント参考箇所へのリンク
その他
複雑な依存関係の解決
一般にモノレポでは数百単位のライブラリ、プロジェクトを扱うこともあり依存関係が複雑化します。本記事ではpantsによって自動的に依存関係を解決していましたが、プロダクトの種類によっては自分たちでより詳細なコントロールをすることが適切な場合があります。
公式ドキュメントではLockfileを使った方法が推奨されています。
Lockfileは人間が解釈しやすいファイルではないため、よりメンテンナンス性の高い、pip-compileを使った方法を提案されているのが以下の記事になります。
変更箇所に応じて実行するCIを選択する
開発体験を損なわないために、変更箇所に応じて実行するCIジョブを選択する必要があります。本記事では紹介しませんが、モノレポを導入時には必ず検討する必要があります。
公式ドキュメント参考箇所へのリンク
以上でpantsによるプログラムの実行までできるようになりました。CIの設定などはまた別の記事で紹介できたらと思います。
Discussion