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

如何在cloudbuild.yaml中实现动态版本控制并解决替换报错?

从package.json自动获取版本号并用于Cloud Build构建

问题场景

当前Cloud Build配置(cloudbuild.yaml)需要手动填写${_VERSION}作为应用版本号,尝试从package.json读取版本号自动赋值时,触发错误:

Your build failed to run: generic::invalid_argument: invalid value for 'build.substitutions': key in the template "VERSION" is not a valid built-in substitution.

原手动配置内容:

steps:
# Step 1: Build the Docker image
- name: 'gcr.io/cloud-builders/docker'
  args: ['build', '-t', 'demo-backend', '-f', 'backend/Dockerfile', 'backend']
# Step 2: Tag the Docker image
- name: 'gcr.io/cloud-builders/docker'
  args: ['tag', 'demo-backend', 'location-docker.pkg.dev/demo/demo-backend-repository/demo-backend:${_VERSION}']
# Step 3: Push the Docker image to Google Container Registry (GCR)
- name: 'gcr.io/cloud-builders/docker'
  args: ['push', 'location-docker.pkg.dev/demo/demo-backend-repository/demo-backend:${_VERSION}']
# Step 4: Deploy the container image to Cloud Run
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
  entrypoint: gcloud
  args:
  - 'run'
  - 'deploy'
  - 'demo-backend'
  - '--image=location-docker.pkg.dev/demo/demo-backend-repository/demo-backend:${_VERSION}'
  - '--platform=managed'
  - '--region=location'
  - '--allow-unauthenticated'

substitutions:
_VERSION: '1.0.0'

options:
defaultLogsBucketBehavior: 'REGIONAL_USER_OWNED_BUCKET'

原尝试的自动版本方案(报错):

steps:
# Step 1: Fetch version from package.json and store it in an environment variable
- name: 'ubuntu'
  entrypoint: 'bash'
  args:
  - '-c'
  - |
    VERSION=$(jq -r .version package.json)
    echo "VERSION=${VERSION}" > /workspace/version.env
# Step 2: Load the version from the environment file and export it as a substitution
- name: 'ubuntu'
  entrypoint: 'bash'
  args:
  - '-c'
  - |
    source /workspace/version.env
    gcloud builds submit --substitutions=_VERSION=${VERSION} .
# Step 3: Build the Docker image
- name: 'gcr.io/cloud-builders/docker'
  args: ['build', '-t', 'demo-backend', '-f', 'backend/Dockerfile', 'backend']
# Step 4: Tag the Docker image
- name: 'gcr.io/cloud-builders/docker'
  args: ['tag', 'demo-backend', 'location-docker.pkg.dev/demo/demo-backend-repository/demo-backend:${_VERSION}']
# Step 5: Push the Docker image to Google Container Registry (GCR)
- name: 'gcr.io/cloud-builders/docker'
  args: ['push', 'location-docker.pkg.dev/demo/demo-backend-repository/demo-backend:${_VERSION}']
# Step 6: Deploy the container image to Cloud Run
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
  entrypoint: gcloud
  args:
  - 'run'
  - 'deploy'
  - 'demo-backend'
  - '--image=location-docker.pkg.dev/demo/demo-backend-repository/demo-backend:${_VERSION}'
  - '--platform=managed'
  - '--region=location'
  - '--allow-unauthenticated'

substitutions:
_VERSION: '1.0.0' # Default value, will be overridden by the fetched version

options:
defaultLogsBucketBehavior: 'REGIONAL_USER_OWNED_BUCKET'

错误原因

  1. Cloud Build的替换变量(如${_VERSION})在构建启动前就已完成解析,构建步骤内无法动态修改或覆盖替换变量的值。
  2. 原方案中步骤2调用gcloud builds submit递归触发新构建,不仅会重复执行流程,还因替换变量传递方式错误导致报错。

正确解决方案

不需要递归提交构建,直接在需要版本号的步骤中读取package.json的版本,或者将版本号写入文件后在后续步骤中引用。以下是两种可行方案:

方案1:直接在步骤中读取版本号

使用bash脚本直接读取package.json的版本,并在docker命令和gcloud命令中使用:

steps:
# Step 1: Build Docker image(无需版本号)
- name: 'gcr.io/cloud-builders/docker'
  args: ['build', '-t', 'demo-backend', '-f', 'backend/Dockerfile', 'backend']

# Step 2: Tag & Push Docker image,同时读取版本号
- name: 'ubuntu'
  entrypoint: 'bash'
  args:
  - '-c'
  - |
    VERSION=$(jq -r .version package.json)
    docker tag demo-backend location-docker.pkg.dev/demo/demo-backend-repository/demo-backend:$VERSION
    docker push location-docker.pkg.dev/demo/demo-backend-repository/demo-backend:$VERSION

# Step 3: Deploy to Cloud Run,使用读取到的版本号
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
  entrypoint: 'bash'
  args:
  - '-c'
  - |
    VERSION=$(jq -r .version package.json)
    gcloud run deploy demo-backend \
      --image=location-docker.pkg.dev/demo/demo-backend-repository/demo-backend:$VERSION \
      --platform=managed \
      --region=location \
      --allow-unauthenticated

options:
defaultLogsBucketBehavior: 'REGIONAL_USER_OWNED_BUCKET'

方案2:将版本号写入文件,后续步骤引用

先将版本号写入文件,后续步骤通过读取文件获取版本,避免重复解析package.json:

steps:
# Step 1: 读取版本号并写入文件
- name: 'ubuntu'
  entrypoint: 'bash'
  args:
  - '-c'
  - |
    jq -r .version package.json > /workspace/VERSION

# Step 2: Build Docker image
- name: 'gcr.io/cloud-builders/docker'
  args: ['build', '-t', 'demo-backend', '-f', 'backend/Dockerfile', 'backend']

# Step 3: Tag Docker image
- name: 'ubuntu'
  entrypoint: 'bash'
  args:
  - '-c'
  - |
    VERSION=$(cat /workspace/VERSION)
    docker tag demo-backend location-docker.pkg.dev/demo/demo-backend-repository/demo-backend:$VERSION

# Step 4: Push Docker image
- name: 'ubuntu'
  entrypoint: 'bash'
  args:
  - '-c'
  - |
    VERSION=$(cat /workspace/VERSION)
    docker push location-docker.pkg.dev/demo/demo-backend-repository/demo-backend:$VERSION

# Step 5: Deploy to Cloud Run
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
  entrypoint: 'bash'
  args:
  - '-c'
  - |
    VERSION=$(cat /workspace/VERSION)
    gcloud run deploy demo-backend \
      --image=location-docker.pkg.dev/demo/demo-backend-repository/demo-backend:$VERSION \
      --platform=managed \
      --region=location \
      --allow-unauthenticated

options:
defaultLogsBucketBehavior: 'REGIONAL_USER_OWNED_BUCKET'

注意事项

  • 确保构建环境中已安装jq工具(ubuntu镜像默认包含,若使用其他镜像需自行安装)。
  • 如果package.json不在代码根目录,需调整jq命令的路径(如backend/package.json)。

内容的提问来源于stack exchange,提问作者Rishav Kumar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 08:12:33