Edited at

依存にプライベートレポジトリを含むGAE/Go(go111)をCloud Buildで自動でプロイする


はじめに

go111 の登場で、Cloud Build を使えば設定ファイル1つで自動デプロイ出来るようになったはずでした。


cloudbuild.yaml

steps:

- name: 'gcr.io/cloud-builders/gcloud'
args: ['app', 'deploy', '--project=$PROJECT_ID', 'gae/app/app.yaml']

monorepo なら private repository でも上記の設定でデプロイ出来ます。

しかし、manyrepo をやろうと本体と別の private repository を参照するとデプロイ出来なくなります。

我々が Cloud Build のトリガーに設定するプロセス(以下「Cloud Build(Trigger)」)とは別に、gcloud app deploy によって実行される Cloud Build のプロセス(以下「Cloud Build(GAE)」)があり、後者は go.mod を見つけると依存を自動解決します。

非常に素敵なのですが、sshの鍵だったりトークンだったり何も設定できないため、プライベートレポジトリが go.mod に含まれると必ず失敗します。


前段でgo mod vendorし、go.modをdeployしない

Cloud Build(Trigger) 側で go mod vendor し、更に .gcloudignorego.mod を指定して gcloud app deploy すれば解決します。

vendor ディレクトリごと GCS にアップロードするので、.gcloudignorevendor を含めてはいけません。


まとめ


  1. go111 のプロジェクトを gcloud app deploy すると Cloud Build による deploy が実行される

  2. この際に実行される Cloud Build に対しては何も設定出来ない


  3. go.mod を含む場合、自動で go get し、そこにプライベートレポジトリがあると失敗する


  4. .gcloudignorego.mod を除外指定していれば自動で go get されない

  5. そのかわり、vendor.gcloudignore に指定せず、 go mod vendor 後に gcloud app deploy する


  6. vendor ディレクトリごと Upload され、go get も行われないので deploy は成功する

  7. 一連の作業を Cloud Build で自動化する為の cloudbuild.yaml がこちら


cloudbuild.yaml

steps:

- name: 'gcr.io/cloud-builders/go:alpine'
entrypoint: sh
args:
- -c
- |
mv `find /workspace -maxdepth 1 ! -name go` ./
git config --global url."https://$$GITHUB_TOKEN:x-oauth-basic@github.com/".insteadOf "https://github.com/"
go mod vendor
find /workspace
dir: 'go/src/github.com/YOUR_ORG/YOUR_PROJECT'
env:
- 'GOPATH=/workspace/go'
- 'GO111MODULE=on'
secretEnv: ['GITHUB_TOKEN']
- name: 'gcr.io/cloud-builders/gcloud'
args:
- 'app'
- 'deploy'
- '--project=$PROJECT_ID'
- 'app/app.yaml'
dir: 'go/src/github.com/YOUR_ORG/YOUR_PROJECT'
env:
- 'GOPATH=/workspace/go'
- 'GO111MODULE=off'
secrets:
- kmsKeyName: 'projects/YOUR_GCP_PROJECT_ID/locations/global/keyRings/github-tokens/cryptoKeys/github-deploy-token'
secretEnv:
GITHUB_TOKEN: 'YOUR_ENCRYPTED_GITHUB_TOKEN'

dirmv などで GOPATH に則ったディレクトリ構成にしています。

kmsKeyName に変数埋め込みは利用できないのでべた書きしてください、ご注意を。

.gcloudignore はこんな感じに


.gcloudignore

.gcloudignore

.git
.gitignore
go.mod
go.sum


YOUR_ENCRYPTED_GITHUB_TOKEN の作り方

https://github.com/settings/tokens でトークンを生成し、以下の様に暗号、前述 yaml に貼り付ける

gcloud kms keyrings create github-tokens --location=global --project=YOUR_GCP_PROJECT_ID

gcloud kms keys create github-deploy-token --location=global --project=YOUR_GCP_PROJECT_ID --keyring=github-tokens --purpose=encryption
echo -n $GITHUB_TOKEN | gcloud kms encrypt \
--plaintext-file=- \
--ciphertext-file=- \
--location=global \
--project=YOUR_GCP_PROJECT_ID \
--keyring=github-tokens \
--key=github-deploy-token | base64