Goで開発途中のプライベートモジュールを参照する方法
💡 はじめに
先日インターンの業務で開発途中のプライベートモジュールを参照したいという場面に出会した。具体的には以下のようなことを実現したかった。
- モジュールAとモジュールBがある
- モジュールA内部でモジュールBを呼び出している
- モジュールBで開発ブランチ(develop)を切って新しい機能を追加した
- mainブランチにはマージしていない
- モジュールAで開発ブランチ(develop)を切って、モジュールBの新機能を呼び出して動作を確認したい←やりたいこと
以下では、上記の実現方法と解説を行う。
🛠️ 方法
モジュールB: github.com/yagikota/private-repo-B
モジュールBのコミットハッシュ: 6f10de1
プライベートレポジトリ: github.com/yagikota
とした時
GOPRIVATE=github.com/yagikota go get github.com/yagikota/private-repo-B@6f10de1
でモジュールAのgo.mod
にモジュールBを追加。
module github.com/yagikota/repo-A
go 1.20
+ require github.com/yagikota/private-repo-B v0.0.0-20230504111014-6f10de185850 // indirect
+ github.com/yagikota/private-repo-B v0.0.0-20230504111014-6f10de185850 h1:W8MOZqBFfCfX4KSuxiPC9meARqHASZC+18eJ5qNzfSY=
+ github.com/yagikota/private-repo-B v0.0.0-20230504111014-6f10de185850/go.mod h1:MzW6pqC7RzhR/iH8/MFBtoAn9FIlEEbo3fLYLXeqRAY=
さらに、go mod tidy
でモジュールBが依存しているモジュールをgo.mod
、go.sum
の整理。
module github.com/yagikota/repo-A
go 1.20
- require github.com/yagikota/private-repo-B v0.0.0-20230504111014-6f10de185850 // indirect
+ require github.com/yagikota/private-repo-B v0.0.0-20230504111014-6f10de185850
+ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+ github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/yagikota/private-repo-B v0.0.0-20230504111014-6f10de185850 h1:W8MOZqBFfCfX4KSuxiPC9meARqHASZC+18eJ5qNzfSY=
github.com/yagikota/private-repo-B v0.0.0-20230504111014-6f10de185850/go.mod h1:MzW6pqC7RzhR/iH8/MFBtoAn9FIlEEbo3fLYLXeqRAY=
+ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
以上で、開発途中のプライベートモジュール(github.com/yagikota/private-repo-B
)を別モジュール(github.com/yagikota/repo-A
)参照することができるようになる。
🎓 解説
go getについて
そもそも、go get
って何をしているのか?これを理解するには、以下の2つのサービスについて理解する必要がある。
proxy.golang.org(Module Mirror)
Goモジュールのダウンロード要求に対して、GitHubなどのVCSからではなくキャッシュされたモジュールを返す。
- ダウンロードの高速化
- 可用性の保証(GitHubが落ちていてもダウンロード可能)
といったメリットがある
環境変数はGOPROXY
。デフォルトではGOPROXY="https://proxy.golang.org,direct"
となっている。
sum.golang.org(Checksum Database)
モジュールの検証情報(checksum)を提供するためのサーバー。
- モジュールの整合性の担保
- 不変性の担保(追記型DBなので改竄されない)
といったメリットがある。
環境変数: GOSUMDB
。デフォルトではGOSUMDB="sum.golang.org"
となっている。
これらのサービスが、以下のように連携してgo get
が動作している。
ref: https://jfrog.com/blog/why-goproxy-matters-and-which-to-pick/
これらのサービスは、一般に公開されているソースコードにしかアクセスでない。非公開モジュールに依存する場合は後述するGOPRIVATE
またはGONOPROXY
環境変数を設定する必要がある。
すべてのモジュールをソースリポジトリから直接ダウンロードするようにgoコマンドを構成するには、GOPROXY
をdirect
に設定する。
GOPRIVATEについて
プライベートモジュールのインストールの際には、環境変数GOPRIVATE
の指定が必要。指定しない場合、以下のようなエラーが出る。
go get github.com/yagikota/private-repo-B@6f10de1
github.com/yagikota/private-repo-B@v0.0.0-20230504111014-6f10de185850: verifying module: github.com/yagikota/private-repo-B@v0.0.0-20230504111014-6f10de185850: reading https://sum.golang.org/lookup/github.com/yagikota/private-repo-!b@v0.0.0-20230504111014-6f10de185850: 404 Not Found
server response:
not found: github.com/yagikota/private-repo-B@v0.0.0-20230504111014-6f10de185850: invalid version: git ls-remote -q origin in /tmp/gopath/pkg/mod/cache/vcs/4463a39359f6875ac8c075bfecd48694efdb7232d6f021b58d8c47fb9d8af8d2: exit status 128:
fatal: could not read Username for 'https://github.com': terminal prompts disabled
Confirm the import path was entered correctly.
If this is a private repository, see https://golang.org/doc/faq#git_https for additional information.
開発途中のモジュール参照方法について
方法としては以下の2つ。
- コミットハッシュを指定して参照
- チーム開発などでGitHubでの共有をしたい場合
- replace directiveの使用
- 開発途中のモジュールをGitHubに上げたくない場合
- 例えば、GitHubに上げたくないけど新しいバージョンを触って欲しいときとかにzipで渡して手元で展開して…みたいなので使ったりするらしい
- 開発途中のモジュールをGitHubに上げたくない場合
コミットハッシュを指定して参照
今回は、こちらの方法を採用。
検証レポジトリはこちら(Publicにしている)
replace directiveの使用
A replace directive replaces the contents of a specific version of a module, or all versions of a module, with contents found elsewhere. The replacement may be specified with either another module path and version, or a platform-specific file path.
今回の場合だと、レポジトリrepo-A
と同じディレクトリにprivate-repo-B
をcloseしておき、開発ブランチ(develop
)にcheckoutした後、repo-A/go.mod
を以下のように変更。
module github.com/yagikota/repo-A
go 1.20
+ replace github.com/yagikota/private-repo-B => ../private-repo-B
その後、go mod tidy
を実行。
module github.com/yagikota/repo-A
go 1.20
replace github.com/yagikota/private-repo-B => ../private-repo-B
+ require github.com/yagikota/private-repo-B v0.0.0-00010101000000-000000000000
+ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+ github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
+ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
検証レポジトリはこちら(Publicにしている)
Discussion