You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在GitHub使用Rebase and Merge时,如何实现基于GCR/Cloud Run的不可变构建?

解决Rebase and Merge下复用PR阶段构建镜像的问题

核心问题是Rebase and Merge会生成新的提交SHA,导致main分支push工作流无法找到PR阶段用原SHA构建的镜像。以下是两种可行的解决方案:

方法一:为PR镜像添加PR编号标签

在PR工作流中给镜像额外打上PR编号的标签,合并到main后通过PR编号找到对应的镜像。

1. 修改PR工作流,添加PR编号标签

在构建推送镜像的步骤中,增加PR编号标签的推送:

on:
  pull_request:
    types: [opened, synchronize, reopened, edited]
    branches: [main]

jobs:
  build-dev:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        app: [your-app-name]
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      # 省略身份验证、环境变量设置等步骤
      
      - name: Build and push Docker image to GCR
        run: |
          # 构建并推送原SHA标签的镜像
          docker build -t gcr.io/${{ env.PROJECT_ID }}/dev-${{ matrix.app }}:${{ github.sha }} .
          docker push gcr.io/${{ env.PROJECT_ID }}/dev-${{ matrix.app }}:${{ github.sha }}
          
          # 添加PR编号标签并推送
          docker tag gcr.io/${{ env.PROJECT_ID }}/dev-${{ matrix.app }}:${{ github.sha }} gcr.io/${{ env.PROJECT_ID }}/dev-${{ matrix.app }}:pr-${{ github.event.number }}
          docker push gcr.io/${{ env.PROJECT_ID }}/dev-${{ matrix.app }}:pr-${{ github.event.number }}
      
      # 省略Cloud Run dev环境部署步骤

2. 修改main分支push工作流,通过PR编号获取镜像

在main分支的push工作流中,用GitHub CLI找到当前提交对应的PR编号,再用该标签拉取镜像并重打test环境标签:

on:
  push:
    branches: [main]

jobs:
  deploy-test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        app: [your-app-name]
    steps:
      - name: Install GitHub CLI
        run: |
          type -p curl >/dev/null || (sudo apt update && sudo apt install curl -y)
          curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \
          && sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \
          && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
          && sudo apt update && sudo apt install gh -y

      - name: Authenticate GitHub CLI
        run: echo "${{ secrets.GITHUB_TOKEN }}" | gh auth login --with-token

      - name: Get merged PR number
        id: get-pr-number
        run: |
          PR_NUMBER=$(gh pr view --commit ${{ github.sha }} --json number --jq '.number')
          echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT

      - name: Tag Docker image for test
        run: |
          gcloud container images add-tag \
            gcr.io/${{ env.PROJECT_ID }}/dev-${{ matrix.app }}:pr-${{ steps.get-pr-number.outputs.pr_number }} \
            gcr.io/${{ env.PROJECT_ID }}/test-${{ matrix.app }}:${{ github.sha }}
      
      # 省略Cloud Run test环境部署步骤

方法二:使用镜像Digest(更可靠)

镜像的Digest是唯一且不可变的标识,不会随标签或Rebase操作变化。在PR工作流中记录Digest,main工作流直接用Digest引用镜像。

1. PR工作流中记录镜像Digest

构建镜像后获取Digest,并存入GitHub提交状态:

# PR工作流中的构建步骤
- name: Build and push Docker image to GCR
  id: build-image
  run: |
    docker build -t gcr.io/${{ env.PROJECT_ID }}/dev-${{ matrix.app }}:${{ github.sha }} .
    docker push gcr.io/${{ env.PROJECT_ID }}/dev-${{ matrix.app }}:${{ github.sha }}
    
    # 获取镜像Digest
    IMAGE_DIGEST=$(gcloud container images describe gcr.io/${{ env.PROJECT_ID }}/dev-${{ matrix.app }}:${{ github.sha }} --format='value(image_summary.digest)')
    echo "image_digest=gcr.io/${{ env.PROJECT_ID }}/dev-${{ matrix.app }}@${IMAGE_DIGEST}" >> $GITHUB_OUTPUT

- name: Save Digest to commit status
  run: |
    gh api repos/${{ github.repository }}/statuses/${{ github.sha }} \
      -X POST \
      -f state="success" \
      -f context="built-image-digest" \
      -f description="Dev environment image digest" \
      -f output="{\"digest\": \"${{ steps.build-image.outputs.image_digest }}\"}"
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

2. main工作流中获取Digest并部署

找到合并PR对应的原提交,取出Digest直接用于部署:

# main分支push工作流的部署步骤
- name: Install GitHub CLI
  run: |
    type -p curl >/dev/null || (sudo apt update && sudo apt install curl -y)
    curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \
    && sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \
    && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
    && sudo apt update && sudo apt install gh -y

- name: Authenticate GitHub CLI
  run: echo "${{ secrets.GITHUB_TOKEN }}" | gh auth login --with-token

- name: Get image Digest from PR commit
  id: get-digest
  run: |
    # 获取合并PR的原提交SHA
    PR_HEAD_SHA=$(gh pr view --commit ${{ github.sha }} --json headSha --jq '.headSha')
    # 从提交状态中取出Digest
    IMAGE_DIGEST=$(gh api repos/${{ github.repository }}/statuses/${PR_HEAD_SHA} --jq '.[] | select(.context == "built-image-digest") | .output.digest')
    echo "image_digest=${IMAGE_DIGEST}" >> $GITHUB_OUTPUT

- name: Deploy to test environment
  run: |
    gcloud run deploy test-${{ matrix.app }} \
      --image ${{ steps.get-digest.outputs.image_digest }} \
      --platform managed \
      --region your-gcp-region \
      --env ENV=test

内容的提问来源于stack exchange,提问作者Safwan Parkar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 17:34:55