{{< details >}}
- Tier: 基础版,专业版,旗舰版
- Offering: JihuLab.com,私有化部署
{{< /details >}}
测试组件
根据组件的功能,测试组件可能需要在仓库中添加额外的文件。例如,使用特定编程语言进行代码检查、构建和测试的软件组件需要实际的源代码示例。您可以在同一个仓库中放置源代码示例、配置文件及类似内容。
示例:测试 Rust 语言 CI/CD 组件
根据组件的功能,测试组件可能需要在仓库中添加额外的文件。
以下 Rust 编程语言的“Hello World”示例简化地使用了 cargo
工具链:
- 进入 CI/CD 组件根目录。
-
使用
cargo init
命令初始化一个新的 Rust 项目。cargo init
该命令创建了所有必需的项目文件,包括一个
src/main.rs
的“Hello World”示例。此步骤足以在组件任务中使用cargo build
构建 Rust 源代码。tree . ├── Cargo.toml ├── LICENSE.md ├── README.md ├── src │ └── main.rs └── templates └── build.yml
-
确保组件有一个任务来构建 Rust 源代码,例如在
templates/build.yml
中:spec: inputs: stage: default: build description: 'Defines the build stage' rust_version: default: latest description: 'Specify the Rust version, use values from https://hub.docker.com/_/rust/tags Defaults to latest' --- "build-$[[ inputs.rust_version ]]": stage: $[[ inputs.stage ]] image: rust:$[[ inputs.rust_version ]] script: - cargo build --verbose
在这个示例中:
-
stage
和rust_version
输入可以从其默认值进行修改。CI/CD 任务以build-
前缀开始,并根据rust_version
输入动态创建名称。命令cargo build --verbose
编译 Rust 源代码。
-
-
在项目的
.gitlab-ci.yml
配置文件中测试组件的build
模板:include: # include the component located in the current project from the current SHA - component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/build@$CI_COMMIT_SHA inputs: stage: build stages: [build, test, release]
-
为运行测试及更多内容,添加额外的函数和测试到 Rust 代码中,并在
templates/test.yml
中添加一个组件模板和任务运行cargo test
。spec: inputs: stage: default: test description: 'Defines the test stage' rust_version: default: latest description: 'Specify the Rust version, use values from https://hub.docker.com/_/rust/tags Defaults to latest' --- "test-$[[ inputs.rust_version ]]": stage: $[[ inputs.stage ]] image: rust:$[[ inputs.rust_version ]] script: - cargo test --verbose
-
通过包含
test
组件模板在流水线中测试额外的任务:include: # include the component located in the current project from the current SHA - component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/build@$CI_COMMIT_SHA inputs: stage: build - component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/test@$CI_COMMIT_SHA inputs: stage: test stages: [build, test, release]
CI/CD 组件模式
本节提供实现常见模式的 CI/CD 组件的实用示例。
使用布尔输入有条件地配置任务
您可以通过结合 boolean
类型输入和 extends
功能来构建具有两个条件的任务。
例如,使用 boolean
输入配置复杂缓存行为:
spec:
inputs:
enable_special_caching:
description: 'If set to `true` configures a complex caching behavior'
type: boolean
---
.my-component:enable_special_caching:false:
extends: null
.my-component:enable_special_caching:true:
cache:
policy: pull-push
key: $CI_COMMIT_SHA
paths: [...]
my-job:
extends: '.my-component:enable_special_caching:$[[ inputs.enable_special_caching ]]'
script: ... # run some fancy tooling
此模式通过将 enable_special_caching
输入传递到任务的 extends
关键字来工作。根据 enable_special_caching
是 true
还是 false
,从预定义的隐藏任务中选择适当的配置(.my-component:enable_special_caching:true
或 .my-component:enable_special_caching:false
)。
使用 options
有条件地配置任务
您可以使用多个选项组合任务,其行为类似于 if
和 elseif
条件。使用 extends
和 string
类型的多个 options
来进行任意数量的条件。
例如,使用 3 种不同的选项配置复杂的缓存行为:
spec:
inputs:
cache_mode:
description: Defines the caching mode to use for this component
type: string
options:
- default
- aggressive
- relaxed
---
.my-component:cache_mode:default:
extends: null
.my-component:cache_mode:aggressive:
cache:
policy: push
key: $CI_COMMIT_SHA
paths: ['*/**']
.my-component:cache_mode:relaxed:
cache:
policy: pull-push
key: $CI_COMMIT_BRANCH
paths: ['bin/*']
my-job:
extends: '.my-component:cache_mode:$[[ inputs.cache_mode ]]'
script: ... # run some fancy tooling
在此示例中,cache_mode
输入提供了 default
、aggressive
和 relaxed
选项,每个选项对应于一个不同的隐藏任务。通过使用 extends: '.my-component:cache_mode:$[[ inputs.cache_mode ]]'
扩展组件任务,任务根据所选选项动态继承正确的缓存配置。
CI/CD 组件迁移示例
本节展示了将 CI/CD 模板和流水线配置迁移到可重用 CI/CD 组件的实用示例。
CI/CD 组件迁移示例:Go
完整的软件开发生命周期流水线可以由多个任务和阶段组成。编程语言的 CI/CD 模板可能在单个模板文件中提供多个任务。作为实践,以下 Go CI/CD 模板应该被迁移。
default:
image: golang:latest
stages:
- test
- build
- deploy
format:
stage: test
script:
- go fmt $(go list ./... | grep -v /vendor/)
- go vet $(go list ./... | grep -v /vendor/)
- go test -race $(go list ./... | grep -v /vendor/)
compile:
stage: build
script:
- mkdir -p mybinaries
- go build -o mybinaries ./...
artifacts:
paths:
- mybinaries
{{< alert type=”note” >}}
您也可以开始迁移一个任务,而不是所有任务。按照下面的说明,在第一次迭代中仅迁移 build
CI/CD 任务。
{{< /alert >}}
CI/CD 模板迁移涉及以下步骤:
- 分析 CI/CD 任务和依赖关系,并定义迁移操作:
-
image
配置是全局的,需要移到任务定义中。 -
format
任务在一个任务中运行多个go
命令。为了提高流水线效率,go test
命令应该移到一个单独的任务中。 -
compile
任务运行go build
,应该重命名为build
。
-
- 定义优化策略以提高流水线效率。
-
stage
任务属性应该是可配置的,以允许不同的 CI/CD 流水线消费者。 -
image
键使用了硬编码的镜像标签latest
。添加golang_version
作为输入,默认值为latest
,以便更灵活和可重用的流水线。输入必须匹配 Docker Hub 镜像标签值。 -
compile
任务将二进制文件构建到一个硬编码的目标目录mybinaries
,这可以通过动态输入和默认值mybinaries
来增强。
-
-
为新组件创建模板目录结构,每个任务一个模板。
- 模板的名称应该遵循
go
命令,例如format.yml
、build.yml
和test.yml
。 - 创建一个新项目,初始化一个 Git 仓库,添加/提交所有更改,设置远程 origin 并推送。修改您的 CI/CD 组件项目路径的 URL。
- 创建其他文件,如编写组件指导中所述:
README.md
、LICENSE.md
、.gitlab-ci.yml
、.gitignore
。以下 shell 命令初始化 Go 组件结构:
git init mkdir templates touch templates/{format,build,test}.yml touch README.md LICENSE.md .gitlab-ci.yml .gitignore git add -A git commit -avm "Initial component structure" git remote add origin https://gitlab.example.com/components/golang.git git push
- 模板的名称应该遵循
- 将 CI/CD 任务创建为模板。从
build
任务开始。- 在
spec
部分定义以下输入:stage
、golang_version
和binary_directory
。 - 添加动态任务名称定义,访问
inputs.golang_version
。 - 使用类似的模式进行动态 Go 镜像版本,访问
inputs.golang_version
。 - 将阶段分配给
inputs.stage
值。 - 从
inputs.binary_directory
创建二进制目录并将其作为参数添加到go build
。 -
定义产物路径为
inputs.binary_directory
。spec: inputs: stage: default: 'build' description: 'Defines the build stage' golang_version: default: 'latest' description: 'Go image version tag' binary_directory: default: 'mybinaries' description: 'Output directory for created binary artifacts' --- "build-$[[ inputs.golang_version ]]": image: golang:$[[ inputs.golang_version ]] stage: $[[ inputs.stage ]] script: - mkdir -p $[[ inputs.binary_directory ]] - go build -o $[[ inputs.binary_directory ]] ./... artifacts: paths: - $[[ inputs.binary_directory ]]
-
format
任务模板遵循相同的模式,但只需要stage
和golang_version
输入。spec: inputs: stage: default: 'format' description: 'Defines the format stage' golang_version: default: 'latest' description: 'Golang image version tag' --- "format-$[[ inputs.golang_version ]]": image: golang:$[[ inputs.golang_version ]] stage: $[[ inputs.stage ]] script: - go fmt $(go list ./... | grep -v /vendor/) - go vet $(go list ./... | grep -v /vendor/)
-
test
任务模板遵循相同的模式,但只需要stage
和golang_version
输入。spec: inputs: stage: default: 'test' description: 'Defines the format stage' golang_version: default: 'latest' description: 'Golang image version tag' --- "test-$[[ inputs.golang_version ]]": image: golang:$[[ inputs.golang_version ]] stage: $[[ inputs.stage ]] script: - go test -race $(go list ./... | grep -v /vendor/)
- 在
-
为了测试组件,修改
.gitlab-ci.yml
配置文件,并添加测试。- 为
build
任务的输入指定一个不同的golang_version
值。 -
修改您的 CI/CD 组件路径的 URL。
stages: [format, build, test] include: - component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/format@$CI_COMMIT_SHA - component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/build@$CI_COMMIT_SHA - component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/build@$CI_COMMIT_SHA inputs: golang_version: "1.21" - component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/test@$CI_COMMIT_SHA inputs: golang_version: latest
- 为
-
添加 Go 源代码以测试 CI/CD 组件。
go
命令期望在根目录中有一个go.mod
和main.go
的 Go 项目。-
初始化 Go 模块。修改您的 CI/CD 组件路径的 URL。
go mod init example.jihulab.com/components/golang
-
创建一个
main.go
文件,包含一个主函数,打印Hello, CI/CD component
作为示例。您可以使用代码注释生成 Go 代码,使用极狐GitLab Duo 代码建议。// Specify the package, import required packages // Create a main function // Inside the main function, print "Hello, CI/CD Component" package main import "fmt" func main() { fmt.Println("Hello, CI/CD Component") }
-
目录结构应如下所示:
tree . ├── LICENSE.md ├── README.md ├── go.mod ├── main.go └── templates ├── build.yml ├── format.yml └── test.yml
-
按照将 CI/CD 模板转换为组件部分中的剩余步骤完成迁移: