CICD Steps
-
- [1. 介绍](#1. 介绍)
- [2. 定义 Steps](#2. 定义 Steps)
-
- [2.1 Inputs](#2.1 Inputs)
- [2.2 Outputs](#2.2 Outputs)
- [3. Using steps](#3. Using steps)
-
- [3.1 Set environment variables](#3.1 Set environment variables)
- [3.2 Running steps locally](#3.2 Running steps locally)
- [4. Scripts](#4. Scripts)
- [5. Actions](#5. Actions)
-
- [5.1 已知的问题](#5.1 已知的问题)
- [6. 表达式](#6. 表达式)
- [7. 实操](#7. 实操)
-
- [7.1 单个step](#7.1 单个step)
- [7.2 多个step](#7.2 多个step)
- [7.3 复用steps](#7.3 复用steps)
- [7.4 添加output到step](#7.4 添加output到step)
- [7.5 使用远程step](#7.5 使用远程step)
1. 介绍
- Steps是作业中可重用且可组合的部分。
- 每个Step都定义可由其他Steps使用的结构化输入和输出。
- Step可以来自本地文件、GitLab.com 存储库或任何其他 Git 源。
Steps 是用于运行作业的 shell 脚本的替代方案。它们提供了更多的结构,可以组合,并且可以测试和重用。 exec:命令是通过使用 Exec 系统调用来运行的,而不是通过运行 shell 来运行。
2. 定义 Steps
Steps在 step.yml 文件中定义。每个文件都有两个文档:规范和定义。
- 规范提供了输入、输出、类型、描述和默认值
- 定义提供了该步骤的实现。步骤定义有两种:
-
exec
类型,执行命令# (spec goes here) --- # Example exec definition exec: command: [ docker, run, -it, ubuntu, uname, -a ]
-
steps
类型,运行一系列其他步骤# (spec goes here) --- # Example steps definition steps: - name: greet_user step: gitlab.com/gitlab-org/ci-cd/runner-tools/echo-step@v1 inputs: echo: hello ${{ inputs.name }} - name: print_system_information step: ./my-local-steps/uname
-
2.1 Inputs
Inputs可以是以下类型:
string
number
boolean
array
struct
默认输入类型是string。,如果输入没有定义默认值,那么它是必需的。
默认值不能使用仅在步骤定义中允许的表达式 (${{ }})。
2.2 Outputs
Outputs可以是以下类型:
string
number
boolean
array
struct
raw_string
step_result
outputs会写入 ${{ output_file }},格式为 key=value,其中 key 是输出的名称。除非类型为 raw_string,否则值应以 JSON 格式写入。
Steps写入的值类型必须与声明的类型匹配,默认的输出类型为 raw_string。
特殊的输出类型 step_result 用于将步骤的执行委托给其他步骤。例如,script 和 action-runner 步骤。
Steps类型定义中的输出使用表达式来从子步骤的输出进行聚合。由于规范中不允许使用表达式,因此 outputs 关键字出现在定义中。为了保持封装性并允许重构,调用者无法直接访问子步骤的输出。
3. Using steps
关键字 step 指向远程或本地steps;
-
远程steps引用由 Git 仓库的 URL、符号 @ 和标签或分支(版本)组成。steps运行器会在仓库根目录下查找名为 step.yml 的文件。
-
本地steps以 . 开头,指向一个目录,步骤运行器会在该目录中查找 step.yml 文件。本地引用始终使用路径分隔符 /,无论操作系统是什么。在加载文件时,会使用适合操作系统的分隔符。
Example job using steps
my-job:
run:
- name: greet_user
step: gitlab.com/gitlab-org/ci-cd/runner-tools/echo-step@v1
inputs:
echo: hello $[[ GITLAB_USER_LOGIN ]]
- name: print_system_information
step: ./my-local-steps/uname
要在作业中使用steps,请在变量中提供steps并调用作业脚本关键字的steps运行程序。史诗 11525 中建议支持使用作业中的步骤作为 GitLab CI 管道配置中的运行关键字。
# Example work-around until run keyword is implemented
my-job:
image: registry.gitlab.com/gitlab-org/step-runner:v0
variables:
STEPS: |
- name: greet_user
step: gitlab.com/gitlab-org/ci-cd/runner-tools/echo-step@v1
inputs:
echo: hello $GITLAB_USER_LOGIN
- name: print_system_information
step: ./my-local-steps/uname
script:
# Run the step-runner's ci command which ready from the STEPS environment variable
- /step-runner ci
3.1 Set environment variables
你不需要为steps声明环境变量。任何以 key=value 形式写入 ${{ export_file }} 的导出都会添加到全局执行环境中。导出的值是纯字符串(无 JSON)。
你可以在steps执行期间使用 env 关键字来临时设置环境变量:
# Example job using env
my-job:
run:
- name: greet_user
step: gitlab.com/gitlab-org/ci-cd/runner-tools/echo-step@v1
env:
USER: $[[ GITLAB_USER_LOGIN ]]
inputs:
echo: hello ${{ env.USER }}
Steps定义还可以临时设置环境变量
# (spec goes here)
---
# Example step definition using env
env:
USER: ${{ inputs.user }}
steps:
- name: greet_user
step: gitlab.com/gitlab-org/ci-cd/runner-tools/echo-step@v1
inputs:
echo: hello ${{ env.USER }}
环境变量的优先顺序是: steps定义 -> steps参考(调用步骤) -> 全局环境
Steps定义中设置的环境变量会覆盖调用步骤时设置的变量,依此类推。
3.2 Running steps locally
要在本地运行steps,请下载 step-runner 并运行 ci 命令。这与用于在生产中运行步骤的二进制文件相同。
STEPS=$(yq '."my-job"'.run .gitlab-ci.yml) step-runner ci
您可以使用 delve 进行调试。在 pkg/runner.go) 中的 Run 处设置断点。
STEPS=$(yq '."my-job"'.run .gitlab-ci.yml) dlv debug . ci
4. Scripts
虽然通常使用steps代替 shell 脚本,但有时仍然需要 shell 脚本。 script 关键字将自动选择正确的 shell 并运行脚本。
# Example job using script
my-job:
run:
- name: greet_user
script: echo hello $[[ GITLAB_USER_LOGIN ]]
仅支持 bash shell
5. Actions
您可以使用 action 关键字运行 GitHub 操作。输入和输出的工作方式与步骤相同。步骤和操作可以互换使用。
# Example job using action
my-job:
run:
- name: greet_user
step: gitlab.com/gitlab-org/ci-cd/runner-tools/echo-step@v1
inputs:
echo: hello $[[ GITLAB_USER_LOGIN ]]
- name: greet_user_again
action: mikefarah/yq@master
inputs:
cmd: echo ["${{ steps.greet_user.outputs.echo }} again!"] | yq .[0]
5.1 已知的问题
GitLab 中运行的操作不支持直接上传artifacts。artifacts必须写入文件系统和缓存,并使用现有的artifacts关键字进行选择。
6. 表达式
表达式是一种用双大括号 (${{ }}) 括起来的mini语言,它们可以引用inputs
、env
(步骤共享的环境)和先前步骤的输出(steps.<step_name>.outputs
)。
表达式还可以引用work_dir,它是构建目录。 step_dir 缓存步骤定义和关联文件。以及output_file 和export_file,这是输出和导出的写入位置。
表达式与模板插值不同,模板插值使用双方括号 ($[[ ]]) 并在作业生成期间进行评估。表达式在作业环境中执行步骤之前进行计算。
7. 实操
cat stap.yml
# 规范有一个名为 who 的输入, who 是可选的,默认值为 world
spec:
inputs:
who:
default: world
# 使用 三重破折号 (---) 将文件分隔为两个 YAML 文档:在 spec 之后添加第二个 YAML 文档,第二个文件是实现,就像函数体一样,使用 exec 键
---
exec:
command: # bash 和 -c 参数启动 Bash shell 并从命令行参数获取脚本输入。除了 shell 脚本之外,您还可以使用命令来执行 docker 或 terraform 等程序。
- bash
- -c
- "echo hello ${{ inputs.who }}" # echo hello ${{ input.name }} 参数包含 ${{ }} 内的表达式。表达式在最后可能的时刻进行计算,并且可以访问当前的执行上下文。此表达式访问输入并读取 who 的值。如果定义了who,则用定义的值替换;如果缺省没有定义who,则使用默认值。
7.1 单个step
cat .gitlab-ci.yml
stages: # List of stages for jobs, and their order of execution
- build
- test
- deploy
hello-world:
variables:
STEPS:
expand: false
value: |
- name: hello_world # 每个调用都会被赋予一个名称,以便您可以在后续步骤中引用输出
step: . # 每次调用都指定要运行的步骤。本地引用 (.) 指向存储库的根目录
image: registry.gitlab.com/gitlab-org/step-runner:v0
script:
- /step-runner ci # 作业脚本调用位于step-runner:v0 映像中的step-runner ci
7.2 多个step
stages: # List of stages for jobs, and their order of execution
- build
- test
- deploy
hello-world:
variables:
STEPS:
expand: false
value: |
- name: hello_world
step: .
- name: hello_steps
step: .
inputs:
who: gitlab steps
image: registry.gitlab.com/gitlab-org/step-runner:v0
script:
- /step-runner ci
7.3 复用steps
7.4 添加output到step
将output添加到你的 hello step中
# 规范有一个名为 who 的输入, who 是可选的,默认值为 world
spec:
inputs:
who:
default: world
outputs: # 在本规范中,定义了一个没有默认值的输出问候语。因为没有默认值,所以需要输出问候语;输出以 key=value 的形式写入文件 ${{ output_file }} (在运行时提供)。
greeting: {}
# 使用 三重破折号 (---) 将文件分隔为两个 YAML 文档:在 spec 之后添加第二个 YAML 文档,第二个文件是实现,就像函数体一样,使用 exec 键
---
exec:
command: # bash 和 -c 参数启动 Bash shell 并从命令行参数获取脚本输入。除了 shell 脚本之外,您还可以使用命令来执行 docker 或 terraform 等程序。
- bash
- -c
- "echo greeting=hello ${{ inputs.who }} | tee ${{ output_file }}" # 此步骤运行 echo greeting=hello ${{inputs.who}} 并将输出发送到日志和输出文件 (tee ${{output_file}})。
spec:
outputs:
all_greetings: {}
---
steps:
- name: hello_world
step: ./hello
- name: hello_steps
step: ./hello
inputs:
who: gitlab steps
outputs:
all_greetings: "${{ steps.hello_world.outputs.greeting }} and ${{ steps.hello_steps.outputs.greeting }}"
7.5 使用远程step
cat .gitlab-ci.yml
hello-world:
variables:
STEPS:
expand: false
value: |
- name: hello_everybody
step: .
- name: all_my_greetings
step: gitlab.com/gitlab-org/ci-cd/runner-tools/echo-step@master
inputs:
echo: "all my greetings say ${{ steps.hello_everybody.outputs.all_greetings }}"
image: registry.gitlab.com/gitlab-org/step-runner:v0
script:
- /step-runner ci