最終更新
Cloud Build は GCP のサービスのひとつで、継続的インテグレーション (CI)・継続的デプロイ (CD) を楽に行うためのものです。使い方を基礎から説明し、CI/CD のどう実現するかを説明します。
目次
Cloud Build とは何か
Cloud Build は GCP のサービスのひとつで、継続的インテグレーション (CI)・継続的デプロイ (CD) を楽に行うためのものです。
本質的には Cloud Build は、指定されたジョブ (ビルドステップ) を順番にこなしていき、失敗したらそこで終了する、というだけのサービスです。CI/CD のために使うのが普通ですが、全く関係ないことに使っても問題はありません。
シェルスクリプトとどう違うのか
テスト・デプロイはシェルスクリプトなどで実現することもできます。ではシェルスクリプトと Cloud Build で何が違うのか。
本質的には同じではありますが、Cloud Build にはいろいろな便利機能が用意されていて、ゴリゴリ書かなくてよいのが利点です。具体的な Cloud Build の利点は下記です。
- GitHub などのソース管理システムと連携が可能。リポジトリに push → 自動的にビルドができる。
- ビルドステップは Docker コンテナ内で実行されるため、ステップ間の環境差異が問題になりづらい。例えばアプリ自体は Python2 で書かれているのでユニットテストは Python3 だが、静的解析ツール Python3 で書かれている場合、ユニットテストを Python2 コンテナ、静的解析ツールを Python3 入りコンテナで動かせばよい。
- タスクの並行実行が可能 (時間短縮につながる)。
- Docker コンテナは、Docker Hub や Google Container Registry にあるものに加え、ユーザーグループが作成した便利なコンテナ、さらに自前で準備したコンテナも利用可能。
- 自前コンテナについては、Cloud Build 内でイメージ作成することも可能。
- 完了後 Cloud Pub/Sub にメッセージ送信することができる。Cloud Functions と連携させれば、Slack への通知などができる。
- ビルドステップは、コマンドの終了ステータスが 0 なら OK、0 以外ならエラーと統一されており、エラーチェック漏れが起きにくい。
- ビルド時の Docker コンテナ環境は Google 側で準備するため、GCE インスタンスなどを用意する必要がない。
- Cloud Build により、過去のビルドログが全て残る。
- GCP の認証として IAM が使えるため、認証が楽
繰り返しですが、上記は自前シェルスクリプトなどで実現可能です。しかしながらこれを設計し、コーディングし、テストする工数を考えると、結構な時間がかかるでしょう。Cloud Build にてその時間を節約できます。
Cloud Build がやってくれないこと
Cloud Build がやってくれないことは下記です。テストケースを書いたり、どうデプロイするのかを指示するのは結局は人間の仕事です。
- 作成したプログラムを、よい感じに自動的にテストしてくれる
- 作成したうログラムを、 よい感じに自動的にデプロイしてくれる
Cloud Build の料金・コスト
Cloud Build の料金は下記のとおり、マシンタイプごとに1分あたりの料金が決まっています。
デフォルトの n1-standard-1 の場合、1日あたり 120分は無料ですのでお得です。 なお、10分かかるビルドを 3回、40分かかるビルドを1回動かした場合、合計は 10×3 + 40 =「70分」です。
マシンタイプ | CPU | 料金・費用 | 毎日4時間実行 での1ヶ月料金 (20営業日・ $1=110円・ 税抜) |
n1-standard-1 | 1 | $0.003/分。ただし1日あたり 120分は無料。デフォルトはこれ。 | 1,188円 |
n1-highcpu-8 | 8 | $0.016/分 | 8,448円 |
n1-highcpu-32 | 32 | $0.064/分 | 33,792円 |
試してみよう
まずは Cloud Shell から試すのが一番よいと思います。
Cloud Shell でログイン後、作業用ディレクトリを作成し、cloudbuild.yaml というファイルを作成してください。
mkdir work
cd work
cat <<EOS > cloudbuild.yaml
steps:
- name: 'ubuntu'
args: [ 'ls', '-l']
EOS
作業用ディレクトリの中で、下記コマンドを実行します。
gcloud builds submit .
すると下記のようになります。
% gcloud builds submit .
Creating temporary tarball archive of 1 file(s) totalling 49 bytes before compression.
Uploading tarball of [.] to [gs://myproject_cloudbuild/source/1559904202.89-c95823ea63ee459b8af755e4c94b0ce8.tgz]
Created [https://cloudbuild.googleapis.com/v1/projects/myproject/builds/eac39d3c-eba0-4274-b0fd-88664c6c91d4].
Logs are available at [https://console.cloud.google.com/gcr/builds/eac39d3c-eba0-4274-b0fd-88664c6c91d4?project=123456].
------------------------------------------------------------------------- REMOTE BUILD OUTPUT -------------------------------------------------------------------------
starting build "eac39d3c-eba0-4274-b0fd-88664c6c91d4"
FETCHSOURCE
Fetching storage object: gs://myproject_cloudbuild/source/1559904202.89-c05823ea63ee459b8af755e4c94b0ce8.tgz#1559904204270175
Copying gs://myproject_cloudbuild/source/1559904202.89-c05823ea63ee459b8af755e4c94b0ce8.tgz#1559904204270175...
/ [1 files][ 190.0 B/ 190.0 B]
Operation completed over 1 objects/190.0 B.
BUILD
Pulling image: ubuntu
Using default tag: latest
latest: Pulling from library/ubuntu
Digest: sha256:b36667c98cf8f68d4b7f1fb8e01f742c2ed26b5f0c965a788e98dfe589a4b3e4
Status: Downloaded newer image for ubuntu:latest
total 4
-rw-r--r-- 1 1000 1000 49 Jun 7 10:41 cloudbuild.yaml
PUSH
DONE
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
ID CREATE_TIME DURATION SOURCE IMAGES STATUS
eac39d3c-eba0-4274-b0fd-88664c6c91d4 2019-06-07T10:43:25+00:00 8S gs://myproject_cloudbuild/source/1559904202.89-c05823ea63ee459b8af755e4c94b0ce8.tgz - SUCCESS
ここで Cloud Build のコンソールの履歴を見てみましょう。下記のようにビルド実行の記録が残ります。該当行をクリックすると、実行時のログも残っています。
Cloud Build が何を行ったかというと、こういうことです。
- Cloud Build の「ビルド実行」が開始されると、指定ディレクトリ (ここではカレントディレクトリ) にあるファイル群をまとめて Cloud Build が準備したインスタンスのディスクに展開する。
- Cloud Build は、cloudbuild.yaml に書かれているとおりに step を実行する。
- name: ‘ubuntu’ とあるので、Docker Hub より Ubuntu のイメージを取得し、コンテナを起動する。さらに引数として “ls -l” を渡す。
- Ubuntu のコンテナは指定された通り ls -l を実行する。
次に、下記を cloudbuild2.yaml として保存します。ここではビルドステップを3つ定義しています。
steps:
- name: 'ubuntu'
args: [ 'ls', '-l' ]
- name: 'ubuntu'
args: [ 'sh', '-c', 'echo hoge > xxx' ]
- name: 'centos'
args: [ 'ls', '-l' ]
下記で実行します。デフォルトのビルド構成ファイル名は cloudbuild.yaml ですが、それ以外のファイル名を使いたい場合は –config オプションで指定可能です。
gcloud builds submit --config=cloudbuild2.yaml
この例では、echo hoge > xxx にて新しいファイルを生成しています。また、前半は ubuntu、後半は centos の Docker イメージで実行しています。
それぞれのビルドステップ 1つずつは、別コンテナとして動きます。よって、OS も別、プロセスも別、環境変数も別です。
ただし、作業領域である /workspace は各ビルドステップ間で共有されます。上記例だと、2つ目で生成した xxx というファイルが、3つ目のステップの ls -l でファイルが存在することが確認できます。
ビルドステップの成功失敗判定
各ビルドステップの成功・失敗判定について。コマンドの終了ステータスが 0 なら成功、1 以上なら失敗、という単純なものです。
下記は date コマンド、ls コマンド、date コマンドを順に実行するものですが、ls コマンドは存在しないファイル名を指定しているため、終了ステータスが 1 とエラーになります。そして 3つ目の date コマンドは実行されません。
cat <<EOS > cloudbuild3.yaml
steps:
- name: 'ubuntu'
args: [ 'date']
- name: 'ubuntu'
args: [ 'ls', 'noexistfile']
- name: 'ubuntu'
args: [ 'date']
EOS
gcloud builds submit --config=cloudbild3.yaml
ビルドステップが失敗するとどうなるか。
ビルド履歴にはビルド実行結果は失敗として記録されます。
ビルド詳細では、ls で失敗し、後続ビルドステップが実行されなかったことがわかります。
いろいろなビルドステップの書き方
いろいろなビルドステップの書き方を説明します。
下記は Docker Hub より Ubuntu イメージを取得し、その中で ls -l を実行します。具体的には https://hub.docker.com/_/ubuntu のイメージが使われます。他にも CentOS や Python など様々なコンテナイメージが公開されています。
steps:
- name: ubuntu
args: ['ls -l']
下記は Google が Cloud Build のために準備した「クラウドビルダー」と呼ばれる便利なコンテナから、gsutilを使っています。
steps:
- name: gcr.io/cloud-builders/gsutil
args: ['cp', './file.txt', 'gs://foobar/']
gsutil のイメージには gsutil だけが入っているというわけではありません。下記は gsutil のイメージに含まれている bash を起動し、bash -c ‘コマンド’ にて、カレントディレクトリ変更やコマンド実行などの前処理を経て、gsutil を実行する例です。
steps:
- name: gcr.io/cloud-builders/gsutil
entrypoint: 'bash'
args: ['-c', 'cd foo/bar/ && ./hoge.sh && gsutil cp * gs://foobar/']
成果物 (アーティファクト)
ビルド定義を実行したあと、ファイルを残したいケースがあります。例えば以下のような例です。
- ビルドとデプロイを分離しており、ビルドした後に jar や zip などのファイルを残したい。
- ユニットテスト等で、テスト結果を HTML として出力するツールがある。
Docker コンテナ内で実行され、/workspace もビルドが終了すればなくなってしまいますので、残したいファイルは GCS 等に配置しておく必要があります。
自前で GCS などにコピーしてもよいのですが、アーティファクトと呼ばれる成果物として登録しておけば、GCS 保存を Cloud Build が手伝ってくれるので少し楽になります。
CI/CD の実践
ここまでで Cloud Build は何をしてくれるのかを説明してきました。しかし本当にやりたいことは、CI/CD ですので、例をあげていくことにします
Python 編
まず、Python で足し算を行うスクリプトがあるとします。標準入力から 2つの値を入力させ、足した結果を表示する、というだけのものです。
#!/usr/bin/env python3
def myadd(a, b):
return int(a) + int(b)
def mainwork():
while True:
print("数字を入力してください")
a = input()
print("数字を入力してください")
b = input()
result = myadd(a, b)
print("{} + {} = {}".format(a, b, result))
if __name__ == "__main__":
mainwork()
では上記の上記の myadd メソッドのユニットテストを書いてみましょう。Python においては標準モジュールである unittest が使われることが多いようなので、それにならってみます。
下記がテストコードです。3+5 が 8 になることと、(-3)+(-5) が -8 になることを確認するものです。
#!/usr/bin/env python3
import unittest
import mycalc
class TestMyCalc(unittest.TestCase):
def test_my_add_plus(self):
value1 = 3
value2 = 5
result = mycalc.myadd(value1, value2)
self.assertEqual(8, result)
def test_my_add_minus(self):
value1 = -3
value2 = -5
result = mycalc.myadd(value1, value2)
self.assertEqual(-8, result)
if __name__ == "__main__":
unittest.main()
上記テストは下記で実行できます。
% python3 test_myadd.py
..
----------------------------------------------------------------------
Ran 2 tests in 0.001s
OK
もうちょっと親切に出力させたい場合は、-v オプションをつけることで個々のテストケース名が表示されます。
% python3 test_mycalc.py -v
test_my_add_minus (__main__.TestMyCalc) ... ok
test_my_add_plus (__main__.TestMyCalc) ... ok
----------------------------------------------------------------------
Ran 2 tests in 0.004s
OK
ではこれを Cloud Build にて実行してみましょう。Cloud Build においては、Docker イメージを選ぶ必要があります。python3 が入っている Docker イメージはどれか。よくわかっていないのですが、おそらく Docker Hub にある python イメージなら大丈夫でしょう。
というわけで下記の cloudbuild.yaml を作成します。
steps:
- name: 'python'
args: ['python3', 'test_mycalc.py', '-v']
カレントディレクトリに cloudbuild.yaml、mycalc.py、test_mycalc.py がある状態で、Cloud Build を実行します。
% gcloud builds submit .
(略)
test_my_add_minus (__main__.TestMyCalc) ... ok
test_my_add_plus (__main__.TestMyCalc) ... ok
----------------------------------------------------------------------
Ran 2 tests in 0.001s
OK
(略)
うまくいっているようですね。コマンドラインから python3 test_mycalc.py -v で実行した場合、テストは Cloud Shell 内で実行されます。Cloud Build で実行した場合は、テストは Cloud Build が用意した python コンテナ上で実行されます。
Python + モジュール編
上記は Python プロジェクトが提供する標準の Docker イメージでテストが実現できました。しかしながら標準 Docker イメージで解決できないケースは多々あります。例として、nose というモジュールを使ってみましょう。
Python のテストにおいて標準モジュールである unitetest はよく使用されますが、あくまで簡単なテストを行うのみで、テストフレームワークというほどの位置づけではありません。Python 界隈では nose というモジュールが使われることが多いようです。
nose は unittest の存在を前提とし、複数のテスト・カバレッジ (網羅性) 計測なども行うことができるツールです。nose は標準モジュールではないので、インストールする必要があります。
pip3 コマンドで nose をインストールします。この際、sudo で root 権限を一時的に取得します。
% sudo pip3 install nose
% nosetest -v . --with-coverage --cover-html
test_my_add_minus (test_mycalc.TestMyCalc) ... ok
test_my_add_plus (test_mycalc.TestMyCalc) ... ok
test_my_add_plus_value_error_NG (test_mycalc2.TestMyCalc2) ... ok
Name Stmts Miss Cover
-------------------------------
mycalc.py 12 8 33%
----------------------------------------------------------------------
Ran 3 tests in 0.022s
OK
cloudbuild-nose.yaml を下記のようにします。args にて、nose と coverage をインストールしているのがポイントです。
steps:
- name: 'python'
args: ['bash', '-c', 'pip3 install nose coverage && nosetests -v --with-coverage --cover-html .']
Cloud Build にて実行します。
gcloud builds submit . --config=cloudbuild-nose.yaml
テストが通り、カバレッジ (網羅率) が 33% であることがわかります。
(略)
Installing collected packages: nose, coverage
Successfully installed coverage-4.5.3 nose-1.3.7
test_my_add_minus (test_mycalc.TestMyCalc) ... ok
test_my_add_plus (test_mycalc.TestMyCalc) ... ok
test_my_add_plus_value_error_NG (test_mycalc2.TestMyCalc2) ... ok
Name Stmts Miss Cover
-------------------------------
mycalc.py 12 8 33%
----------------------------------------------------------------------
Ran 3 tests in 0.011s
OK
PUSH
DONE
(略)
Cloud Build HowTo
並列実行するには
ビルド実行自体は、10個まで並列実行可能です。それを超えた分は待ちになりますが、順番に処理されていきます。
ビルドステップはデフォルトでは上から下に順番に実行します。並行実行したい場合、各 step に waitFor を記述することで、どのステップの実行を待つかを指定できます。
例として、下記の依存関係を持つ step があるとします。
これを実現するビルド構成ファイルは下記です。
steps:
- name: 'ubuntu'
id: step1
- name: 'ubuntu'
id: step2
waitFor: ['-']
- name: 'ubuntu'
id: step3
waitFor: ['step1']
- name: 'ubuntu'
id: step4
waitFor: ['step1', 'step2']
- name: 'ubuntu'
id: step5
ポイントは下記のとおり。
- 待つべきステップを waitFor で指定する。参照される側のステップには id を指定しておくこと。
- waitFor には複数のステップを記述可能なので配列 [~] になっている。
- ビルド実行直後に並列実行したい場合は waitFor: [‘-‘] と書く。
- waitFor を記述しない場合、先行するすべてのステップの完了を待ってから実行が開始される (デフォルト)。上記例の step5 は waitFor を記述していないが、あえて書くならば下記と同じである。
- name: 'ubuntu'
id: step5
waitFor: ['step1', 'step2', 'step3', 'step4']
マシンタイプを変更するには
デフォルトでは n1-standard-1 が使われます。他のマシンタイプもありますが、GCE のようにたくさんマシンタイプがあるわけではなく、使えるのは n1-standard-1・n1-highcpu-8・n1-highcpu-32 の3つのみです。
下記のようにビルド構成ファイルに記載します。
steps:
....
options:
machineType: 'N1_HIGHCPU_8'
一時的な変更であれば下記のように gcloud builds submit のオプションとして指定する方法もあります。
gcloud builds submit --machine-type=n1-highcpu-8
なお、毎日 120分の無料枠があるのは n1-standard-1 のみであり、その他のマシンタイプの場合無料枠はないことに注意してください。
タイムアウト設定をするには
デフォルトでは、ビルド全体のタイムアウト設定は 10分 (600秒) です。これを 900秒に延長する例は下記です。
steps:
- name: 'ubuntu'
args: ['sleep', '600']
timeout: 900s
タイムアウトは上記のようにビルド全体に設定することもできますが、各ステップに設定することも可能です。
下記は、ステップ1 で 200秒、ステップ2 で 300秒、ビルド全体で 1000秒のタイムアウト設定を行っています。
steps:
- name: 'ubuntu'
args: ['sleep', '100']
timeout: 200s
- name: 'ubuntu'
args: ['sleep', '100']
timeout: 300s
timeout: 1000s
環境変数
ビルド構成ファイルにて、ファイルを include するには
共通処理を別ファイルに切り出しておいて、個別のビルド構成ファイル cloudbuild.yaml から共通処理を include したい、というケースがあるかもしれません。
しかしながら 2020/1 現在、そのようなことはできないようです。なんらかのテキスト処理ツールを使い、ひな形から最終的な cloudbuild.yaml を自動生成するしかないと思われます。
ビルドトリガ設定
ビルドトリガとは何か
ビルドトリガを使うことで git からの clone や、git に push した際に自動的にビルドやリリース作業を行うなどの自動化が可能になります。
これまで見てきたように、Cloud Build はビルドトリガなしでも実行することはできます。しかしながら、スクリプトなど必要なファイル群をローカルに配置した上でビルド実行を行う必要があり、面倒です。そこを補完してくれるのがビルドトリガです。
ビルドトリガを作成してみよう
ビルドトリガは、Cloud Build コンソールから設定するのが簡単です。
(書きかけ)
複数のビルドトリガで同じビルド定義ファイルを使う
さらなるメリットとして、複数のビルドトリガを用意し、同じビルド定義ファイルを呼び出す、というものがあります。
例えば、バッチプログラムが3つあり下記のようなソース構成になっているとします。
- hoge/
- tools/
- build.sh
- deploy.sh
- batch1/
- batch2/
- batch3/
- tools/
各バッチのビルドとデプロイ方法は下記のように、各ソースディレクトリで build.sh と deploy.sh を実行するだけ、とします。
cd $HOME/hoge/batch1/
../tools/build.sh && ../tools/deploy.sh
cd $HOME/hoge/batch2/
../tools/build.sh && ../tools/deploy.sh
cd $HOME/hoge/batch3/
../tools/build.sh && ../tools/deploy.sh
ここで batch1・batch2・batch3 それぞれのビルドとデプロイを Cloud Build で実現するにはどうするか。
batch1 用のビルド定義ファイル、batch2 用のビルド定義ファイル、batch3 用のビルド定義ファイルを作成することはもちろんできますが、似たようなビルド定義ファイルになってしまい、メンテナンス性が落ちてしまいます。
そのような場合、ビルド定義ファイルは 1つだけ作成し、ビルドトリガを3つ作成することをおすすめします。
ビルド定義ファイルは下記のようにします。バッチ名を変数 _BATCH_NAME で受け取るのがポイントです。
# builds/build-and-deploy.yaml として配置
steps:
- name: 'ubuntu'
entrypoint: 'bash'
args:
- '-cvx'
- |
cd hoge/${_BATCH_NAME} && ../tools/build.sh
- name: 'ubuntu'
entrypoint: 'bash'
args:
- '-cvx'
- |
cd hoge/${_BATCH_NAME} && ../tools/deploy.sh
substitutions:
_BATCH_NAME:
そしてビルドトリガを 3つ作成します。
- ビルドトリガ その1: batch1 のビルド & デプロイ
- ビルド定義ファイル builds/build-and-deploy.yaml
- _BATCH_NAME: batch1
- ビルドトリガ その2: batch2 のビルド & デプロイ
- ビルド定義ファイル builds/build-and-deploy.yaml
- _BATCH_NAME: batch2
- ビルドトリガ その3: batch3 のビルド & デプロイ
- ビルド定義ファイル builds/build-and-deploy.yaml
- _BATCH_NAME: batch3
3つのビルドトリガは実行するビルド定義ファイルは同じですが、ビルド定義ファイルに渡す変数が異なります。
このようにビルド定義ファイル 1つに対し、複数のビルドトリガを準備しておくことでビルド定義を集約し、メンテナンスがしやすくなります。
ビルドをスキップするには
ビルドトリガが設定済のとき、コメント修正などの軽微な修正の場合はビルドさせたくない場合があります。Git のコミットメッセージに “[skip ci]” または “[ci skip]” を含めることで、トリガが起動しなくなります。
ビルドトリガの無効化
ビルドトリガは無効化することが可能です。ここで言う無効化とは「GitHub等での push を契機としてビルド実行をする自動連携機能を止める」ということなので、 無効化した場合でも、手動でのビルド実行や gcloud beta builds trigger run による実行は可能です。
ビルドトリガをコマンドラインから実行するには
gcloud beta builds triggers run を使います。
gcloud beta builds triggers run [トリガID] \
--branch=[BRANCH名]
上記の「トリガID」は gcloud beta builds triggers list で確認することができます。2019/07 時点では GCP コンソール (管理画面) 上ではトリガIDは確認できないように見えます
また、ブランチ名は指定必須です (master, develop, feature/foobar など)。
ビルド構成ファイルから、他のビルドトリガを実行するには
下記のようにします。
steps:
- name: gcr.io/cloud-builders/gcloud
args: ['beta', 'builds', 'triggers', 'run', '[トリガID]', '--branch=${BRANCH_NAME}']
ビルドトリガの export・import
ビルドトリガは Cloud Console 上から GUI にて設定・更新できますが、gcloud コマンドで export・import することも可能です。
まずは import からです。mytrigger.yaml にトリガ情報を記述し、それを gcloud beta builds triggers import するだけです。
$ cat mytrigger.yaml
name: my-trigger
github:
owner: GoogleCloudPlatform
name: cloud-builders
push:
branch: .*
$ gcloud beta builds triggers import --source=mytrigger.yaml
Cloud Build 結果を Slack に通知する
Cloud Build の終了時に結果を Slack 通知する方法を説明します。
その1: ビルド定義ファイルの最終stepで通知するやり方
まず 1つ目のやり方として、ビルド定義ファイルの最後のステップで、Slack 通知を行うというやり方があります。
例えば以下のようなコマンドで、Slack チャンネルにメッセージ投稿ができるとします。
$ curl -XPOST -d "token={token}" -d "channel={チャンネル名}" -d 'text=<!channel> 処理終了です' https://slack.com/api/chat.postMessage
上記を sh スクリプト化し、ビルド定義ファイルの最後に下記のように呼び出すことで Cloud Build 終了時に Slack 通知が行えます。
steps:
- (何かしらの処理)
- name: ubuntu
args: ['./send-slack-message.sh']
この方法は簡単ではあるのですが、欠点は前のステップでエラーになった場合、上記スクリプト実行のステップが処理されない、ということです。
やはり処理が成功したのか失敗したのかを通知したいものですので、このやり方はおすすめはできません。
その2: Cloud Pub/Sub + Cloud Functions で結果を通知する。
Cloud Build の処理が完了すると、Cloud Pub/Sub にメッセージを発行する機能があります。こちらの方法であれば、途中のステップで失敗したとしても Pub/Sub メッセージは必ず発行されますので、成功・失敗いずれの通知も可能です。
例として、Cloud Build → Pub/Sub → Cloud Functions → Slack 通知する例をあげておきます。
Cloud Functions を作成する際に Pub/Sub トピック名を指定することで、Pub/Sub サブスクリプションが自動的に作成されます。
参考:https://cloud.google.com/cloud-build/docs/configure-third-party-notifications?hl=ja
トピック・サブスクリプション
Cloud Build が送信する Pub/Sub トピックは、1つだけで、トピック名は “cloud-builds” 固定です。Cloud Build API 有効化の際、トピックが自動的に生成されます。
トピックには好きなサブスクリプションをぶらさげることができますので、下記のような構成にすることも可能です
- トピック cloud-builds
- サブスクリプション ビルド結果 Slack 通知用
- サブスクリプション 静的解析結果 Slack 通知用
- サブスクリプション メール送信用
- サブスクリプション 日次ビルドサマリ通知用
ただし、Cloud Build の結果はすべてのサブスクリプションに同じものが送信されますので、各サブスクリプションでの取捨選択が必要になります。
ビルド定義ごとに任意の Pub/Sub トピックを指定できるようになるといいんですが。
output への出力
Pub/Sub メッセージ内には各stepの成功・失敗は記録されているのですが、標準出力・標準エラー出力は含まれていません。そのような場合、ビルドステップ内で $BUILDER_OUTPUT/output に出力することで、Pub/Sub メッセージにその出力が載りますので、Slack 通知などに使うことができます。
例えば下記のようなビルド構成ファイルを使うと、
steps:
- name: ubuntu
args: ['bash', '-c', 'ls -l > $BUILDER_OUTPUT/output']
- name: ubuntu
args: ['ls -l']
- name: ubuntu
args: ['bash', '-c', 'date > $BUILDER_OUTPUT/output']
下記のような Pub/Sub メッセージが出力されます。step 1つめと 3つめの $BUILDER_OUTPUT/output の内容が builStepOutputs 内に入ります。出力されなかった 2つめは null になっています。base64 エンコードされているので、base64 デコードしてから処理しましょう。
results":{
"buildStepOutputs":[
"a29tbW(略)", // step1 の出力 (ls -l)
null, // step2 の出力
"xxx(略)", // step3 の出力 (date)
],