使用 JenkinsFile 构建 golang 项目
2024-08-26 by dongnan
简介
Jenkinsfile 是一个包含 Jenkins Pipeline
定义的文本文件,使用 Groovy
编写。它描述了构建、测试和部署项目的步骤。
通过 Jenkinsfile
,可以实现持续集成和持续部署(CI/CD)的自动化过程。
目标
使用 JenkinsFile
方式,构建 golang 项目。
环境描述
- OS: Ubuntu Server 20.04 LTS
- Docker: 19.03.15
- Docker-compose: 1.29.2
- Jenkins: 2.452.2 LTS
前提条件
- 首先是 jenkins 环境,如果你没有 Jenkins,可以使用
Docker
部署。参考这篇文章 。 - 其次是 golang 项目托管在 git 仓库,并且在项目中创建了一个
Jenkinsfile
文件。
基本结构
Jenkinsfile
的基本结构可以分为以下几个部分:
- 声明式 Pipeline: 使用声明式语法定义流水线,语法简单、易读。
- 脚本式 Pipeline: 使用脚本式语法定义流水线,语法灵活、功能强大,但较复杂。
下面的例子是 声明式 Pipeline 为例。
示例
pipeline {
agent any
environment {
//GO
GO111MODULE = 'on'
GOPROXY = 'https://goproxy.cn,direct'
GOPATH = "${env.WORKSPACE}/go"
GOBIN = "${env.GOPATH}/bin"
PATH = "${env.GOBIN}:${env.PATH}"
APPNAME = 'ci-go'
// Docker
HUBADDR = 'yjt.xxx.com'
HUBPROJECT = 'test'
HUBENV = "${BRANCH_NAME}"
DOCKERFILE_HOME = 'docker'
DOCKER_IMAGE_INFO = """${sh(
returnStdout: true,
script: 'tail -n1 ./version.txt'
).trim()}""" //返回值会带有换行符,使用trim 替换掉!!!
DOCKER_IMAGE_TAG = "${HUBADDR}/${HUBPROJECT}/${HUBENV}/${DOCKER_IMAGE_INFO}"
// Email
RECIPIENTS = 'admin@xxx.com'
//RECIPIENTS = 'admin@xxx.com, dongnan@xxx.com'
SUBJECT_FAILURE = "Build Failure: ${env.JOB_NAME} #${env.BUILD_NUMBER}"
SUBJECT_FIXED = "Build Fixed: ${env.JOB_NAME} #${env.BUILD_NUMBER}"
SUBJECT_NOT_BUILT = "Build Skipped: ${env.JOB_NAME} #${env.BUILD_NUMBER}"
BODY_TEMPLATE = """<p>Build Status: ${BUILD_STATUS}</p>
<p>Job: ${env.JOB_NAME} #${env.BUILD_NUMBER}</p>
<p>Check console output at Jenkins_URL to view the results.</p>"""
}
stages {
// stage('Checkout') {
// steps {
// git 'https://your-git-repo-url.git'
// }
// }
stage('Check Docker Image') {
steps {
// groovy
script {
def imageExists = sh(script: "docker inspect ${DOCKER_IMAGE_TAG} > /dev/null 2>&1", returnStatus: true) == 0
if (imageExists) {
currentBuild.result = 'NOT_BUILT'
echo "Docker image ${DOCKER_IMAGE_TAG} already exists, skipping build."
currentBuild.description = "Docker image exists, build skipped."
return
} else {
echo "Docker image ${DOCKER_IMAGE_TAG} does not exist, proceeding with build."
}
}
}
}
stage('Build Go') {
// docker镜像不存在,则执行构建步骤,否则跳过此步骤
when {
expression { currentBuild.result != 'NOT_BUILT' }
}
steps {
// Go版本; 清理并下载依赖; 编译Go
sh "go version && go mod tidy && go build -o ${APPNAME}"
sh "mv ${APPNAME} ${DOCKERFILE_HOME}/"
}
}
stage('Build Docker') {
// docker镜像不存在,则执行构建步骤,否则跳过此步骤
when {
expression { currentBuild.result != 'NOT_BUILT' }
}
steps {
// 多行 shell
sh """
cd ${DOCKERFILE_HOME}
pwd
docker build -t ${DOCKER_IMAGE_TAG} .
"""
// sh "docker push ${DOCKER_IMAGE_TAG}"
}
}
stage('Test Image') {
when {
expression { currentBuild.result != 'NOT_BUILT' }
}
steps {
// 添加你的测试步骤
sh 'echo "Running tests..."'
}
}
}
post {
failure {
script {
def subject = SUBJECT_FAILURE
def body = BODY_TEMPLATE.replace('null', 'FAILURE')
mail(
to: "${RECIPIENTS}",
subject: subject,
body: body,
mimeType: 'text/html'
)
}
}
fixed {
script {
def subject = SUBJECT_FIXED
def body = BODY_TEMPLATE.replace('null', 'FIXED')
mail(
to: "${RECIPIENTS}",
subject: subject,
body: body,
mimeType: 'text/html'
)
}
}
notBuilt {
script {
def subject = SUBJECT_NOT_BUILT
def body = BODY_TEMPLATE.replace('null', 'NOT_BUILT')
mail(
to: "${RECIPIENTS}",
subject: subject,
body: body,
mimeType: 'text/html'
)
}
}
}
}
主要元素:
- environment: 定义 golang、docker、邮件 所使用的环境变量。
- stages:阶段包括 stage 与 steps。
- Check Docker Image:检查 docker 镜像是否存在,存在则退出。
- Build Go: 编译 golang 程序。
- Build Docker:打包 docker 镜像。
- Test Image:测试镜像,过程略。
- post :定义在 Pipeline 结束后执行的操作。
- 这里只用了 failure、fixe、notBuilt 这3种条件块。
配置项目
在 Jenkins 的项目中配置如下:
配置 git
仓库地址与分支
确定 Jenkinsfile
文件的路径位置
验证
通过 git 仓库中的 Jenkinsfile
文件构建项目,不同的阶段状态:
总结
Jenkinsfile
提供了一种强大且灵活的方法来定义 CI/CD 流水线。
通过使用声明式或脚本式 Pipeline 语法,可以根据项目需求自动化构建、测试和部署过程。
利用环境变量、多分支 Pipeline 和条件执行等功能,可以进一步增强流水线的功能和灵活性。
参考文档
- Jenkins 传统构建 与 Pipeline构建的区别
- https://www.jenkins.io/zh/doc/book/pipeline/jenkinsfile/
- https://groovy-lang.org/single-page-documentation.html