CloudBuild & GitHub 連携 〜GitHubにpushしたら CloudRun に自動でデプロイする方法  

# やりたいこと＆実行イメージ
今回は、こんな感じのことをやってみました。
参考にしたのはこちらです。
https://cloud.google.com/cloud-build/docs/automating-builds/run-builds-on-github?hl=ja

- pullリクエスト時：　buildを実行
- master への marge 時：　build & Cloud Run へ deploy を実行
　　　![GitHub & Docker 連携.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/7d2f09a5-4907-6610-58c0-24f943896c1a.jpeg)

# はじめの準備

- Cloud Run にUPするソース
- 連携するための GitHub リポジトリ　（今回はpublicのものです。）
- GCPプロジェクト （課金が有効になっているもの）<br>
  ※もちろん、無料お試し中でもできます！
- GCPプロジェクトで Cloud Build、Cloud Run を有効にしておく


## 設定ファイルやソースの準備
以下、諸々の必要なファイルを作成して、連携対象のGitHubリポジトリにpushしておきます。
※そもそもcloudBuild.yamlファイルが存在しないと、CloudBuildが動かないのです・・・
以下を含めたソースはすべてGitHubにUPしてますので、必要に応じてご参照ください。
https://github.com/anyanco/CloudBuild-sample


### CloudBuild 設定ファイル
プロジェクトフォルダの直下に以下の２つのファイルを作成しておきます。
今回は<b>「cloudbuild-sample」</b>という名前で Cloud Run サービスを作成します。

- cloudbuild_build.yaml
- cloudbuild_deploy.yaml

```yaml:./cloudbuild_build.yaml
steps:
# Build the container image
- name: 'gcr.io/cloud-builders/docker'
  args: ['build',
         '-t',
         'asia.gcr.io/$PROJECT_ID/cloudbuild-sample:$SHORT_SHA',
         '.']
```

ここでは、Docker image を build するだけの設定を記載します。
`-t`コマンドでタグの設定をします。
`$SHORT_SHA`は、このbuildを実行するタイミングだけに割り振られるkeyだと思ってください。

cloudbuild.yaml の書き方の詳細は以下を参照ください。
https://cloud.google.com/cloud-build/docs/configuring-builds/create-basic-configuration?hl=ja

```yaml:./cloudbuild_deploy.yaml
steps:
# Build the container image
- name: 'gcr.io/cloud-builders/docker'
  args: ['build',
         '-t',
         'asia.gcr.io/$PROJECT_ID/cloudbuild-sample:$SHORT_SHA',
         '.']

# Push the container image to Container Registry
- name: 'gcr.io/cloud-builders/docker'
  args: ['push',
         'asia.gcr.io/$PROJECT_ID/cloudbuild-sample:$SHORT_SHA']

# Deploy container image to Cloud Run
- name: 'gcr.io/cloud-builders/gcloud'
  args: ['run',
         'deploy',
         'cloudbuild-sample',
         '--image',
         'asia.gcr.io/$PROJECT_ID/cloudbuild-sample:$SHORT_SHA',
         '--region',
         'asia-northeast1',
         '--platform',
         'managed',
         '--allow-unauthenticated']

images:
- asia.gcr.io/$PROJECT_ID/cloudbuild-sample:$SHORT_SHA

```

こちらは以下の３ステップの動作を行います。
　<b>build → push → deploy</b>
なお、pushでは Container Registry への push を表しています。
どこで何をやっているかは、コメントを参照ください。

### Dockerfile
cloudbuild_~.yaml で build時に使用する Dockerfile が必要になります。
こちらの中身です。

```Dockerfile:./Dockerfile
# Use the official Golang image to create a build artifact.
FROM golang:1.14
# Create and change to the app directory.
WORKDIR /go/src
# Copy go.mod & go.sum
COPY go.* ./
# GoModuleを使うため、念の為 GO111MODULE をonにする.
RUN export GO111MODULE=on && go mod download
# 必要なもののみUP.
COPY ./app ./app
# app配下を実行ファイルに変換？
RUN go install ./app
# 実行
CMD ["/go/bin/app"]
```

### その他
その他の`main.go`などの中身に関しては、[こちらのGitHubリポジトリ](https://github.com/anyanco/CloudBuild-sample)をご参照ください。

## GitHub の設定

1.　以下のURLから、GitHub Marketplace にて、Cloud Build APIを有効にします。
　　　https://github.com/marketplace/google-cloud-build

![Greenshot 2020-05-25 15.44.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/33a7ed0f-cdb9-4792-81ae-f3d1e4484f54.png)
こんな画面の下の方。。。
矢印のところをクリックします。
（こちらの画像では有効化済みのため、一部違うところがあるかも）
![Greenshot 2020-05-25 15.46.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/1eb95c72-8e6f-84b1-e6a7-98bf550034db.png)

すると、こんな感じの表示になります。
アカウント名など、表示されている項目をよく確認して、ボタンをクリックします。
　　　![Greenshot 2020-05-22 16.06.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/7fba5b69-5689-acb5-61be-34f5bf940b34.png)


2.　ここで、連携対象のリポジトリを選択して、「Install」をクリックします。
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/d7beb5b1-2d28-c438-6845-da9134c3eab3.png)

※すでにAPIをインストール済みの場合は、こちらの設定から追加が可能です。
![Greenshot 2020-05-25 16.02.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/5625d098-da94-33d0-f44d-b5a6e2c7c7a1.png)

後はもろもろ設定があるかと思いますが、画面にしたがってポチポチしてください。
（キャプチャがあいまい・・・）
設定が完了すると、GCPプロジェクトに飛びます。

## GCPプロジェクトの設定
GitHub側の設定が完了したら、次はGCPプロジェクトの設定を行います。
記載されているプロジェクト名、リポジトリ名が間違いない場合は 「完了」 をクリックします。
記載されているリポジトリ名が異なる場合は 「編集」 を、
プロジェクトが異なる場合は 「＋別のプロジェクトを追加」 をそれぞれクリックします。
![Greenshot 2020-05-25 16.11.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/0eb2ba2f-7c68-8a62-a076-9e0f26933a0c.png)

「編集」をクリックした場合は以下のような画面になります。
対象のリポジトリ名を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/62897051-2ce4-6bab-9079-e2a42f64366d.png)

問題なければ 「リポジトリを接続」 をクリックします。

この画面でトリガーを設定できそうなのですが、なぜかdefaultトリガーの作成しかできません。。。
上の 「トリガー設定」 リンクをクリックしても何も起きず。
というわけで、おとなしく 「pushトリガーを作成」 をクリックします。
（後で気づいたのですが、どうせdefaultトリガーを作成しても後から削除するなら、
「今回はスキップ」を選択しておくと、後から消す手間が省けましたね。。。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/fcd30ecf-5018-36e3-2a2f-baa7a030070d.png)

するとこのように表示されるので、いったん 「完了」 をクリックしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/8e988148-8814-a69e-481e-46c48fe09a08.png)

そうすると、またGitHub側に戻ってきました。
![Greenshot 2020-05-25 16.25.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/ac2b9163-e2f6-4f8e-0fd8-a389d3bab611.png)

これで GitHub と GCP の連携はいったん完了です。

## トリガーの設定
では、先程は default のトリガーしか作成できなかったので、ちゃんとしたトリガーを設定します。

まず、GCPプロジェクトにて、メニューから
<b>Cloud Build > トリガー</b>
に遷移します。

ひとつだけ作成されているのが、先程の default トリガーです。
上部の 「トリガーを作成」 をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/9b96a23a-436a-0419-3d43-4ede807d432a.png)

以下の項目を入力していきます。
説明は必須ではないですが、入力しておくとわかりやすいです。
まずはじめに、pullリクエスト時にビルドを行うトリガーを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/47a218c9-157b-3df4-ec45-4050f2dd5676.png)

また、今回は pullリクエスト時と、marge時で異なる動作をさせたいため、
それぞれのタイミングで実行させたい cloudbuild_~.yaml を設定します。
入力できたら、「完了」 をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/fb63c4f5-bb4b-12b0-8b24-5516919abe1c.png)

同様に、marge時のトリガーも作成します。
作成できたら、defaultトリガーはいらない挙動をしないよう、削除してしまいましょう。
（不安な場合は「無効」にしても大丈夫です。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/0007f885-8477-8bfd-cbdb-1a17935b9c3e.png)

よくよく見ると、「ステータス」 列の隣に 「トリガーを実行」 と記載されているものとされていないものがあります。
イベントが 「pullリクエスト」 となっている場合は実際にpullリクエストした場合でしか動かないのでしょうね、たぶん。

# 確認
ではここまでできたら、実際に確認していきます。

1.　ブランチを作成して、適当に`main.go`に修正を加えます。
2.　１で行った修正をブランチにpushします。
3.　pullリクエストを作成します。
4.　以下のような感じでチェック結果がわかります。
　　緑のマークの上部分が CloudBuild の結果です。
　　下は GitHub側のチェックです。
　　履歴のところ、よく見ると、失敗したら✗になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/3f852d8b-1f66-209a-eb9b-abd92c514da4.png)

５.　GCP側でもビルド状況を確認できます。
　　<b>「メニュー」 > 「Cloud Build」 > 「履歴」</b>
　　緑は成功、赤が失敗。
　　・・・いろいろ試行錯誤したんですよ。。。
　　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/63e5d7dd-c715-001a-a3c9-cc598a7b19c5.png)

６.　Margeします。
　GitHub側はこんな状態です。
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/bc702877-6e95-903b-f1f5-f747acd4389a.png)

  GitHub側にはCloudBuildのその後を知る術はないので、GCPに見に行きます。
　<b>「メニュー」 > 「Cloud Build」 > 「履歴」</b>
　最新が緑なので、成功したようです。
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/cc205533-9264-db5f-3cfd-fc6786aa4214.png)

　次に、Container Registry に push されているかを確認します。
　ばっちりいます。
　ちなみに、このサービス名で登録するのが初めてであっても、勝手にフォルダが作られるので大丈夫です。
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/36c57c1f-1ec8-ebbf-623d-3a0a59ac5c08.png)

　最後は Cloud Run です。
　・・・ちょっと失敗しました。デプロイ先がおかしかったです。。。

　というわけで修正して動かし直しました。
　何回か失敗しているのはご愛嬌ということでｗ
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/13a19f66-e0db-c82a-bd3d-729c9320ce7f.png)

　ビルドが成功しているのを確認できたら、Cloud Run にてサービスができているかのチェック。
　もともとこの名前のサービスはなかったのですが、無事、作成されていることを確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/2d7521c9-be38-24be-e6a5-852a562475c6.png)

# さいごに
　思ったより簡単に連携の設定ができました。
　トリガーも設定項目がわかりやすかったです。ただ、最初にデフォルトしか作成できないのは仕様なのでしょうか？
　（もしかしたら見逃してる？）
　トリガーに関しては、GitHubの操作をもっと細かく設定できそうなので
　（feature/~ で始まるブランチなら○○する、みたいな）
　この辺は設定次第でいろいろできそうです。

　あと、実際に仕事とかで使うならprivateリポジトリになりそうなので、この辺は要調査。