モノレポで Go Modules を使う
Multi-Module Repository
Go Modules では Git で管理されているリポジトリ内に複数のモジュールを定義することが可能です。*1
これを利用すると、たとえばプロジェクト内で使う Go ツールの依存管理をプロジェクトのコードとは異なる go.mod
で行うことができます。
$ go mod init # create project go.mod $ mkdir tools && cd tools $ go mod init # create tools go.mod $ cat <<EOF // +build tools package tools import ( _ "github.com/rakyll/statik" ) EOF $ go get -tags tools ./... # add tool dependencies to go.mod
このとき、ディレクトリはこのような構造になっています。
. ├── go.mod ├── go.sum └── tools ├── go.mod ├── go.sum └── tools.go
モジュール単位のバージョニング
Go modules はモジュール単位でバージョニングを行うため、モジュールを分ければ当然バージョニングも別々にできるようになります。
Go modules では VCS のタグから prefix を解釈することができ、マルチモジュール構成の場合は prefix を付けることでモジュール単位でバージョニングできます。
prefix はリポジトリ内のパスに対応し、ルートモジュールの prefix は空文字列であるため、単純に v0.1.0
といった見慣れたタグ名になります。
上記のマルチモジュール構成の場合、 tools
のバージョニングには tools
を prefix としてつけ、 tools/v0.1.0
といったタグ名になります。
モノレポと Go Modules
既存のベンダリングツールではリポジトリ単位でしかバージョニングができませんでしたが、Go modules を使うと上記のようにモノレポでも異なるリリースサイクルを持つことができるようになります。
また、Go プロジェクトのモノレポにおいて Renovate *2 のような依存パッケージ・モジュールの更新を行ってくれる bot との相性が悪くなっていました。
たとえば google-cloud-go は、GCP のサービス群のライブラリがすべて置かれているリポジトリですが、従来ではリポジトリ単位でしかバージョニングできなかったため、プロジェクトで使っていないパッケージの更新によりバージョンが上がった場合でも Renovate が動作してしまうといった問題がありました。
しかし、Go modules により必要なモジュールだけを依存対象に含められるようになっため、このような問題は解消することができるようになりました。
google-cloud-go はマルチモジュール構成のお手本としても参考になります。
Releases · googleapis/google-cloud-go · GitHub
今回紹介したことは Go Wiki にも記載されているため、詳しくはこちらを見てみてください。