`cloud-builds` TopicをsubscribeするCloud Build Triggerが作成・更新できなくなったので回避策を導入した話

はじめに

今年の3月後半から cloud-builds TopicをsubscribeするGoogle Cloud Build Triggerの作成・更新時にエラーが発生するようになってしまい、構築していたデプロイパイプラインを更新することができなくなりました。Google Cloudのサポートによるとこの仕様変更が元に戻るかはわからないとのことだったため、パイプラインの変更が最小限となるようなワークアラウンドを導入しました。今回はこのワークアラウンドの紹介をしたいと思います。

Cloud Buildの仕様変更の詳細

Google Cloud BuildはTriggerの開始や終了時に cloud-builds という名前のCloud Pub/Sub Topicにイベントを自動的にPushします。コミューンではデプロイパイプラインにCloud Buildを使用しており、トリガー条件としてこの cloud-builds Topicをsubscribeする形式を採用しています。冒頭に書いたとおりですが、3月後半からこの cloud-builds TopicをsubscribeするCloud Build Triggerの作成・更新時にそれぞれ下記のエラーが発生するようになってしまいました。

  • 作成時
    • Failed to create trigger: trigger should not listen on cloud-builds topic
  • 更新時
    • Failed to update trigger: trigger should not listen on cloud-builds topic

Google Cloudのサポートからいただいた下記内容の回答を見てこの挙動が元に戻る可能性は低いと判断し、この後紹介するワークアラウンドを導入することを決めました。

  • Google Cloud内部の不具合を修正するための一時的な処置として cloud-builds を利用するCloud Build Triggerの作成と更新を制限している
  • そのためエラーの発生は意図したものである
  • 問い合わせ時点では仕様が元に戻るかは不明であり、恒久的にどうするかは開発チームが計画中

ワークアラウンドの紹介

今回の仕様変更に追従するための開発リソースは最小限にしたかったためデプロイパイプラインに対する変更が少なく済む方法を検討しました。その結果 cloud-builds Topicのメッセージを別のPub/Sub Topicにコピーし、Cloud Build Triggerはコピー先のTopicをsubscribeするように変更する方式を採用しました。

下記の3点がワークアラウンドの要約となります。

  • cloud-builds をトリガーにするCloud Functionsと、 cloud-builds の内容をコピーする cloud-build-result というPub/Sub Topicを作成する
  • このFunctionsは cloud-builds のメッセージを cloud-build-result という別のPub/Sub Topicへコピーする
  • Cloud Build Triggerは cloud-build-result をsubscribeする形に変更する

またbefore/afterを図にすると下記のようになりました。

ワークアラウンドで使用しているコード

コミューンではフロントエンド・バックエンド開発にTypeScriptを使用しているため、ワークアラウンドもJavaScriptで作りました。

index.js

const { PubSub } = require('@google-cloud/pubsub')
exports.replicate = (event, _context) => {
  const client = new PubSub()
  const json = JSON.parse(Buffer.from(event.data, 'base64').toString())
  client.topic('cloud-build-result').publishMessage({ json })
}

package.json

{
  "name": "cloud-builds-result-replicator",
  "version": "0.0.1",
  "dependencies": {
    "@google-cloud/pubsub": "^3.4.1"
  }
}

cloudbuild.yaml

steps:
  - id: 'Deploy to Cloud Functions'
    name: gcr.io/cloud-builders/gcloud
    entrypoint: 'bash'
    args:
      - '-c'
      - |
        gcloud functions deploy cloud-builds-result-replicator \
          --entry-point=replicate \
          --runtime=nodejs18 \
          --trigger-topic=cloud-builds \
          --allow-unauthenticated \
          --project=$PROJECT_ID

おわりに

予想外の仕様変更により作業が進まなくなった時はびっくりしましたがサポートの回答などを参考に問題に対する向き合い方を社内で話し合って、素早くワークアラウンドを実装できたので良い機会になったと思っています! 最後になりますが、コミューンの開発に少しでも興味をお持ちいただけた方、今回の記事についてやコミューンにおけるクラウドインフラとの向き合い方などをぜひカジュアルにお話しませんか?下記フォームよりカジュアル面談のお申し込みをお待ちしております!

docs.google.com