jenkins作为ci检测代码是否合并的实践
通常我们使用 Jenkins 完成了项目上线整个 CICD 的流程,这是应对高速发展的业务的方案,随着业务进程的发展,一定会到一个以稳定为第一要务的阶段,在这个阶段中,保障高质量的代码上线是其核心,于是,我们就需要着手针对代码检测做一些工作。
这些工作,可以通过与 Gitlab 结合的静态 ci 检测来进行,很多地方介绍的都是基于 gitlab-ci 或者其他诸如 drone 之类的工具来进行,我这里则结合 Jenkins 来进行分析。因为在我的概念中,一直觉得 gitlab 好好做一个代码管理工具就可以了,不必引入过多外部依赖,从而给代码管理本身带来不稳定因素。
为方便演示,我这里以一个 NGINX 配置文件集成的场景来进行讲解。
一些现实教训告诉我们,很多时候的故障或者异常超 80%都是因为变更
引起的,所以我们将所有 NGINX 的配置收归到 gitlab 进行管理,如果要调整就走代码上线的流程,减少直接上机操作的次数。
接下来展示整个配置流程,主要分享思路,具体静态检查逻辑根据需求可进行调整。
# 1,gitlab 配置
gitlab 配置的核心在于,我们首先要控制一些指定分支的权限,比如控制 master 分支不能直接 push,且仅有Maintainers
权限的人能够 merge,配置位置:进入项目
--->Settings
--->Repository
--->Protected Branches
:
这样我们只把部分 leader 赋予Maintainers
权限,即可控制到代码的上线,必须经过这几个大佬的手才行。
注意:
如果在实际生产中,这里要控制的分支,也许 master 未必合适,因为 master 常常应对着正式环境地发布,讲究稳定的同时也考虑一些紧急场景的效率,因此,实际生产中,或许这里控制住预发环境的 pre 分支会更合适!
接着我们要勾选一个相当重要的配置项,only allow merge requests to be merged if the pipeline succeeds
,配置位置:进入项目
--->Settings
--->General
--->Merge request settings
:
此配置项决定了仅当流水线成功时才能够进行 merge,否则 merge 按钮将会是灰色的,使得Maintainers
无法进行代码合并。
# 2,Jenkins 配置
我们创建如下流水线作为当前项目的 ci 配置:
pipeline {
agent {
label "slave_test_go"
}
environment {
// 服务名称
SERVICE_NAME="${JOB_BASE_NAME}"
MODE="DEPLOY"
REASON="无"
REMOTE_HOST="占位"
_VERSION="测试验证"
// 主项目地址
GIT_URL = "https://gitlab.test.com/ops/openrestyConfig.git"
}
parameters {
string(name: 'BRANCH', defaultValue: 'master', description: '请输入将要构建的代码分支')
}
options {
timestamps() // 输出构建日志打印时间信息
timeout(time: 10, unit: 'MINUTES') // 设置构建超时时间
buildDiscarder(logRotator(numToKeepStr: '15')) // 设置历史构建保留次数
gitLabConnection('gitlab-token') // 操作gitlab的token
}
triggers{
gitlab(triggerOnPush: false,triggerOnMergeRequest: true,branchFilterType: 'All',secretToken: "${env.GIT_TOKEN}") // 预留Gitlab提交自动构建
}
stages {
stage('置为pending') {
steps {
script {
try {
updateGitlabCommitStatus name: 'build', state: 'pending'
}catch(exc) {
env.REASON = "置为pending出错"
throw(exc)
}
}
}
}
stage('拉取代码') {
steps {
script {
try {
env.CAUSE = currentBuild.getBuildCauses()[0].(userId)
if ("${CAUSE}" == 'null') {
env.BRANCH = sh(script: 'echo ${gitlabBranch}', returnStdout: true).trim()
}
checkout(
[$class: 'GitSCM', doGenerateSubmoduleConfigurations: false, submoduleCfg: [], extensions: [[$class: 'CloneOption', depth: 1, noTags: false, reference: '', shallow: true]],
branches: [[name: "$BRANCH"]],userRemoteConfigs: [[url: "${env.GIT_URL}", credentialsId: "cicd-pass"]]]
)
// 定义全局变量
env.COMMIT_ID = sh(script: 'git log --pretty=format:%h', returnStdout: true).trim() // 提交ID
env.COMMIT_USER = sh(script: 'git log --pretty=format:%an', returnStdout: true).trim() // 提交者
env.COMMIT_TIME = sh(script: 'git log --pretty=format:%ai', returnStdout: true).trim() // 提交时间
env.COMMIT_INFO = sh(script: 'git log --pretty=format:%s', returnStdout: true).trim() // 提交信息
}catch(exc) {
env.REASON = "拉取代码出错"
throw(exc)
}
}
}
}
stage('检测项目') {
steps {
script {
try {
docker.image('reg.test.com/base/openresty:1.19.3.2').inside(" -v /etc/hosts:/etc/hosts") {
sh '''nginx -c $WORKSPACE/nginx.conf -t'''
}
}catch(exc) {
env.REASON = "检测项目出错"
throw(exc)
}
}
}
}
}
post {
success {
updateGitlabCommitStatus(name: 'build', state: 'success')
addGitLabMRComment comment: "🤖Jenkins ci check success🥳, see the log: ${BUILD_URL}console"
}
failure {
updateGitlabCommitStatus(name: 'build', state: 'failed')
addGitLabMRComment comment: "🤖Jenkins ci check failed🤯, see the log: ${BUILD_URL}console"
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
这里有几个要点:
gitLabConnection
:要在系统管理中创建一个可操作 gitlab 的 token,非常重要,如果没有此项配置,则流水线无法将状态回调给 gitlab 项目。配置位置:
系统管理
--->系统配置
--->Gitlab
:这里限制了 triggers 条件仅为 merge 时触发,当前还可以根据需求限制固定分支,从而将 ci 检测控制在指定的范围里。
触发构建之前,首先将状态置为 pennding,从而让 gitlab 项目无法 merge。
拉完代码之后,我们借助集成好的镜像对 NGINX 配置文件进行语法检测。
然后在最后借助流水线的 post 能力,将不同的状态回调给 gitlab。
关于如何配置自动触发的流水线,这里就不展开了,可以参考:自动构建的原始配置以及 pipeline 中的用法 (opens new window)。只不过在 gitlab 添加 hook 的时候仅配置 merge event 即可。
# 3,验证
这个时候我们可以走正常开发流程,新需求从 master 切出来一个独立的分支,调整完成之后,提交自己的普通分支,然后创建一个 merge request:
注意,此时 merge 按钮仍旧是绿色的,这是一个不足之处,只有当流水线开始触发,将状态置为 pennding 时才会转变,如果你知道有更好的办法控制这个按钮,欢迎留言交流。
接着就会自动触发流水线进行静态检测,如果成功,则会有如下显示:
此时需要进行 merge 的同学其实不必再纠结提交配置文件的语法是否有问题,只需要 Review 下 Changes 的内容即可决定是否 merge。
如果失败,则状态如下:
注意,当流水线检测失败之后,gitlab 的 merge 状态也会变成灰色无法 merge,并提示:The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure
,那么对应的开发同学就需要解决掉对应的冲突或者问题之后方可再次提交 merge,自己的代码才能够通过这道关卡而上线。
其他资料: