绝大部份项目的构建流程是:拉取源码---执行单元测试---构建目标包---构建镜像---推送镜像---集群拉取镜像部署 ,此脚本为Jenkins流水线共享库(Jenkins pipline shared library),将所有步骤统一定义到此脚本中,所有项目引用共享库即可,支持多分支构建,不同的分支发布到不同的环境。引用共享库之后,就只需要在项目的Jenkinsfile中,定义各自项目的参数即可,避免了每个项目都编写大量高度重复的构建脚本:
#!groovy
library 'pipeline-shared-library'
def map = [:]
map.put('repoBranch',env.BRANCH_NAME)
map.put('repoUrl','http://gitlab.balabala.com/development/balabala.git')
map.put('appName','demo-app')
map.put('k8sSvcName','kubernetes-service-name')
map.put('tag','v1.0.1')
map.put('k8sResourceType','Deployment')
map.put('runUnitTest','0')
map.put('credentialsId','3818ec5a-b476-4471-8c47-db36ed4d5eb0')
map.put('proRegistryAddr','127.0.0.1:8888/registry')
map.put('fatRegistryAddr','registry.cn-hangzhou.aliyuncs.com/app_k8s')
map.put('multibrachComposeName','demo-app-multi_master')
map.put('pubRepoUrl','https://nexus.balabala.com/repository/maven-releases/')
map.put('pubRepoUrl','https://nexus.balabala.com/repository/maven-snapshots/')
map.put('gradleConfigFileName','build.gradle')
if(env.BRANCH_NAME == 'master') {
map.put('k8sNamespace','pro')
map.put('multibrachComposeName', 'demo-multi_master')
map.put('buildJar','demo-service-1.0.0-RELEASE.jar')
}
if(env.BRANCH_NAME == 'feature/demo'){
map.put('k8sNamespace','fat')
map.put('multibrachComposeName', 'demo-multipipeline_feature_demo')
map.put('buildJar','demo-service-1.0.0-SNAPSHOT.jar')
}
ci("gradle",map)
#!groovy
def call(String type, Map map) {
if (type == "gradle") {
pipeline {
agent any
//triggers {
// parameterizedCron(env.BRANCH_NAME != 'master' ? '''H/1 * * * * % ABC=XYZ''' : '')
//}
parameters {
choice(
name: 'env',
choices: ['fat', 'uat', 'pro'],
description: 'fat:测试环境部署\nuat:演示环境部署\npro:生产环境部署'
)
string(name: 'repoBranch', defaultValue: "${map.repoBranch}", description: 'git分支名称')
string(name: 'repoUrl', defaultValue: "${map.repoUrl}", description: '项目仓库的地址')
string(name: 'appName', defaultValue: "${map.appName}", description: '应用的名称,打包Docker镜像时以此命名')
string(name: 'k8sSvcName', defaultValue: "${map.k8sSvcName}", description: 'Kubernetes服务的名称,不要超过24个字符(实际使用时根据Kubernetes服务名称的规定)')
string(name: 'tag', defaultValue: "${map.tag}", description: '版本标签,镜像标签')
string(name: 'k8sResourceType', defaultValue: "${map.k8sResourceType}", description: 'Kubernetes资源类型,如Deployment、StatefulSet等等')
string(name: 'runUnitTest', defaultValue: "${map.runUnitTest}", description: '是否运行单元测试')
string(name: 'k8sNamespace', defaultValue: "${map.k8sNamespace}", description: 'Kubernetes命名空间')
string(name: 'credentialsId', defaultValue: "${map.credentialsId}", description: 'Jenkins认证凭据ID,用于获取原始码')
string(name: 'fatRegistryAddr', defaultValue: "${map.fatRegistryAddr}", description: 'FAT环境注册地址')
string(name: 'multibrachComposeName', defaultValue: "${map.multibrachComposeName}", description: '' +
'多分支构建时,分支组合名称,例如项目的名字是dolphin,有一个hotfix分支,在多分支构建时,传入Jenkins自动生成的名称dolphin_hotfix')
string(name: 'pubRepoUrl', defaultValue: "${map.pubRepoUrl}", description: 'Jar包发布的仓库地址')
string(name: 'buildJar', defaultValue: "${map.buildJar}", description: '构建目标Jar包名称')
}
tools {
gradle "Gradle"
}
environment {
GRADLE_HOME = "${tool 'Gradle'}"
PATH = "${env.GRADLE_HOME}/bin:${env.PATH}"
repoUrl = "${map.repoUrl}"
registryAddr = getRegistryAddr("${params.env}" == null ? "fat" : "${params.env}", map)
k8sResourceType = getKubernetesResourceType("${params.k8sResourceType}")
}
stages {
stage('checkout-source') {
steps {
git branch: "${params.repoBranch}",
credentialsId: "${params.credentialsId}",
url: "${params.repoUrl}"
}
}
stage('unit-test') {
when {
expression {
"${params.runUnitTest}" == '1'
}
}
steps {
sh "./gradlew test"
}
}
stage('build-api') {
steps {
script {
try {
sh "./gradlew :${params.multibrachComposeName == null ? params.appName : params.multibrachComposeName}:${params.appName}-api:build publishMavenPublicationToMavenRepository -x test"
} catch (err) {
echo "Publish jar failed, but will be continue," + err.getMessage()
}
}
}
}
stage('build') {
steps {
sh "./gradlew :${params.multibrachComposeName == null ? params.appName : params.multibrachComposeName}:${params.appName}-service:build -x test"
}
}
stage('prune-image'){
steps{
sh "docker system prune"
}
}
stage('package-image') {
steps {
sh "docker build -f ./Dockerfile --build-arg buildJar=\"${params.buildJar}\" -t=\"${params.appName}:${params.tag}\" ."
}
}
stage('tag-image') {
steps {
sh "docker tag ${params.appName}:${params.tag} ${registryAddr}/${params.appName}:${params.tag}"
}
}
stage('push-image') {
steps {
sh "docker push ${registryAddr}/${params.appName}:${params.tag}"
}
}
stage('rolling-update-fat') {
when {
expression {
"${params.env}" == 'fat'
}
}
steps {
sh "kubectl rollout restart ${k8sResourceType} ${k8sSvcName} -n ${params.k8sNamespace}"
}
}
stage('rolling-update-uat') {
when {
expression {
"${params.env}" == 'uat'
}
}
steps {
sh "kubectl rollout restart ${k8sResourceType} ${k8sSvcName} -n ${params.k8sNamespace}"
}
}
stage('rolling-update-pro') {
when {
expression {
"${params.env}" == 'pro'
}
}
steps {
sh "/Users/dabaidabai/.jenkins/workspace/build_shell/update-production-pod.sh ${params.tag} ${k8sSvcName} ${params.k8sNamespace} ${params.appName} ${k8sResourceType}"
}
}
}
}
}
}
/**
* 获取不同部署环境的容器推送地址
*
* @param env
* @param map
* @return
*/
def getRegistryAddr(env, Map map) {
print("choice:" + env)
if ("pro" == env) {
return "${map.proRegistryAddr}"
}
if ("fat" == env) {
print("fataddress:" + "${map.fatRegistryAddr}")
return "${map.fatRegistryAddr}"
}
if ("uat" == env) {
return "${map.uatRegistryAddr}"
}
}
/**
* 获取Kubernetes资源类型
* @param value
* @return
*/
def getKubernetesResourceType(value) {
return value == null ? "Deployment" : value
}