tl;dr
- GAE/GoのCI/CDでCloud Buildを使う
-
aetestを使ったtestを実行するため、goapp testをCloud Build上で実行したい - 最新のGCP SDKではgoappを簡単には使えなくなっているので、
gcr.io/cloud-builders/gcloudを使う場合ひと工夫必要である
goapp test
GAE/Goでappengine.NewContextに依存したtestを実行するためには、aetestが必要になります。
aetestを使ったtestを実行するためにはgoapp testが必要となります。
Cloud Build上のGCP SDK
CI/CDをCloud Buildで行います。
ほぼGithubのprivate repositoryであってもほぼ無料で使用できるのと、GAEへのdeployなどIAMで権限管理できるのでGCP上にアプリケーションを構築するのであれば使わない理由はないといえます。
Cloud BuildでGCP SDKを使ったbuild pipelineを構築する場合、gcr.io/cloud-builders/gcloudを使うことになると思います。
これは割と最新のGCP SDKがinstallされたimageになります。
ただ最近のSDKだとapp-engine-go componentをinstallしていても、goappは簡単には使えないようになっています。
これはgcr.io/cloud-builders/gcloudであっても同様で、goapp自体存在はしているものの、PATHが通ってなかったり、実行フラグが立っていないので使うにはひと手間必要となります。
goappのpathを調べる
gcr.io/cloud-builders/gcloud上でgoappがどこに存在しているのかを調べるために、gcr.io/cloud-builders/gcloudを手元にpullしてきて入ってみます。
$ docker run --rm --name gcloud --entrypoint bash -it gcr.io/cloud-builders/gcloud
root@99f4e01f618f:/# which gcloud
/builder/google-cloud-sdk/bin//gcloud
root@99f4e01f618f:/# ls -l /builder/google-cloud-sdk/platform/google_appengine/ |grep goapp
-rw-r--r-- 1 root root 4798 Jul 14 03:17 goapp
ありました、/builder/google-cloud-sdk/platform/google_appengine/goappです。
ただ実行権限はついてませんね。
まあgoapp自体はただのpythonスクリプトなので、python経由で叩けば問題なしです。
cloudbuild.yamlに記述
これまで調べた内容を元に以下1のような感じになります。
steps:
- name: gcr.io/cloud-builders/gcloud
env:
- 'GOPATH=/workspace/gopath'
entrypoint: python
args: ['/builder/google-cloud-sdk/platform/google_appengine/goapp', 'test', './app']
id: goapp-test
GOPATHを設定しているのは、gcloud deployでGAEのdeployをするためにGOPATHをいじる2からです。
またいまやっているプロジェクトではGAEからFirestoreとCloud Storageにアクセスしており、testでもこれらのAPIを使う3ようにしています。そのため、serviceAccountKey.jsonを渡してあげる必要があります。
KMSで暗号化したserviceAccountKey.jsonを事前にserviceAccountKey.json.encなどとしてrepositoryにaddしておきます。
これをCloud Build上でdecryptしてtestで使うようにします。
steps:
- name: gcr.io/cloud-builders/gcloud
args:
- kms
- decrypt
- --ciphertext-file=secrets/serviceAccountKey.json.enc
- --plaintext-file=secrets/serviceAccountKey.json
- --location=global
- --keyring=demo-keyring
- --key=demo-key
id: decrypt-service-account
waitFor: ['-']
- name: gcr.io/cloud-builders/gcloud
env:
- 'GOPATH=/workspace/gopath'
- 'GOOGLE_APPLICATION_CREDENTIALS=/workspace/secrets/serviceAccountKey.json'
entrypoint: python
args: ['/builder/google-cloud-sdk/platform/google_appengine/goapp', 'test', './app']
waitFor: ['decrypt-service-account']
id: goapp-test
事前にgcloud kms4でrepository上のserviceAccountKey.json.encをdecrypt5しておきます。
decryptしたserviceAccountKey.jsonはGOOGLE_APPLICATION_CREDENTIALSで指定することでcloud.google.com/go6から透過的に使えるようになります。
-
別途
goappに実行権限をつけて、PATHも通したimageを用意してGCRにpushしておけば簡単に使えますが、gcr.io/cloud-buildersはCloud Build上でcacheされていて高速に使えるので、gcr.io/cloud-builders/gcloudを使います。 ↩ -
GAE/Go (+dep) で gcloud app deploy する為の構成を参考にしてます。事前にsymlinkを作ってあげる必要があります。 ↩
-
google-cloud-go-testingにFirestoreのmockはないのと、Cloud Storageのmockも使いにくかったので。。。 ↩
-
keyring,keyは適当です ↩ -
事前にIAMでCloud Build用のサービスアカウントにKMSの権限をつけておく必要があります ↩