https://cloud.google.com/cloud-build より引用
ピックアップ Advent Calendar 2018 16日目です。
今日はサーバーサイドエンジニアのinari111がお送りします。
Goを毎日書いていますが、Goの話は出てきません…
adventar.org
弊社ではProtocol BuffersというIDL(Interface Definition Language, インタフェース定義言語)を採用しています。
以前は、protocコマンドでProtoファイルからAPIのドキュメントを生成 -> GCS(Google Cloud Storage)にアップロードする作業を手動で行っていました。
手動でドキュメント生成をするのは辛く、そして忘れてしまうこともあるので、この記事ではCloud Buildを使って自動化するまでを解説したいと思います。
Cloud Buildとは
ビルド、テスト、デプロイなどを実行してくれる従量課金制なビルドサービスです。
1日あたり120分まで無料枠があります。
各ビルドステップはDockerコンテナで実行され、Dockerイメージは公式ビルダー や cloud-builders-community もあるので必要に応じて使うことができます。
ファイル構成
Protoファイルはアプリケーションのソースコードとは別のリポジトリで管理していて、ファイル構成は以下のようになっています。
今回のゴールは、 proto/admin_api/*.proto
proto/core/*.proto
proto/user_api/*.proto
のどれかに変更があったらProtoファイルからAPIドキュメントを生成し、GCSにアップロードをすることです。
.
├── Makefile
├── README.md
├── _doc
│ └── rpc (生成したドキュメントを置く)
├── _docker
│ └── Dockerfile
├── cloudbuild.yaml (ビルドステップを定義)
├── proto
│ ├── README.md
│ ├── admin_api (Admin API用Protoファイル)
│ │ └── aaa.proto
│ ├── core (Admin API, User API両方でimportするProtoファイル)
│ │ └── bbb.proto
│ └── user_api (User API用Protoファイル)
│ └── ccc.proto
└── rtdb
└── hoge_db_schema.yaml (Realtime DatabaseのSchema)
トリガーを作成する
GitHubを選択
その後、対象のリポジトリの選択をします。
トリガーの設定を書いていきます。
GitHubにpushしたときに proto/admin_api
proto/core
proto/user_api
下のどれかのProtoファイルに変更があれば ビルドが実行されるようにしました。
※ proto/**/*.proto
と書いても動かなかったので、下記のように記載しています。
cloudbuild.yamlを作成
cloudbuild.yamlを用意します。CircleCIのconfig.yamlみたいなものです。
各stepをこのように定義しました。
steps:
- name: 'gcr.io/cloud-builders/docker'
dir: "_docker"
args: ['build', '-t', 'gcr.io/$PROJECT_ID/{image名}', '.']
- name: 'gcr.io/$PROJECT_ID/{image名}'
args: ['make', 'gen-proto-doc']
- name: 'gcr.io/cloud-builders/gsutil'
dir: "_doc/rpc"
args: ['-m', 'cp', 'index.html', '${_RPC_DOC_PATH}/${BRANCH_NAME}_${SHORT_SHA}.html']
images: ['gcr.io/$PROJECT_ID/{image名}']
各stepを軽く解説します。
1つ目は、Dockerをビルドします。 dir
で指定したディレクトリにあるDockerfileを対象とし、 gcr.io/$PROJECT_ID/{image名}
というイメージを作成します。
2つ目は、前stepでビルドしたイメージを使い、 make gen-proto-doc
を実行します
gen-proto-doc
は
protoc -Iproto --doc_out=_doc/rpc --doc_opt=html,index.html proto/**/*.proto
を実行するようにMakefileに定義していて、Protoファイルからドキュメントを生成することができます。
結果として _doc/rpc/index.html
が作成されます。
3つ目は gsutilコマンドを使ってGCSにファイルをアップロードします。
BRANCH_NAME
や SHORT_SHA
はcloudbuild.yaml上で使うことができる変数です。デフォルトで使えるものは他にもあるのでこちらを参照してください。https://cloud.google.com/cloud-build/docs/configuring-builds/substitute-variable-values
独自の変数をトリガーの設定ページから登録することもできます。今回はGCSのパスを_RPC_DOC_PATH
として登録していました。
最後の images
を書くことで Container Registryにpushできます。不要だったら記載する必要はありません。
ローカルで検証
cloud-build-localをインストール
gcloud components install cloud-build-local
cloud-build-localをインストールしたら、ローカルで実行することができます。
--configでビルドリクエストファイルを指定
--dryrun=falseでビルドを実行
--pushはビルド中に作成されたイメージをContainer Registry にpushするかどうかです
変数に _RPC_DOC_PATH
を設定しているので --substitutions=_RPC_DOC_PATH=gs://{バケット名}/{パス}
を指定する必要があります。
ローカルから実行する場合に限り、 BRANCH_NAME
や SHORT_SHA
の指定も必要です。
ローカルで実行する場合はこんな感じになります。
cloud-build-local --config=cloudbuild.yaml --dryrun=false --push=false --substitutions=_RPC_DOC_PATH=gs://{バケット名}/{パス},BRANCH_NAME=hoge,SHORT_SHA=aaaaa .
↑を実行するとGCS上にアップロードできました。
開発時の検証やテストはcloud-build-localでだいたい事足りました。
ローカルからビルドを送信
実際にローカルからビルドを送信してリモートでビルドを実行した場合は、以下のコマンドを実行します。
gcloud builds submit --config=cloudbuild.yaml --substitutions=_RPC_DOC_PATH=gs://{バケット名}/{パス},BRANCH_NAME=hoge,SHORT_SHA=aaaaa
ブラウザからビルド実行
ブラウザからも実行可能です。
GitHubへのpushをトリガーにビルド実行
これは書くまでもないですね。
ビルドを実行したくなかったら、[skip ci]
または [ci skip]
をコミットメッセージに書くとビルドがスキップされます。
最後に
- Cloud Buildを使い、APIドキュメントの生成を自動化することができました
- 特定のパスのファイルに変更があった場合のみ処理を実行することができるのは便利です
- 今回は触れませんでしたが、ドキュメントのURLをSlackに通知するのもやっていく予定です
- 他の会社でもProtocol Buffers採用してほしい