🌩️

Cloud Functions にプライベートモジュールを使った Go 関数をデプロイしようしたらハマった

2022/02/20に公開

一体、何が起きてるんだ……?

一体何にハマったのか?

具体的には リポジトリが非公開 な 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 vendorvendor ディレクトリを作成し、そこへ example.com/pkg をまるっとコピーする

と言う手段を取りました。

具体的には go mod vendorvendor ディレクトリを構成した後で、

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 のビルドシステムがサポートしていないから です。

なお関連してそうな情報はこの辺りです:

https://issuetracker.google.com/issues/184141587?pli=1

https://stackoverflow.com/questions/66494835/google-cloud-function-using-internal-private-function

色々推察するに Cloud Functions の go116 runtime ビルダーは、内部で go mod tidy に相当する 外部モジュールを取得する 機構が有り、それが非公開な同一リポジトリへの import に対しても適用されているのではないか? と私は思ってます。

おわりに

まぁ対処法が分かってしまえば大したことは無いのですが、

Cloud Functions で Go の非公開モジュールを使う場合には go mod vendor を使う

と覚えておくと良いのかもしれません。

※ ちなみにこれで私は半日ぐらい溶かしました。ナンテコッタイ……。

GitHubで編集を提案

Discussion