🙆

Cloud Buildでコミットの差分だけをデプロイする

2024/03/07に公開

概要

Cloud Buildを使用して、前回成功したビルドと現在のビルドの間で変更されたファイルをだけ検出し、デプロイする方法を紹介します。

変更されたファイルをだけをデプロイする必要性ですが、私の場合は、GitHubでBigQueryのDDL(テーブル定義・作成のSQL)を管理しており、変更がpushされるたびに全てのDDLが実行され、テーブルが書き換わるのを防ぐためです。

ステップ

1. 過去のコミット履歴を表示させる

過去のコミット履歴を表示させるために、gcr.io/cloud-builders/gitイメージを使用し、git fetch に --unshallow 引数を渡して、過去の履歴を取得します。

unshallowオプションは、過去の成功したコミット履歴まで遡るために必要なオプションです。

steps:

# 過去のコミット履歴を表示させる
  - name: gcr.io/cloud-builders/git
    args:
      - fetch
      - '--unshallow'

2. 前回成功したコミットを見つける関数の定義

gcr.io/google.com/cloudsdktool/cloud-sdkイメージを使用して、以下の関数を定義します。この関数では、前回成功したコミットを見つけます。

 - name: gcr.io/google.com/cloudsdktool/cloud-sdk
    entrypoint: bash
    args:
      - '-c'
      - |
        # 前回成功したコミットを見つける
        nth_successful_commit() {
          # nth_successful_commit()関数の変数
          local n=$1  
          local trigger_name=$2
          local project=$3
          local trigger_id=$4
          local build_find_limit=50
         
          local nth_successful_build=$(gcloud builds list --filter "buildTriggerId=$trigger_id AND STATUS=(SUCCESS)" --format "value(id)" --limit=$build_find_limit --project $project | awk "NR==$n") || exit 1
          local nth_successful_commit=$(gcloud builds describe $nth_successful_build --format "value(substitutions.COMMIT_SHA)" --project $project) || exit 1
          echo $nth_successful_commit
        }

3. git diffで、変更のあったファイルを検出する

2で作成した関数に、トリガー名・プロジェクトID・トリガー名を渡して、前回成功したコミットを見つけます。
git diffコマンドを使用して、前回成功したコミットと現在のコミットの間で変更されたファイルを取得します。

  - name: gcr.io/google.com/cloudsdktool/cloud-sdk
    entrypoint: bash
    args:
      - '-c'
      - |
        apply_trigger_name=$_APPLY_TRRIGER_NAME
        project=$PROJECT_ID
        previous_commit_sha=$(nth_successful_commit 1 $apply_trigger_name $project $_TRRIGER_ID) || exit 1
        commit_sha=$COMMIT_SHA 
        files=($(git diff --name-only ${previous_commit_sha} ${commit_sha})) || exit 1
        echo "変更のあったファイルは、${files[@]}です"
substitutions:
  _TRRIGER_ID: "" #トリガーID
  _APPLY_TRRIGER_NAME: "" #トリガー名

4. 検出したファイルだけデプロイする

forループを使用して、変更されたファイルを1つずつ処理し、(私の場合)BigQueryにクエリを実行してデプロイします。
cloudbuild.yamlはデプロイの対象外にしています。

  - name: gcr.io/google.com/cloudsdktool/cloud-sdk
    entrypoint: bash
    args:
      - '-c'
      - |
        for file in ${files[@]}; do
            if [ $file = 'cloudbuild.yaml' ]; then
                :
            else
                echo $file
                bq query --use_legacy_sql=false < $file #任意のデプロイコマンドにしてください
            fi
        done

注意点

この辺を見ながら、Cloud BuildにGitHubの認証情報を与える必要があります。認証周りの設定が面倒だったら、GitHubをCSRにミラーリングすれば認証はパスできます。

全てのステップをまとめたコード

https://github.com/odaren/diffelence-deploy

Discussion