Go
GAE
GoogleAppEngine
GoogleCloudPlatform
DEP

GAE/Go (+dep) を gcloud コマンドを使わずに CI でデプロイ

GAE (Google App Engine) のアプリをデプロイする際は通常 gcloud app deploy コマンドを使います

dep を使うと gcloud deploy できない?

しかし、GAE/Go の組み合わせにおいて、dep を使っていると次のようなエラーでデプロイできず困りました。

Updating service [default]...failed.
ERROR: (gcloud.app.deploy) Error Response: [9] Deployment contains files that cannot be compiled: Compile failed:
2018/01/28 01:49:22 go-app-builder: Failed parsing input: package "path/to/project/vendor/google.golang.org/appengine/urlfetch" cannot import internal package "google.golang.org/appengine/internal/urlfetch"

すでにこのエラーについては次の記事で取り上げられていました。

残念ながらまだ修正されてないようです。

そこで、この問題のissue に上がっていた「古い goapp を使う方法」を試してみます。

goapp deploy コマンドを使う

次のページから goapp コマンドを含む古い sdk をインストールできます。

https://cloud.google.com/appengine/docs/standard/go/download#previous-sdk

インストール完了したら、普通に goapp deploy コマンドを打つだけです。

$ goapp deploy -application <PROJECT_ID> -version <VERSION> path/to/app.yaml

これでデプロイに成功!解決!…と思ったのですが、CIで自動デプロイしようとしたときに問題が発生しました

goapp コマンドは gcloud コマンドの認証トークンを読んでくれないので、認証が通らず、CI で自動デプロイできないということでした。

CI の出力を見ると、「ブラウザを開いて認証してね」というメッセージで完全停止してしまっていました。

$ gcloud auth activate-service-account --key-file path/to/secret.json
$ goapp deploy -application *** -version master
Activated service account credentials for: [***@***.iam.gserviceaccount.com]
Updated property [core/project].
08:47 AM Host: appengine.google.com
08:47 AM Application: *** (was: None); version: master (was: None)
08:47 AM Starting update of app: ***, version: master
08:47 AM Getting current resource limits.
Your browser has been opened to visit:

    https://accounts.google.com/o/oauth2/auth?scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fappengine.admin+https%3A%2F%2Fwww.googleapis.com%2Fauth......

If your browser is on a different machine then exit and re-run this
application with the command-line parameter 

  --noauth_local_webserver

Too long with no output (exceeded 10m0s)

appcfg.py update コマンドを使う

goapp コマンドには認証トークンをコマンドで設定するようなオプションがなかったため、goapp が内部で呼び出している appcfg.py コマンドを使います。

こちらのコマンドでは認証トークンを直接指定できるオプション --oauth2_access_token があるので、そこに gcloud auth print-access-token を使って gcloud コマンド側で認証したトークンを持ってくるという方法です。

$ appcfg.py update --application=<PROJECT_ID> --version=<VERSION> --oauth2_access_token=$(gcloud auth print-access-token 2> /dev/null) path/to/app.yaml

これにて無事にCIからのデプロイに成功しました! (⌒▽⌒)

image.png

$ appcfg.py update --application=*** --version=master --oauth2_access_token=$(gcloud auth print-access-token 2> /dev/null) path/to/app.yaml
Activated service account credentials for: [***@***.iam.gserviceaccount.com]
Updated property [core/project].
09:35 AM Host: appengine.google.com
09:35 AM Application: *** (was: None); version: master (was: None)
09:35 AM Starting update of app: ***, version: master

...

09:35 AM Starting deployment.
09:35 AM Checking if deployment succeeded.
09:35 AM Deployment successful.
09:35 AM Checking if updated app version is serving.
09:36 AM Completed update of app: ***, version: master