持续集成的构建环境
功能介绍
构建环境是指用来运行构建任务的环境,它通常是一个预装了开发语言 SDK、命令行工具的操作系统环境或者 Docker 环境。
CODING 持续集成会为每个构建任务分配一台 CVM 作为构建资源,您可以通过内置的 agent label 来使用不同的环境进行构建。目前支持的构建环境有三种:
- 默认环境:在 CODING 提供的云主机上执行 Pipeline 或 stage
- 使用 Docker 自定义构建环境:在指定已构建好的 Docker 镜像环境中,或使用代码仓库中指定的 Dockerfile 脚本构建环境,执行 Pipeline 或 stage
默认环境
在【持续集成计划设置】->【流程配置】->【基础配置】->【图形化编辑器】中,默认选中 “使用默认构建环境”,您的持续集成任务将会在云主机 / 自定义节点的操作系统下进行构建。
如果您使用 Jenkinsfile 进行流程配置,设置 agent 为 agent any,持续集成将在默认环境运行构建程序。
pipeline {
agent any
stages {
stage("检出") {
steps {
checkout([
$class: 'GitSCM',
branches: [[name: env.GIT_BUILD_REF]],
userRemoteConfigs: [[url: env.GIT_REPO_URL, credentialsId: env.CREDENTIALS_ID]]
])
}
}
...
}
}
如果您选择 CODING 提供的云主机作为构建节点,并选择默认环境进行构建,我们已经为您安装了以下软件 SDK 和命令行工具:
预装的软件 SDK
默认环境中提供的 SDK 以及对应的版本如下(更新日期:2019 年 11 月 30 日):
- android-sdk: 26.1.1
- build-essential
- java: 1.8.0_191
- python: 2.7.12
- python3: 3.5.2
- python3.7: 3.7.3
- nodejs: 10.15.3
- php: 7.3.5
- ruby: 2.6.0
- go: 1.12.4
- dotnet-core: 2.2
- erlang: Erlang/OTP 21
- elixir: 1.8.1
预装的命令行工具
默认环境中提供的命令行工具以及对应的版本如下(更新日期:2020 年 5 月 7 日):
- bundler: 1.17.2
- cmake: 3.5.1
- composer: 1.8.5
- coscmd: 1.8.5.36
- docker-compose: 1.23.1
- docker: 18.09.1
- git-lfs: 2.7.2
- git: 2.7.4
- gradle: 4.10.3
- helm: 2.13.1
- jq: 1.5-1-a5b5cbe
- kubectl: 1.14
- maven: 3.6.1
- mercurial: 3.7.3
- nvm: 0.34.0
- pigz: 2.3.1
- pip3: 19.0.3
- rancher: 2.2.0
- rvm: 1.29.7
- sshpass: 1.05
- svn: 1.9.3
- tccli: 3.0.67.1
- vsftpd: 3.0.3
- yarn: 1.15.2
选择不同版本的预装 SDK
若默认环境中预装的 SDK 版本不满足您的要求,您可以使用 CODING 官方提供的其他版本镜像作为构建环境。
在【持续集成计划设置】->【流程配置】->【基础配置】->【图形化编辑器】中,选择 “使用 CODING 官方提供的 Docker 镜像”,然后从列表中选择符合您构建需求的 SDK 和版本,作为 pipeline / stage 的 agent。
例如,默认预装的 node.js 版本为 10.15.3,而当前构建需要 node.js 12 以上的版本,可以在下面列表中进行选择:
对应的 Jenkinsfile 为:
pipeline {
agent {
docker {
registryUrl 'https://coding-public-docker.pkg.coding.net'
image 'public/docker/nodejs:12'
}
}
stages {
stage('Test') {
steps {
sh 'node --version'
}
}
}
}
使用 Docker 自定义构建环境
CODING 持续集成为您提供三种方式自定义 Docker 构建环境,可以满足您不同的构建需求:
- 使用存放在项目内制品库的 Docker 镜像:适用于项目层级的标准构建环境,保障项目内镜像安全,方便管理,通过项目令牌您也可以拉取其他项目的镜像;
- 使用指定 Registry 地址(默认为 Docker Hub)的 Docker 镜像:适用于拉取储存在其他平台的镜像;
- 使用 Dockerfile 脚本构建环境:适用于灵活搭建构建环境的需求;
使用存放在项目内制品库的 Docker 镜像
在【持续集成计划设置】->【流程配置】->【基础配置】->【图形化编辑器】中,选择 “使用项目内的 Docker 镜像”,即可将制品库中的镜像作为 pipeline / stage 的 agent。
对应的 Jenkinsfile 为:
pipeline {
agent {
docker {
image 'laravel-demo/laravel-docker/laravel-demo:1.0.0'
registryUrl 'https://codes-farm-docker.pkg.coding.net/'
registryCredentialsId env.CODING_ARTIFACTS_CREDENTIALS_ID
}
}
stages {
stage('Test') {
steps {
sh 'php -v'
}
}
}
}
如何推送自定义构建环境镜像到制品库并作持续集成构建环境,请参见在持续集成中使用自定义 Docker 构建环境。
注意:env.CODING_ARTIFACTS_CREDENTIALS_ID
只可用于本项目的制品库,而跨项目使用制品库需按照下列步骤进行操作:
- 在制品库所在的项目中创建「项目令牌」,获得用户名和密码;
- 在持续集成所在的项目中录入「项目凭据」,选择「用户名+密码」类型,并授权给持续集成;
- 在持续集成中添加环境变量
DOCKER_CREDENTIALS_ID
,取值选用「项目凭据」,上方的代码也对应改成registryCredentialsId env.DOCKER_CREDENTIALS_ID
如何将「项目令牌」录入凭据请参见在持续集成中使用凭据。
使用指定 Registry 地址的 Docker 镜像
在【持续集成计划设置】->【流程配置】->【基础配置】->【图形化编辑器】中,选择 “使用指定的 Docker 镜像”,即可将指定地址的镜像作为 pipeline / stage 的 agent。
其中,“Docker 镜像” 为必填项,需要填入您的镜像名称;“Registry 地址” 默认为 Docker Hub (hub.docker.com);如果需要拉取私有镜像,需要填写 “Registry 认证凭据 ID”,如何录入凭据请参见在持续集成中使用凭据。
下面是在公有镜像仓库中拉取指定版本 SDK 的镜像,作为持续集成的构建环境的对应 Jenkinsfile:
pipeline {
agent {
docker {
image 'node:7-alpine'
args '-v /etc/hosts:/etc/hosts' // args 为非必填参数,可以为 docker 执行运行时的参数
}
}
stages {
stage('Test') {
steps {
sh 'node --version'
}
}
}
}
下面是在私有镜像仓库中拉取指定版本 SDK 的镜像,作为持续集成的构建环境的对应 Jenkinsfile:
pipeline {
agent {
docker {
image 'laravel-demo/laravel-docker/laravel-demo:1.0.0' // 修改为你的镜像名称
registryUrl 'https://codes-farm-docker.pkg.coding.net/' // 修改为你的仓库地址
// CODING 制品库无需修改此行,其他仓库需录入凭据管理
registryCredentialsId env.CODING_ARTIFACTS_CREDENTIALS_ID
}
}
stages {
stage('Test') {
steps {
sh 'php -v'
}
}
}
}
使用 Dockerfile 脚本构建环境
如果上述提供的自定义构建环境方式并不能满足您的需求,您还可以使用 Dockerfile 脚本构建环境。
如果项目已经使用 Docker,那么用同一份 Dockerfile
作为持续集成构建环境很方便,符合「DRY」原则。比如代码仓库中 Dockerfile
如下:
FROM php:7.4-apache
RUN apt-get update \
&& apt-get install -y unzip
Jenkinsfile
:
pipeline {
agent any
stages {
stage('Checkout') {
steps {
checkout([
$class: 'GitSCM',
branches: [[name: env.GIT_BUILD_REF]],
userRemoteConfigs: [[url: env.GIT_REPO_URL, credentialsId: env.CREDENTIALS_ID]]
])
}
}
stage('Use Docker') {
agent {
dockerfile {
filename 'Dockerfile' // 可选,自定义 Dockerfile 文件名
dir 'build' // 可选,Dockerfile 所在目录
additionalBuildArgs '--build-arg version=1.0.2' // 可选,docker build 自定义参数
}
}
stages {
stage('Test') {
steps {
sh 'php -v'
sh 'unzip -v'
}
}
}
}
}
}
每次构建都根据 Dockerfile
进行 docker build
会浪费时间,推荐进阶阅读:《最佳实践 - Jenkins Dockerfile 保存镜像用于下次构建》。
使用多个 Docker 镜像或多个 Docker 后台
使用多个 Docker 镜像
pipeline {
agent none
stages {
stage('Back-end') {
agent {
docker { image 'maven:3-alpine' }
}
steps {
sh 'mvn --version'
}
}
stage('Front-end') {
agent {
docker { image 'node:7-alpine' }
}
steps {
sh 'node --version'
}
}
}
}
使用多个 Docker 后台
自动化测试往往需要临时的基础设施(比如 MySQL、Redis、Elasticsearch),无需购买搭建,而是创建一个桥接网络,在其中启动多个 Docker 后台即可,测试完毕自动删除。
pipeline {
agent any
stages {
stage('检出') {...}
stage('准备依赖') {
steps {
script {
sh 'docker network create bridge1';
sh(script:'docker run --net bridge1 --name mysql -d' +
' -e "MYSQL_ROOT_PASSWORD=my-secret-pw" -e "MYSQL_DATABASE=test_db" mysql:5.7', returnStdout: true)
sh(script:'docker run --net bridge1 --name redis -d redis:5', returnStdout: true)
}
}
}
stage('单元测试') {
agent {
docker {
image 'openjdk:14-jdk-alpine'
args '-v /root/.gradle/:/root/.gradle/ -v /root/.m2/:/root/.m2/' +
' --net bridge1 -e "DB_HOST=mysql" -e "REDIS_HOST=redis"' +
' -e "DB_DATABASE=test_db" -e "DB_USERNAME=root" -e "DB_PASSWORD=my-secret-pw"'
reuseNode true
}
}
steps {
sh './gradlew test'
}
}
}
}
直接在持续集成中安装工具
如果您不希望通过 Docker 自定义构建环境,也可以直接在持续集成中安装。
stage('安装 yarn') {
steps {
sh 'npm install -g yarn'
sh 'yarn -v'
}
}
stage('安装依赖') {
steps {
sh 'yarn install'
}
}
更多参数
在自定义 Docker 构建环境时,可以选择是否使用根节点的的工作空间。当勾选该选项时,当前 stage 的 Docker 容器会和 pipeline 在同一个 node 运行,当前 stage 在运行时可以获取 pipeline 工作空间(workspace)的根目录下保存的所有文件。
对应的 Jenkinsfile 参数为 reuseNode
,类型:Boolean,默认为 false:
pipeline {
agent { // pipeline agent
docker {
registryUrl 'https://coding-public-docker.pkg.coding.net'
image 'public/docker/android:29'
}
}
stages {
// 代码被检出到 pipeline agent 的工作空间根目录下
stage('检出代码') {
steps {
checkout([
$class: 'GitSCM',
branches: [[name: env.GIT_BUILD_REF]],
userRemoteConfigs: [[url: env.GIT_REPO_URL, credentialsId: env.CREDENTIALS_ID]]
])
}
}
stage('单元测试') {
agent { // stage pipeline
dockerfile {
// 默认在当前节点工作空间根目录下找名为 “Dockerfile” 的文件构建环境
filename 'Dockerfile'
// 如果 reuseNode 为 false,则无法找到之前检出到 pipeline agent 的工作空间根目录下的 Dockerfile
reuseNode true
}
}
steps {
sh 'npm run test:ci'
junit '*.xml'
}
}
}
}
参考资料
