goやpythonで複数のパッケージをmonorepo的に1つのrepositoryで管理する方法について調べていた

調べていたのでメモ。作業結果は以下のリポジトリにある。

github.com

どういうときに欲しくなるか?

どういうときに欲しくなるかと言うと、複数の関心事のそれぞれに対して複数の環境への共通の対応をしたくなったとき。その上その複数の関心事というのが曖昧な場合。

例えば、micro serviceのためのlog基盤を考えてみる。この場合にlogの出力の表現は同様の形式でハンドリングできるような環境だと嬉しい。 ここで、そのようにほしい機能や要件が決まっている場合はgo-logger,python-loggerのように別途repositoryを分けて管理すれば良いかもしれない。 (このように分けた場合にmasterデータや共通の仕様をどこに置くべきか?みたいな話も別途発生しうる)

ただ、その上、この欲しい機能のような何かが未確定で曖昧な状況になっているときにとりあえず1つのrepositoryで管理できるような状況だと嬉しい。 それこそ機能Mかつ言語MでMNだけのrepositoryを作ると言うようなことは避けたいというようなタイミングのとき。

どういうものが欲しいか?

とりあえず以下のことができれば良い

  • 言語ごとにsub packageを切ってそれをpublicにinstallできる形で公開
  • (それぞれのsub package毎のCI)

後者はまだ調べている途中。今回は前者を調べた。また前者は公式のpackage registry (e.g. pypi) などに登録する必要はない。

python

pythonの場合は、pipでインストールするときに、 subdirectory=<dir name> というquery stringをつければ良いようだ。このような感じ。

If your repository layout is:

pkg_dir
├── setup.py  # setup.py for package "pkg"
└── some_module.py
other_dir
└── some_file
some_other_file

Then, to install from this repository, the syntax would be:

$ python -m pip install -e "vcs+protocol://repo_url/#egg=pkg&subdirectory=pkg_dir"

利用例はこちら。foo,barというパッケージを使っている。

$ .venv/bin/python main.py
hello from foo (0.1.1)
hello from bar (0.1.1)

このパッケージ自体はpoetryを使って雑に作った。

requirements.txtの指定が肝。

main.py

import foo
import bar


foo.hello()
bar.hello()

go

goでも同様にgo/foo,go/barというディレクトリ以下にパッケージを作る。 こちらは公開のために <directory name>v<version number> というtagを付けて上げれば良いようだ。

For example, suppose we have a module example.com/repo/sub/v2, and we want to publish version v2.1.6. The repository root corresponds to example.com/repo, and the module is defined in sub/v2/go.mod within the repository. The prefix for this module is sub/. The full tag for this release should be sub/v2.1.6.

利用例

利用例はこちら1

$ go run main.go
hello from foo (0.1.1)
hello from bar (0.1.1)

パッケージはこちら

こちらの肝はこのMakefile

さいごに

あとはgithub actionsでのCIなどの方法を調べておきたい2


  1. 1.15で確認した。1.16でのgo installなどの変化などはまだ把握しきっていない。

  2. 軽く調べた感じpathsで分岐する方法とrepository event dispatchで頑張る方法とstepのoutputsをifで見る方法があるみたい