Cloud Functions にプライベートモジュールを使った Go 関数をデプロイしようしたらハマった
一体、何が起きてるんだ……?
一体何にハマったのか?
具体的には リポジトリが非公開 な Go 関数において、Cloud Functions へ登録する関数が同一リポジトリ内の関数を import
していると、 import
したモジュールの名前解決が出来ずに Cloud Functions のデプロイに失敗する、と言う感じです。
実際に遭遇した例を上げると、
example.com/ ← リポジトリ全体が非公開
main.go ← これが `pkg/func/action` と `pkg/lib/mod` 等を import している
go.sum
go.mod
pkg/
func/
action/
action.go
lib/
mod/
mod.go
と言う状況下において Go 関数内で import "example.com/pkg/func/action"
しても、Cloud Functions のビルドシステムで前述のモジュールの名前解決が出来ない、と言うのが今回ハマった事柄です。
※ この問題が起きる関数は terraform + terranix を使って自動デプロイしようとしていました。
私が取った解決方法
それでこれを解決するためにどうしたかと言うと、これは、
go mod vendor
でvendor
ディレクトリを作成し、そこへexample.com/pkg
をまるっとコピーする
と言う手段を取りました。
具体的には go mod vendor
で vendor
ディレクトリを構成した後で、
example.com/
main.go
go.sum
go.mod
pkg/ ← このディレクトリ以下を↓
func/
action/
action.go
lib/
mod/
mod.go
vendor/
.../
example.com/
pkg/ ← ここへコピー
func/
action/
action.go
lib/
mod/
mod.go
.../
と言う様なディレクトリ構造を持たせた zip
ファイルを作成し、それをそのまま Cloud Functions にデプロイしたと言う感じですね。なるほどシンプル。
※ なお私は Cloud Functions にデプロイする zip
ファイルは terranix 側で生成しています。
何故こんなことになったのか
これは一言で言えば(2022年2月現在)Google Cloud Functions のビルドシステムがサポートしていないから です。
なお関連してそうな情報はこの辺りです:
色々推察するに Cloud Functions の go116
runtime ビルダーは、内部で go mod tidy
に相当する 外部モジュールを取得する 機構が有り、それが非公開な同一リポジトリへの import
に対しても適用されているのではないか? と私は思ってます。
おわりに
まぁ対処法が分かってしまえば大したことは無いのですが、
Cloud Functions で Go の非公開モジュールを使う場合には
go mod vendor
を使う
と覚えておくと良いのかもしれません。
※ ちなみにこれで私は半日ぐらい溶かしました。ナンテコッタイ……。
Discussion