GithubActions で CloudRun を CI/CD する
はじめに
GithubActions で CloudRun を CI/CD する方法を紹介します。
CloudRun を CI/CD する記事はいろいろありますが、情報が古かったり、Registry に Push する過程が説明されていなかったりと、ちょっとしたハマりどころがありました。
そこで今回はハンズオン形式で、GithubActions で CloudRun を CI/CD する方法を紹介します。
事前準備
以下の記事の続きから始めます。
まだ行っていない方は前回の記事から行うとハンズオンが進められます
開発環境
- go version go1.20.3 linux/amd64
- VSCode
- Docker version 23.0.4
- Google Cloud SDK 418.0.0
1. GithubActions で CI を行う
ここでは Go のテストを作成して、GithubActions で CI を行います。
1-1. テストを作成する
必要なライブラリをいれます
$ go get "github.com/stretchr/testify/assert"
適当なテストを作成します
$ touch sample_test.go
package main
import (
"testing"
"github.com/stretchr/testify/assert"
)
func Test_Sample(t *testing.T) {
assert.Equal(t, 1, 1)
}
テストを実行します
$ go test
PASS
ok gin-ping 0.011s
1-2. GithubActions の設定を行う
GithubActions につかう設定ファイルを作成します
$ mkdir .github
$ mkdir .github/workflows
$ touch .github/workflows/run.yml
以下の内容を記述します
name: Run CI/CD
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- uses: actions/setup-go@v3
with:
go-version: "1.20"
- name: Cache Go modules
id: cache-go
uses: actions/cache@v3
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Download Go modules
shell: bash
if: ${{ steps.cache-go.outputs.cache-hit != 'true' }}
run: |
go mod download
- name: Run Go tests
run: |
go test
GithubActions で Go のテストを実行する設定ができました。
1-3. GithubActions でテストを実行する
実行するために Push を行います
(リポジトリがない人は作成してください)
$ git add .
$ git commit -m "add test"
$ git push origin main
Github のリポジトリにアクセスして、Actions のタブを開きます
しばらく待っていると、テストが実行されます
テストが成功したら、CI の設定は完了です。
2. GithubActions で CD を行う
ここでは GithubActions で CI したイメージを、CloudRun にデプロイします。
2-1. Artifact Registry への Push を自動化する
GithubActions で Artifact Registry に Push するための設定を行います。
まずは GithubActions で利用するサービスを作成します
$ export PROJECT_ID=作成したプロジェクトのID
$ gcloud iam service-accounts create docker-image-ci --display-name="Docker Image CI" --project=$PROJECT_ID
次に Artifact Registry に Push するための権限を付与します
$ gcloud iam roles create artifactRegistryCIRole --project=$PROJECT_ID --title="Docker image CI Role" --description="Push docker image via CI" --permissions=artifactregistry.repositories.uploadArtifacts --stage=BETA
$ gcloud projects add-iam-policy-binding $PROJECT_ID --member=serviceAccount:docker-image-ci@$PROJECT_ID.iam.gserviceaccount.com --role=projects/$PROJECT_ID/roles/artifactRegistryCIRole
次にサービスアカウントの鍵を作成します
$ gcloud iam service-accounts keys create key.json --iam-account=docker-image-ci@$PROJECT_ID.iam.gserviceaccount.com --project=$PROJECT_ID
コマンドを実行した直下に key.json が作成されます。
この内容は環境変数として GithubActions に登録するので Base64 に変換してクリップボードにコピーします
cat key.json | base64 | xclip -selection c
2-2. GithubActions の設定を行う
GithubActions でリポジトリの「Settings」→「Secrets and variables」→「Actions」に移動します
「New repository secret」をクリックして、以下の内容を入力します
Name | Value |
---|---|
GCLOUD_AUTH | 先ほど Base64 に変換した key.json の内容 |
SERVICE_ACCOUNT | docker-image-ci@$PROJECT_ID.iam.gserviceaccount.com |
PROJECT_ID | 作成したプロジェクトの ID |
次に GithubActions にビルドと Artifact Registry へのプッシュの設定を行います
run.yml
を修正します
name: Run CI/CD
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- uses: actions/setup-go@v3
with:
go-version: "1.20"
- name: Cache Go modules
id: cache-go
uses: actions/cache@v3
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Download Go modules
shell: bash
if: ${{ steps.cache-go.outputs.cache-hit != 'true' }}
run: |
go mod download
- name: Run Go tests
run: |
go test
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
with:
ref: ${{ github.ref }}
- id: "auth"
uses: "google-github-actions/auth@v1"
with:
credentials_json: "${{ secrets.GCLOUD_AUTH }}"
- name: Setup Google Cloud
uses: google-github-actions/setup-gcloud@v1
with:
service_account_key: ${{ secrets.GCLOUD_AUTH }}
project_id: ${{ secrets.PROJECT_ID }}
- name: Configure docker for artifact registry
run: |
gcloud auth configure-docker us-west1-docker.pkg.dev
- name: set TAG
run: |
echo "TAG=$(echo $GITHUB_REF | awk -F/ '{print $NF}')" >> $GITHUB_ENV
- name: Build
run: docker build -t us-west1-docker.pkg.dev/${{ secrets.PROJECT_ID }}/go-api/api-image:${{ env.TAG }} .
- name: Push
run: |
docker push us-west1-docker.pkg.dev/${{ secrets.PROJECT_ID }}/go-api/api-image:${{ env.TAG }}
うまくいきました
Artifact Registry にイメージが Push されました
2-3. CloudRun に自動でデプロイする」
まずはサービスにデプロイするための権限を付与します
GCP を開いて、「IAM と管理」→「IAM」をクリック
作成したサービスアカウントを選択して、一番右の鉛筆マークをクリックします
「別のロールを追加」をクリックして以下を追加します
- Cloud Run 管理者
- Secret Manager 管理者
- サービス アカウント ユーザー
「保存」をクリックします
run.yml
を修正します
name: Run CI/CD
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- uses: actions/setup-go@v3
with:
go-version: "1.20"
- name: Cache Go modules
id: cache-go
uses: actions/cache@v3
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Download Go modules
shell: bash
if: ${{ steps.cache-go.outputs.cache-hit != 'true' }}
run: |
go mod download
- name: Run Go tests
run: |
go test
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
with:
ref: ${{ github.ref }}
- id: "auth"
uses: "google-github-actions/auth@v1"
with:
credentials_json: "${{ secrets.GCLOUD_AUTH }}"
- name: Setup Google Cloud
uses: google-github-actions/setup-gcloud@v1
with:
service_account_key: ${{ secrets.GCLOUD_AUTH }}
project_id: ${{ secrets.PROJECT_ID }}
- name: Configure docker for artifact registry
run: |
gcloud auth configure-docker us-west1-docker.pkg.dev
- name: set TAG
run: |
echo "TAG=$(echo $GITHUB_REF | awk -F/ '{print $NF}')" >> $GITHUB_ENV
- name: Build
run: docker build -t us-west1-docker.pkg.dev/${{ secrets.PROJECT_ID }}/go-api/api-image:${{ env.TAG }} .
- name: Push
run: |
docker push us-west1-docker.pkg.dev/${{ secrets.PROJECT_ID }}/go-api/api-image:${{ env.TAG }}
- name: Deploy
run: |-
gcloud run deploy api-image \
--project=${{ secrets.PROJECT_ID }} \
--image=us-west1-docker.pkg.dev/${{ secrets.PROJECT_ID }}/go-api/api-image:${{ env.TAG }} \
--region=us-west1 \
--service-account=${{ secrets.SERVICE_ACCOUNT }} \
--allow-unauthenticated
新しいイメージでデプロイされたことを確認するために、main.go を修正します
package main
import (
"fmt"
"os"
"github.com/gin-gonic/gin"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
type User struct {
gorm.Model
Id int `gorm:"primaryKey" json:"id"`
Name string `json:"name"`
Age int `json:"age"`
}
func main() {
user := os.Getenv("DB_USER")
password := os.Getenv("DB_PASSWORD")
dsn := fmt.Sprintf("%s:%s@tcp(aws.connect.psdb.cloud)/[DB名]?tls=true", user, password)
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "Deployed",
})
})
r.GET("/users", func(c *gin.Context) {
var users []User
db.Unscoped().Find(&users)
c.JSON(200, users)
})
r.Run() // listen and serve on 0.0.0.0:8080
}
/ping
のレスポンスが変えてみました
実際に GitHub Actions を回してデプロイされるか確認します
$ git add .
$ git commit -m "change response"
$ git push origin main
GitHub Actions は成功したことを確認したら、前回した Curl をもう一度実行してみます
$ curl https://go-api-xxxxxx-an.a.run.app/ping
{"message":"Deployed"}
レスポンスが変わっていました
CD ができていることが確認できました
おわりに
今回は GithubActions で CloudRun の CI/CD を実装しました
あまり GCP は使い慣れていないのですこし権限周りが大変でしたがなんとか快適に使えるようになったので今後利用していきたいです
今回作成したリポジトリは以下になります
Discussion