CI/CD自动构建发布环境搭建使用实践
通过C/C++的cmake工程示例项目,构建Gitlab+Jenkins+Artifactory自动构建发布环境。其中
- Gitlab提供源码仓库功能,通过webhook自动触发器(trigger)触发Jenkins构建动作
- Jenkins提供构建发布中心角色,通过从Gitlab拉取源码(Git)、构建(Build)、测试(Test)、发布(Publish)、部署(Deploy), 完成整个CI/CD流程
- Artifactory提供二进制生成物(tar,zip,deb,exe等)仓库功能,以及每次编译构建详情辅助信息
测试环境
- Host机器: WSL2(Ubuntu 20.04.2 LTS )
- 采用docker容器运行服务
- Gitlab镜像:gitlab/gitlab-ce:latest、
- Jenkins镜像: jenkins/jenkins:latest
- Artifactory镜像: docker.binary.io/jfrog/artifactory-oss:latest
安装配置过程中碰到的坑
- Jenkins内置openjdk11版本,对Gitlab插件太高,需要降到jdk8版本
- Artifactory TCP端口8081和8082,其中8081是API端口,8082才是Web前端端口,需要将两者都映射出来
- 新版Jenkins内的Artifactory插件和旧版本配置有较大不同,在Publish时采用直接指定Artifactory服务器地址临时方案
- Gtilab配置Webhook时,首先需要管理员对网络配置打开webhook网络使能。
- 如果容器启动过程中异常,用docker logs <容器ID>查看调试日志,基本能找到问题。
- HOST端volumes映射到容器内,需要保证路径有读写权限
docker-compose.yaml文件
version: "3.2"
services:
gitlab:
image: gitlab/gitlab-ce:latest
container_name: gitlab-container
restart: always
environment:
- GITLAB_SECRETS_DB_KEY_BASE=******
- GITLAB_HOST=172.26.180.63
- GITLAB_PORT=10081
- GITLAB_SSH_PORT=10023
ports:
- "10081:80"
- "10023:22"
volumes:
- '/data/gitlab/config:/etc/gitlab'
- '/data/gitlab/logs:/var/log/gitlab'
- '/data/gitlab/data:/var/opt/gitlab'
jenkins:
image: jenkins/jenkins:latest
container_name: jenkins-container
restart: always
ports:
- "8081:8080"
- '50000:50000'
volumes:
- '/var/run/docker.sock:/var/run/docker.sock'
- '/data/jenkins/jenkins_home:/var/jenkins_home'
environment:
- "JENKINS_OPTS=--prefix=/jenkins"
- "JAVA_HOME=/var/jenkins_home/opt/jdk1.8.0_202"
- "PATH=/var/jenkins_home/opt/jdk1.8.0_202/bin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
artifactory:
image: docker.bintray.io/jfrog/artifactory-oss:latest
container_name: artifactory-container
restart: always
ports:
- "9081:8081"
- "9082:8082"
volumes:
- '/var/opt/jfrog/artifactory:/var/opt/jfrog/artifactory'
在Jenkins容器中设置环境变量JAVA_HOME和PATH,用jdk8替换openjdk11; Artifactory容器把8081和8082端口都映射出来。Jenkins容器启动后除了安装默认插件外,还需要安装: Gitlab、Cmake、Aritfactory等插件,同时把WSL2作为Jenkins的node节点(slave节点)加到构建节点集合内,通过ssh(用户名/密码)方式登录,并设定其标签(cmake ubuntu), 在WSL2子系统内安装cmake,openjdk, gcc,cppcheck等编译工具套件。
工程
Gitlab工程基于jenkinsexample, 涉及Qt部分被剔除。该工程内含Jenkins构建脚本文件Jenkinsfile,通过改动该文件做实验操作。在Jenkins仪表盘界面可以构建流水线(pipeline)和多分枝流水线(multibranch pipeline)项目,在Gitlab端配置集成Jenkins,可将工程和Jenkins项目进行链接,实现自动触发.
Jenkinsfile文件内容
pipeline {
agent {
label 'cmake'
}
options {
buildDiscarder(logRotator(numToKeepStr: '10'))
}
parameters {
booleanParam name: 'RUN_TESTS', defaultValue: true, description: 'Run Tests?'
booleanParam name: 'RUN_ANALYSIS', defaultValue: true, description: 'Run Static Code Analysis?'
booleanParam name: 'DEPLOY', defaultValue: true, description: 'Deploy Artifacts?'
booleanParam name: 'PUBLISH', defaultValue: true, description: 'Publish Artifacts?'
}
stages {
stage('Build') {
steps {
cmake arguments: '-DCMAKE_CXX_FLAGS=-g', installation: 'InSearchPath'
cmakeBuild buildType: 'Release', cleanBuild: true, installation: 'InSearchPath', steps: [[withCmake: true]]
}
}
stage('Test') {
when {
environment name: 'RUN_TESTS', value: 'true'
}
steps {
ctest 'InSearchPath'
}
}
stage('Analyse') {
when {
environment name: 'RUN_ANALYSIS', value: 'true'
}
steps {
sh label: '', returnStatus: true, script: 'cppcheck . --xml --language=c++ --suppressions-list=suppressions.txt 2> cppcheck-result.xml'
publishCppcheck allowNoReport: true, ignoreBlankFiles: true, pattern: '**/cppcheck-result.xml'
}
}
stage('Deploy') {
when {
environment name: 'DEPLOY', value: 'true'
}
steps {
sh label: '', returnStatus: true, script: '''cp jenkinsexample ~
cp test/testPro ~'''
}
}
stage('Publish'){
when {
environment name: 'PUBLISH', value: 'true'
}
steps {
script{
def server = Artifactory.newServer url: 'http://172.26.180.63:9081/artifactory', username:'admin' , password:'******'
def uploadSpec="""{
"files":[
{
"pattern":"jenkinsexample",
"target":"example-project/${BUILD_NUMBER}/",
"props":"XXX=xxx;YYY=yyy"
}
]
}"""
buildInfo = server.upload spec: uploadSpec
buildInfo.env.collect()
server.publishBuildInfo buildInfo
}//script
}
}
}
}
Jenkins的新Pipeline语法和旧版本有一些差异,实践中会碰到一些使用错误,可以查看Jenkins项目的console输出定位出错位置,进行调试; 新版本Artifactory插件和旧版本配置有出入(暂时搞不懂如何使用),这里直接定义了Artifactory服务器!