22

基本上,在使用 Google Cloud Build 时,我如何在后续步骤中读取在早期构建步骤中写入的值?

具体来说,我想制作一个基于时间戳和 $SHORT_SHA 组合的自定义图像标签。像下面这样的东西。虽然,它不起作用,因为 docker 抱怨“导出”,而且,即使这有效,它也可能是一个不同的环境:

  # Setting tag in a variable:
  - name: 'ubuntu'
    args: ['export', '_BUILD_TAG=`date', '-u', '+%Y%m%dT%H%M%S_$SHORT_SHA`']

然后,在后面的步骤中:

  # Using tag from the variable:
  - name: gcr.io/cloud-builders/docker
    args: ['build', '-t', 'gcr.io/$PROJECT_ID/$_BUILD_TAG', '.']

那么,如何在另一个步骤中使用一个步骤的输出呢?我可以将内容写入date文件,然后读取它,但我不知道如何从我读取的文件中设置变量(或以其他方式插入其结果以形成 docker build 的参数)。

4

6 回答 6

20

我从来没有找到一种方法来在一个构建步骤中设置一个可以在其他步骤中读取的环境变量,但我最终通过以下方式构建康斯坦丁的答案来实现相同的效果:

在早期步骤中,我生成基于​​日期的标签并将其写入文件。文件系统(/workspace)在步骤之间保留,并用作我的环境变量的存储。然后,在我需要引用该值的每个步骤中,我都会将该文件放在适当的位置。诀窍是使用 sh 或 bash 作为每个容器中的入口点,以便从文件中读取的子 shell 可以执行。

这是一个例子:

## Set build tag and write to file _TAG
- name: 'ubuntu'
  args: ['bash', '-c', 'date -u +%Y%m%dT%H%M_$SHORT_SHA > _TAG']

...

# Using the _TAG during Docker build:
- name: gcr.io/cloud-builders/docker
entrypoint: sh
args: ['-c', 'docker build -t gcr.io/$PROJECT_ID/image_name:$(cat _TAG) .']

需要注意的一点是,如果您在 JSON 对象或需要双引号的东西中以这种方式进行 bash 插值,则在容器中执行时,您需要 subshel​​l 调用永远不会被单引号包围,只有双引号,这可能需要转义内部双引号来构建 JSON 对象。这是一个示例,我使用 _TAG 文件值修补 kubernetes 配置以部署新构建的映像:

- name: gcr.io/cloud-builders/kubectl
entrypoint: bash
args: ['-c', 'gcloud container clusters get-credentials --zone $$CLOUDSDK_COMPUTE_ZONE $$CLOUDSDK_CONTAINER_CLUSTER ; kubectl patch deployment deployment_name -n mynamespace -p "{\"spec\":{\"template\":{\"spec\":{\"containers\":[{\"name\":\"image_name\",\"image\":\"gcr.io/$PROJECT_ID/image_name:$(cat _TAG)\"}]}}}}}"']
env:
- 'CLOUDSDK_COMPUTE_ZONE=us-central1-b'
- 'CLOUDSDK_CONTAINER_CLUSTER=my-google-proj-cluster-name'
于 2018-09-20T01:11:11.613 回答
4
- name: gcr.io/cloud-builders/docker
  entrypoint: sh
  args
    - '-c'
    - 'docker build -t gcr.io/$PROJECT_ID/$(date -u +%Y%m%dT%H%M%S_$SHORT_SHA) .'
于 2018-09-17T12:38:56.867 回答
1

尽管这不能解决您的问题,但我确实想发布此答案,因为您问题的第一句话是“基本上,在使用 Google Cloud Build 时,我如何读取在后续构建步骤中写入的值步骤? ”。这就是你这样做的方式。

官方文档

Volume 是一个 Docker 容器,它安装在构建步骤中以跨构建步骤持久保存文件。当 Cloud Build 运行构建步骤时,它会自动将工作区卷挂载到 /workspace。您可以使用步骤的 volumes 字段指定要安装到构建步骤容器中的其他卷。

这是一个在 github issue 中提出此问题的人实现的示例,但将日期放入卷中以供稍后阅读:

steps:
- name: 'ubuntu'
  volumes:
  - name: 'vol1'
    path: '/persistent_volume'
  entrypoint: 'bash'
  args:
  - '-c'
  - |
        date -u +%Y%m%dT%H%M_$SHORT_SHA > /persistent_volume/file
- name: 'gcr.io/cloud-builders/docker'
  volumes:
  - name: 'vol1'
    path: '/persistent_volume'
  args: ['run', '-v', 'vol1:/data', 'alpine', 'cat', 'data/file']

但是,对于您的特定情况,我将使用子shell命令对其进行标记,就像在此答案中所做的那样:

$(date -u +%Y%m%dT%H%M%S_$SHORT_SHA)
于 2019-01-23T12:59:20.597 回答
1

这是我刚刚自己在另一个中重用 GitVersion 输出的示例。它建立在@chetabahana 发布的答案之上。

steps:
- id: 'Gitversion: Unshallow repo'
  name: gcr.io/cloud-builders/git
  args: [fetch, --unshallow]

- id: 'Gitversion: Parse'
  name: gittools/gitversion:latest-linux
  entrypoint: /bin/bash
  args:
    - -c 
    - |
      dotnet /app/GitVersion.dll > /workspace/gitversion.json

- id: 'Gitversion: Env file'
  name: stedolan/jq
  entrypoint: /bin/bash
  args:
    - -c
    - |
      for s in $(cat /workspace/gitversion.json | jq -r "to_entries|map(\"\(.key)=\(.value|tostring)\")|.[]" ); do
        echo "export $s" >> /workspace/gitversion.env
      done

- id: 'Build and push API image'
  name: gcr.io/cloud-builders/docker
  entrypoint: /bin/bash
  args:
    - -c
    - |
      source /workspace/gitversion.env
      docker build -t gcr.io/xxxx/example:$${SemVer}-$${BuildMetaData} example-app
      docker push gcr.io/xxxx/example:$${SemVer}-$${BuildMetaData}

神奇的成分是$$转义替换变量,这样构建作业就不会尝试替换,而是将其留给bash替换。

于 2019-11-24T19:29:36.797 回答
0

在您的情况下,您不需要导出或安装卷。

steps:
- name: 'ubuntu'
  entrypoint: 'bash'
  args:
  - '-c'
  - |
        printenv

- name: gcr.io/cloud-builders/docker
  entrypoint: 'bash'
  args:
  - '-c'
  - |
        printenv

它会输出

BUILD
Starting Step #0
Step #0: Pulling image: ubuntu
Step #0: Using default tag: latest
Step #0: latest: Pulling from library/ubuntu
Step #0: Digest: sha256:eb70667a801686f914408558660da753cde27192cd036148e58258819b927395
Step #0: Status: Downloaded newer image for ubuntu:latest
Step #0: HOSTNAME=XXXXXXXXXXX
Step #0: BUILDER_OUTPUT=/builder/outputs
Step #0: PWD=/workspace
Step #0: HOME=/builder/home
Step #0: SHLVL=1
Step #0: PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Step #0: _=/usr/bin/printenv
Finished Step #0
Starting Step #1
Step #1: Already have image (with digest): gcr.io/cloud-builders/docker
Step #1: HOSTNAME=XXXXXXXXXXX
Step #1: PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Step #1: PWD=/workspace
Step #1: SHLVL=1
Step #1: HOME=/builder/home
Step #1: DEBIAN_FRONTEND=noninteractive
Step #1: BUILDER_OUTPUT=/builder/outputs
Step #1: _=/usr/bin/printenv
Finished Step #1

所以你可以使用/workspaceor /builder/home,但是因为我们不能使用除了在 yaml 文件上定义的替换之外的变量,所以将它们作为脚本放在 repo 中,如下所示:

steps:
- name: 'ubuntu'
  entrypoint: 'bash'
  args:
  - '-c'
  - |
        bash test.bash

- name: gcr.io/cloud-builders/docker
  entrypoint: 'bash'
  args:
  - '-c'
  - |
        bash result.bash

测试.bash

#!/bin/bash
SHORT_SHA=myvar
date -u +%Y%m%dT%H%M_$SHORT_SHA > /workspace/myfile.txt

结果.bash

#!/bin/bash
_BUILD_TAG=`cat /workspace/myfile.txt`
echo "the transferred value is: $_BUILD_TAG"

输出:

BUILD
Starting Step #0
Step #0: Pulling image: ubuntu
Step #0: Using default tag: latest
Step #0: latest: Pulling from library/ubuntu
Step #0: Digest: sha256:eb70667a801686f914408558660da753cde27192cd036148e58258819b927395
Step #0: Status: Downloaded newer image for ubuntu:latest
Finished Step #0
Starting Step #1
Step #1: Already have image (with digest): gcr.io/cloud-builders/docker
Step #1: the transferred value is: 20190708T1706_myvar
Finished Step #1
PUSH
DONE
于 2019-07-08T16:44:03.720 回答
0

太糟糕了,谷歌(还)不支持。但是,我一直在使用以下简单的方法,并且效果很好。请记住,文件/workspace默认保存到容器之间共享。如果您需要它在不同的目录中,请将其保存或复制到其他地方。

# Save variable to file
- name: 'gcr.io/cloud-builders/gcloud'
  entrypoint: 'bash'
  args:
  - '-c'
  - |
    _id=$(openssl rand -hex 16,,)
    echo "$${_id}" > id.txt

# Set variable from file
- name: 'gcr.io/cloud-builders/gcloud'
  entrypoint: 'bash'
  args:
  - '-c'
  - |
    _id=$(cat id.txt)
    echo "$${_id}"
于 2020-03-25T10:20:06.983 回答