wheatandcatの開発ブログ

React Nativeで開発しているペペロミア & memoirの技術系記事を投稿してます

PR毎にCloud Runをデプロイできるようにする

GCP固有の処理などローカル環境では検証できない機能が増えてきたので、PR毎にCloud Runをデプロイできるように修正した。

PR

github.com

参考記事

zenn.dev

cloud.google.com

実装

Cloud Runはtagを設定することで、リビジョンのURLが設定され個別にアクセスが可能になる(詳しくは以下を参照)

cloud.google.com

なので、仕組み的には、PRがオープン時にブランチの環境でCloud Runにtagを設定してデプロイ、PRがクローズ時にtagを削除すればOK

上記の仕組みをGitHub Actionsに組み込むと以下の通りになった。

まずは、PRがオープンした際のコード

github/workflows/deploy_review_branch.yml

name: Deploy Review Branch

on: pull_request

env:
  SERVICE_ACCOUNT_JSON: ${{ secrets.REVIEW_SERVICE_ACCOUNT_JSON }}
  GCP_SERVICE_ACCOUNT_JSON: ${{ secrets.REVIEW_GCP_SERVICE_ACCOUNT_JSON }}
  PROJECT_ID: ${{ secrets.REVIEW_GCP_PROJECT_ID }}
  SERVICE_NAME: ${{ secrets.REVIEW_SERVICE_NAME }}
  REGION: ${{ secrets.REGION }}
jobs:
  deploy-branch:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
      pull-requests: write
    steps:
      - uses: "actions/checkout@v3"

      - name: Create serviceAccount.json file
        run: echo $SERVICE_ACCOUNT_JSON | base64 --decode -i > ./serviceAccount.json
      - name: Create gcpServiceAccount.json file
        run: echo $GCP_SERVICE_ACCOUNT_JSON | base64 --decode -i > ./gcpServiceAccount.json

      - id: "auth"
        name: "Authenticate to Google Cloud"
        uses: "google-github-actions/auth@v0.4.0"
        with:
          workload_identity_provider: ${{ secrets.REVIEW_WORKLOAD_IDENTITY_PROVIDER }}
          service_account: github-actions@${{ secrets.REVIEW_GCP_PROJECT_ID }}.iam.gserviceaccount.com

      - name: Set up Cloud SDK
        uses: google-github-actions/setup-gcloud@v0

      - name: Authorize Docker push
        run: gcloud auth configure-docker

      - name: Build Submit
        run: |-
          gcloud builds submit --pack image=asia.gcr.io/$PROJECT_ID/$SERVICE_NAME:latest

      - name: Deploy to Cloud Run
        run: |-
          gcloud run deploy $SERVICE_NAME \
            --project=$PROJECT_ID \
            --image=asia.gcr.io/$PROJECT_ID/$SERVICE_NAME:latest \
            --region=$REGION \
            --service-account=github-actions@$PROJECT_ID.iam.gserviceaccount.com \
            --allow-unauthenticated \
            --tag=pr-${{ github.event.pull_request.number }} \
            --no-traffic

      - name: Find Comment
        uses: peter-evans/find-comment@v2
        id: fc
        with:
          issue-number: ${{ github.event.pull_request.number }}
          comment-author: github-actions[bot]
          body-includes: "Preview"

      - name: Create Preview URL
        id: preview-url
        run: echo "::set-output name=value::https://pr-${{ github.event.pull_request.number }}---memoir-backend-pmrozdfyha-an.a.run.app"

      - name: Get datetime for now
        id: datetime
        run: echo "::set-output name=value::$(date)"
        env:
          TZ: Asia/Tokyo

      - name: Create or update comment
        uses: peter-evans/create-or-update-comment@v2
        with:
          comment-id: ${{ steps.fc.outputs.comment-id }}
          issue-number: ${{ github.event.pull_request.number }}
          body: |
            Visit the :eyes: **Preview** :eyes: for this PR (updated for commit ${{ github.event.pull_request.head.sha }}):
            <${{ steps.preview-url.outputs.value }}>
            <sub>(:fire: updated at ${{ steps.datetime.outputs.value }})</sub>
          edit-mode: replace

今回は参考記事に合わせてcreate-or-update-commentを使用してPRにデプロイしたCloud RunのURLをコメントするように追加。以下のように表示される。

次にPRがクローズした際のコード

.github/workflows/cloud-run.delete-preview.yml

name: Cloud Run (Delete Preview)2

on:
  pull_request:
    types: [closed]

env:
  PROJECT_ID: ${{ secrets.REVIEW_GCP_PROJECT_ID }}
  SERVICE_NAME: ${{ secrets.REVIEW_SERVICE_NAME }}
  REGION: ${{ secrets.REGION }}
jobs:
  delete-preview:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
      pull-requests: write
    steps:
      - uses: "actions/checkout@v3"

      - id: "auth"
        name: "Authenticate to Google Cloud"
        uses: "google-github-actions/auth@v0.4.0"
        with:
          workload_identity_provider: ${{ secrets.REVIEW_WORKLOAD_IDENTITY_PROVIDER }}
          service_account: github-actions@${{ secrets.REVIEW_GCP_PROJECT_ID }}.iam.gserviceaccount.com

      - name: Set up Cloud SDK
        uses: google-github-actions/setup-gcloud@v0

      - name: Deploy revision with tag
        run: |-
          gcloud run services update-traffic $SERVICE_NAME \
          --region=$REGION \
          --remove-tags=pr-${{ github.event.pull_request.number }}

      - name: Find Comment
        uses: peter-evans/find-comment@v2
        id: fc
        with:
          issue-number: ${{ github.event.pull_request.number }}
          comment-author: github-actions[bot]
          body-includes: "Preview"

      - name: Create Preview URL
        id: preview-url
        run: echo "::set-output name=value::https://pr-${{ github.event.pull_request.number }}---product-x-drwvbiotlz-an.a.run.app"

      - name: Get datetime for now
        id: datetime
        run: echo "::set-output name=value::$(date)"
        env:
          TZ: Asia/Tokyo

      - name: Create or update comment
        uses: peter-evans/create-or-update-comment@v2
        with:
          comment-id: ${{ steps.fc.outputs.comment-id }}
          issue-number: ${{ github.event.pull_request.number }}
          body: |
            Visit the :eyes: **Preview** :eyes: for this PR (updated for commit ${{ github.event.pull_request.head.sha }}):
            ~<${{ steps.preview-url.outputs.value }}>~
            <sub>(:warning: deleted at ${{ steps.datetime.outputs.value }})</sub>
          edit-mode: replace

上記でPRがクローズした際に、対象のCloud Runにtagを削除して、コメントしているURLにはアクセスできなくなるので、以下の通りにコメントを更新している。

これでPR毎にCloud Runをデプロイできるようになり、よりデバッグがやりやすくなった。