詹金斯搭建
Jenkins共享库的正式文档相当不错,但并不完美。
本文扩展了如何将Jenkins共享库与私有git存储库,语义版本一起使用以及对库进行单元测试,并提供了可运行的示例。
简短介绍
当处理多个相似的管道时,Jenkins共享库是一个方便的工具。 如果您正在寻找减少Jenkins管道中代码重复的方法,那么本文可能是开始的正确位置。
本文假定读者以某种方式熟悉Jenkinsfiles或至少熟悉管道作为代码的概念。 如果您不熟悉Jenkinsfiles,这是我的基本介绍的链接 。
对于那些新来的CI
您的公司可能正在经历Agile / DevOps转型,突然之间就有推动对每个项目使用持续集成(CI)甚至连续交付/部署(CD)的推动。 也许只是团队自己想要开始使用CI,并正在寻找有关这些DevOps的指南。 无论您遇到什么情况,开始构建和部署应用程序时通常都会遇到三个常见问题:
- 我们应该使用什么配置项?
- 我们的管道非常相似。 我们如何避免重复?
- 对管道进行单元测试是否合理?
在我看来,CI之旅开始时通常只考虑第一个问题,而后两个问题只有在新自动化的管道发展壮大并需要专人负责维护之后才会实现……等等,这不是DevOps的原意。应该……好吧,没关系,让我们继续吧。
我们应该使用什么配置项?
这个问题的答案通常是“詹金斯”,因为它仍然是市场上最受欢迎和功能最丰富的CI。 哦,它是免费的,默认情况下,它成为您管理层认为最好的候选人之一。
我们的管道非常相似。 我们如何避免重复?
这个问题更有趣,因为詹金斯有两个选择。 一种选择是使用Jenkins Job DSL插件(JDSL)完全自动化您的工作的初始创建和内容,但是使用JDSL通常意味着多个团队有一个Jenkins实例,或者整个公司有一个中央实例(这很好用)当所有项目都遵循相同的约定时)。 同样,创建高质量的种子JDSL作业的初始成本可能会很耗时,并且它会承担您使用它创建的更多作业的费用。 那么,如果您不想大量投资JDSL怎么办? 我的答案是尝试使用詹金斯共享库 (JSL)。 尽管可以将JDSL与JSL结合使用,但是在本文中,我将只关注JSL。
对管道进行单元测试是否合理?
让我问您一个问题:您如何测试新的管道功能? 如果在每次进行少量更改后都必须将更改推送到Jenkins并等待构建看到它们的执行效果,您可以吗? 如果没有,那么您将必须能够在没有CI服务器存在的情况下在本地运行管道或对其进行单元测试。
在理想的世界中,所有管道都是简单的,幂等的,以声明性方式(例如,使用ansible剧本 )编写的,没有逻辑,您应该能够在没有CI服务器存在的情况下在本地测试它们的运行。
但是,如果在Jenkins管道中使用groovy ,那么对管道的各个阶段进行逻辑爬虫并不少见。 在这种情况下,如果您使用JSL,则可以像测试其他任何常规代码一样对代码进行单元测试。
当前,很难对所有与基础架构相关的代码进行整体测试,因为它需要昂贵的模拟,隔离和幂等性组合。 但是,如果您有机会轻松地对管道的一部分进行单元测试,则可以这样做。 根据我的经验,当您必须对管道的大部分内容进行单元测试时,这意味着应将代码提取为(Jenkins)插件,因为该插件尚不存在。
一些自动化工具具有“空运行”模式,但是在更复杂的情况下,它不够用。 不幸的是,可测试性仍然不是大多数基础架构工具的主要关注点。
使用Jenkins共享库的优缺点
组织中的管道越相似,使用JSL所期望的结果就越好。
好东西:
- 可以由多个团队使用不同的Jenkins实例共享。
- 初始成本非常低,可以逐步进行项目介绍。
- 可以模块化和单元测试。
- 可以并且应该对源代码进行版本控制。
- 它的开发可以通过与公司中其他项目相同的封闭式构建 。
- 可以公开使用,也可以设为私有,具体取决于您的存储库设置。
- 可以进行语义版本控制,从而轻松引入重大更改而不会干扰依赖的管道。
丑陋的:
有一些不可避免的障碍,但是要这样考虑:替代方案通常归结为某种代码重复或令人讨厌的做法,例如使用未为其设计的VCS将公司的所有源代码保存在一个庞大的代码存储库( monorepo )中。
这里是:
- 进行语义版本控制时,至少需要更改两个存储库:JSL存储库和包含Jenkinsfiles的所有从属存储库。
- E2e测试新管道功能需要从JSL存储库提交和推送(一次或多次),并从相关存储库进行提交和推送(仅推送一次,重新生成多次)。 这不是JSL本身的问题,而是Jenkins管道可测试性已有十年的历史了。 端到端的测试真的很困难,因为它们最初并不是设计为可测试的。
这可能会让您放慢速度,但请考虑其他选择。 代码重复是维护的噩梦。 如果您认为monorepo是答案,那么除非您使用吹笛者,否则我会回避它。
简而言之,JSL具有与创建和维护开源库相似的收益和成本。 最重要的是,它具有端到端的可测试性,这对我来说是最大的缺点。 我希望将来我们能够以一流的公民身份获得带有可测试管道的CI。
定义詹金斯共享库
JSL通常是一个语义版本化的gradle groovy项目,保存在git存储库中,该存储库是Jenkins克隆的git,并在使用Jenkinsfile请求的管道作业时放置在类路径中 。 (赞!)
如果您了解上一段,那么您可能已经对它们如何协同工作有了很好的了解。 如果没有,请不要担心,我们将逐步进行解释。
为了弄清楚Jenkins在幕后的实际作用,我们将运行使用JSL的最基本的管道作业。
设置一个Jenkins实例
为了演示Jenkins在使用JSL时正在做什么,我需要一个Jenkins实例。 我将在本地计算机上运行一个,为此,我将把我的GitHub 项目与dockerized Jenkins,几个示例性Jenkinsfiles和另一个dockerized服务一起使用,该服务将从文件夹中加载我的Jenkinsfiles,并告诉Jenkins创建工作。
此设置仅用于演示目的,不适合生产使用。
如果您想阅读本文并运行示例,则需要安装docker和docker-compose 。
git clone https: //github.com/hoto/jenkinsfile-examples.git -b blog-jenkins-shared-libraries cd jenkinsfile-examples docker-compose pull docker-compose up
Jenkins应该在您的Web浏览器上的localhost:8080
上可用
已经有几份工作了。 它们的配置基于位于存储库内jenkinsfiles
目录中的Jenkinsfiles <job_name>.groovy
文件。 编辑,创建或删除任何这些Jenkins文件将使更改立即反映在Jenkins中(有时需要刷新页面)。
Jenkins已设置为禁用身份验证,并安装了几个预安装的插件,因此在运行后可以立即使用。
jenkinsfile-examples
项目的结构:
$ pwd ~/projects/jenkinsfile-examples $ tree . ├── Dockerfile ├── docker-compose.yml ├── configs │ └── C- 001 -jenkins-shared-library-build-and-test.xml ├── jenkinsfiles │ ├── 001 -stages-declarative-style.groovy │ ├── 002 -stages-scripted-style.groovy │ ├── 003 -stages-parallel.groovy │ ├── 004 -stages-parallel-with-sequential.groovy │ ├── 020 -post-actions.groovy │ ├── 030 -wait-until.groovy │ ├── 031 -wait-until-with-post-actions.groovy │ ├── 050 -shared-library-where-is-it-cloned.groovy │ ├── 051 -shared-library-using-global-variables.groovy │ ├── 052 -shared-library-using-classes.groovy │ ├── 070 -parameterized-build-choices.groovy │ ├── 090 -wait- for -user-input-not-blocking-executor.groovy │ └── 091 -wait- for -user-input-blocking-executor.groovy └── source
└── jenkins
└── usr
└── share
└── jenkins
├── plugins.txt
└── ref
├── config.xml
└── scriptApproval.xml
引用共享库
让我们运行一个名为050-shared-library-where-is-it-cloned
,它使用以下Jenkinsfile 050-shared-library-where-is-it-cloned.groovy
(如您所见,Jenkinsfiles可以命名为您的项目Jenkinsfile
惯例称其为Jenkinsfile
):
library(
identifier: 'jenkins-shared-library@1.0.4' ,
retriever: modernSCM(
[
$ class : 'GitSCMSource' ,
remote: ' https://github.com/hoto/jenkins-shared-library.git ' remote: ' https://github.com/hoto/jenkins-shared-library.git '
]
) ) pipeline {
agent any
stages {
stage( 'Where is Jenkins Shared Library cloned' ) {
steps {
script {
sh 'ls -la ../050-shared-library-where-is-it-cloned@libs/jenkins-shared-library'
}
}
}
} }
我们对这项工作应该感兴趣的是:
- 请求位于https://github.com/hoto/jenkins-shared-library的
library
,引用git标签1.0.4
- 创建一个列出库所在位置的阶段。 这只是为了揭示詹金斯在幕后所做的魔术。
让我们运行它并查看构建日志。
分解日志:
Jenkins尝试加载共享库:
Loading library jenkins-shared-library @1 .0. 4 Attempting to resolve 1.0 . 4 from remote references...
它找不到它,因此它克隆了引用的git仓库https://github.com/hoto/jenkins-shared-library.git
并签出了标记为1.0.4
的提交:
git init /var/jenkins_home/workspace/ 050 git init /var/jenkins_home/workspace/ -shared-library-where-is-it-cloned @libs /jenkins-shared-library ... git config remote.origin.url https: //github.com/hoto/jenkins-shared-library.git ... Checking out Revision b80d1b3ab131580ba51c94d3d97dd65530ec2a66 ( 1.0 . 4 )
库存储库已从作业工作区外部克隆到../050-shared-library-where-is-it-cloned@libs/jenkins-shared-library
目录中。 我们可以通过在阶段内部执行的命令来验证:
ls -la ../ 050 -shared-library-where-is-it-cloned @libs /jenkins-shared-library total 72 drwxr-xr-x 8 jenkins jenkins 4096 Nov 4 18 : 49 . drwxr-xr-x 3 jenkins jenkins 4096 Nov 4 18 : 49 .. drwxr-xr-x 2 jenkins jenkins 4096 Nov 4 18 : 49 .circleci -rw-r--r-- 1 jenkins jenkins 245 Nov 4 18 : 49 .editorconfig drwxr-xr-x 8 jenkins jenkins 4096 Nov 4 18 : 49 .git -rw-r--r-- 1 jenkins jenkins 81 Nov 4 18 : 49 .gitattributes -rw-r--r-- 1 jenkins jenkins 34 Nov 4 18 : 49 .gitignore -rw-r--r-- 1 jenkins jenkins 1211 Nov 4 18 : 49 Jenkinsfile -rw-r--r-- 1 jenkins jenkins 1100 Nov 4 18 : 49 LICENSE -rw-r--r-- 1 jenkins jenkins 676 Nov 4 18 : 49 README.md -rw-r--r-- 1 jenkins jenkins 789 Nov 4 18 : 49 build.gradle drwxr-xr-x 3 jenkins jenkins 4096 Nov 4 18 : 49 gradle -rwxr-xr-x 1 jenkins jenkins 5296 Nov 4 18 : 49 gradlew -rw-r--r-- 1 jenkins jenkins 2260 Nov 4 18 : 49 gradlew.bat drwxr-xr-x 3 jenkins jenkins 4096 Nov 4 18 : 49 src drwxr-xr-x 4 jenkins jenkins 4096 Nov 4 18 : 49 test drwxr-xr-x 2 jenkins jenkins 4096 Nov 4 18 : 49 vars
050-shared-library-where-is-it-cloned
工作的目的仅在于显示Jenkins如何将共享库下载到其工作区中。 现在,让我们运行一些更有用的东西。
使用Jenkins共享库
使用全局变量
作业051-shared-library-using-global-variables
正在使用Jenkins 脚本化的流水线模型和流畅的界面设计模式,从而可以编写优雅,通用和可重用的流水线。 如果您有很多类似的项目,则可以使用这种方法使用通用的Jenkinsfile创建模板存储库,并轻松编写新项目及其管道的脚本。
该模型是我的首选模型,因为它具有最大的功能,可重用性和多功能性,同时使管道易于同时读取。 我建议您先尝试一下。
有两种编写这样的管道的策略:
- 提取所有内容,包括命令本身。 只有当所有项目都遵循相同的约定(公司中每个人都知道)时,此方法才有效。 这样做的缺点是,仅查看Jenkinsfile就会很难分辨使用什么命令来构建项目。
- 除了命令外,对所有内容进行抽象。 当您的公司没有建立类似项目的惯例时,这很有用。 如果您有很多遗留项目,那么使用此策略可能会为您省去一些麻烦。
此示例使用策略2:
jsl = library(
identifier: 'jenkins-shared-library@1.0.4' ,
retriever: modernSCM(
[
$ class : 'GitSCMSource' ,
remote: ' https://github.com/hoto/jenkins-shared-library.git ' remote: ' https://github.com/hoto/jenkins-shared-library.git '
]
) ) simplePipeline([jsl: jsl])
.build(
command: 'My build command'
)
.unitTest(
command: 'My unit test command'
)
.deploy(
command: 'My deploy command'
)
另外,当管道增长时,您可以将构建阶段与部署阶段分开,以使维护变得更容易。
使用类
Job 052-shared-library-using-classes
正在使用新的Jenkins 声明性管道模型。 在为单个项目快速创建管道时,我发现声明性模型很有用。 当您尝试将其抽象为多个项目时,它很快就会不足。 我会远离它,并使用脚本模型编写自定义管道。
您仍然可以将声明性模型与脚本化模型混合使用,但我不推荐这样做,无论如何,这是一个示例:
jsl = library(
identifier: 'jenkins-shared-library@1.0.4' ,
retriever: modernSCM(
[
$ class : 'GitSCMSource' ,
remote: ' https://github.com/hoto/jenkins-shared-library.git ' remote: ' https://github.com/hoto/jenkins-shared-library.git '
]
) ) def build = jsl.com.mycompany.jenkins.Build. new ( this ) pipeline {
agent any
stages {
stage( 'Init' ) {
steps {
script {
build.setBuildDescription(
title: "#${env.BUILD_NUMBER} My build title." ,
description: 'My build description.'
)
}
}
}
stage( 'Build' ) {
steps {
script {
echo 'Building...'
}
}
}
stage( 'Unit Test' ) {
steps {
script {
echo 'Unit Testing...'
}
}
}
stage( 'Deploy' ) {
steps {
script {
echo 'Deploying...'
}
}
}
} }
将Jenkins共享库设为私有
在本文中使用的示例中,引用的JSL是从GitHub上的公共存储库中克隆的。 通过引用,我指的是这一部分:
jsl = library(
identifier: 'jenkins-shared-library@1.0.4' ,
retriever: modernSCM(
[
$ class : 'GitSCMSource' ,
remote: ' https://github.com/hoto/jenkins-shared-library.git ' remote: ' https://github.com/hoto/jenkins-shared-library.git '
]
) )
现在,如果您希望JSL存储库是私有的怎么办? 那很容易做到。
要克隆私有JSL存储库,Jenkins需要能够与托管服务提供商进行身份验证。 您可以通过许多不同的方式实现这一目标:
- 通过使用添加到您的Jenkins凭据中的基本身份验证(用户和密码),然后引用
credentialsId
:jsl = library( identifier: 'jenkins-shared-library@1.0.4' , retriever: modernSCM( [ $ class : 'GitSCMSource' , remote: ' https://github.com/hoto/jenkins-shared-library.git ' remote: ' https://github.com/hoto/jenkins-shared-library.git ' , 'github-cicd-user' credentialsId: 'github-cicd-user' ] ) )
- 通过使用添加到您的Jenkins凭据中的ssh密钥,然后引用
credentialsId
:jsl = library( identifier: 'jenkins-shared-library@1.0.4' , retriever: modernSCM( [ $ class : 'GitSCMSource' , remote: 'git@github.com:hoto/jenkins-shared-library.git' , 'github-cicd-ssh-rw' credentialsId: 'github-cicd-ssh-rw' ] ) )
- 通过向您的Jenkins实例添加ssh密钥并使用私有ssh URL引用JSL,例如
git@github.com:hoto/jenkins-shared-library.git
这实际上可能很难配置,因此根据您的Jenkins设置先尝试其他方法。 另外,这种方法不是我的最爱,因为它“神奇”,因为它隐藏了Jenkins身份验证以及使用哪个ssh密钥的详细信息。
而且,显然,JSL存储库不必托管在GitHub上(它甚至不必是git存储库),它可以从私有的GitLab或Bitbucket等托管。
Jenkins共享库的结构
我们已经研究了如何使用JSL,但是如何构造JSL存储库? 让我们解构本文中使用的共享库存储库。
源代码位于https://github.com/hoto/jenkins-shared-library/tree/1.0.4。
从标记1.0.4
,存储库的完整结构:
$ pwd ~/projects/jenkins-shared-library $ tree -a . ├── .circleci │ └── config.yml ├── Jenkinsfile ├── build.gradle ├── gradle │ └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── src │ └── com │ └── mycompany │ └── jenkins │ ├── Build.groovy │ └── Git.groovy ├── test │ ├── com │ │ └── mycompany │ │ └── jenkins │ │ ├── BuildShould.groovy │ │ └── GitShould.groovy │ └── mocks │ └── WorkflowScriptStub.groovy └── vars
└── simplePipeline.groovy
单元测试共享库
让我们从头开始分解这个项目。
├── .circleci │ └── config.yml ├── Jenkinsfile ├── build.gradle ├── gradle │ └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat
这个仓库是一个标准的gradle groovy项目,没有什么特别的。 它使用gradle包装器gradlew
签入到源代码管理中。 这是一个标准过程,这样做可以确保CI使用与开发人员相同的gradle版本。 另一个优点是,通过使用gradlew
(unix)或gradlew.bat
(windows)脚本,您不需要安装gradle,它将把gradle二进制文件下载到存储库中。
我在项目中包含了一个Jenkinsfile,但由于我不想为运行Jenkins的机器付费,因此未使用它。 我仍然希望在每次推送存储库时自动测试共享库项目,因此我添加了一个.circleci/config.yml
文件,并将GitHub存储库连接到免费的circleci在线服务。
如果是真实情况,我将使用Jenkins实例并创建一个引用共享库存储库的多分支管道作业。 但是,没有詹金斯即服务,因此在此示例中我使用的是circle ci。
为了向您展示如何使用Jenkins实例测试您的JSL存储库, jenkinsfile-examples
项目中包含一个预制的作业配置,名为C-001-jenkins-shared-library-build-and-test
:
因为我的JSL项目是标准的gradle git存储库,所以在多分支管道作业中只需指定两件事:项目存储库位置(GitHub)和Jenkinsfile的位置(root)。 打开C-001-jenkins-shared-library-build-and-test
作业设置以验证:
让我们看一下jenkinsfile-shared-library
Jenkinsfile
,然后最终运行该作业。
jsl = library(
identifier: "jenkins-shared-library@${env.BRANCH_NAME}" ,
retriever: modernSCM(
[
$ class : 'GitSCMSource' ,
remote: ' https://github.com/hoto/jenkins-shared-library.git ' remote: ' https://github.com/hoto/jenkins-shared-library.git '
]
) ) build = jsl.com.mycompany.jenkins.Build. new ( this ) git = jsl.com.mycompany.jenkins.Git. new ( this ) pipeline {
agent {
docker {
image 'docker.io/gradle:4.5.1-jdk8'
args '-v /root/.gradle:/home/gradle/.gradle'
}
}
options {
timeout(time: 5 , unit: 'MINUTES' )
}
stages {
stage( 'Init' ) {
steps {
script {
COMMIT_MESSAGE = git.commitMessage()
COMMIT_AUTHOR = git.commitAuthor()
build.setBuildDescription(
message: COMMIT_MESSAGE,
description: COMMIT_AUTHOR
)
}
}
}
stage( 'Unit Tests' ) {
steps {
script {
sh './gradlew test'
}
}
}
} }
关于此特定管道,有两点值得注意:
- 它在每个阶段都使用docker作为代理,这使得运行非常容易,因为Jenkins执行程序仅需要docker。 无需在Jenkins上安装任何工具和编译器,一切都来自docker容器。
- 在构建和测试自己时,它使用了一个巧妙的引用自己的技巧。
如果您没有注意到管道正在使用指向自身的共享库:
jsl = library(
identifier: "jenkins-shared-library@${env.BRANCH_NAME}" ,
retriever: modernSCM(
[
$ class : 'GitSCMSource' ,
remote: ' https://github.com/hoto/jenkins-shared-library.git ' remote: ' https://github.com/hoto/jenkins-shared-library.git '
]
) )
最重要的是,标识符使用环境变量${env.BRANCH_NAME}
指向库版本。 当您将其与多分支管道作业和门控拉取请求结合使用时,从技术上讲,您可以在将它们合并到master分支之前添加新的管道功能并对它们进行单元测试。 想一想; 可能性是无限的……但是,老实说,我不认为将所有管道功能都塞入一个Jenkinsfile是可行的。 您最终可能会使用几个组件,仅此而已。
首先,“ Unit Tests
阶段的构建花费了1min 15s
而重试相同的构建之后,它仅花费了4s
因为所有依赖项都已缓存在主机上。 这是通过将一些额外的参数传递给docker来从主机args '-v /root/.gradle:/home/gradle/.gradle'
装载gradle缓存来args '-v /root/.gradle:/home/gradle/.gradle'
否则每个新阶段每次都必须下载所有依赖项因为每个阶段都是一个新的Docker容器。
共享库类
在groovy中,您可以使用类或脚本。 恕我直言,大多数逻辑应放在可单元测试的类中,然后从groovy脚本(Jenkinsfile本身是groovy脚本)中引用。
├── src │ └── com │ └── mycompany │ └── jenkins │ ├── Build.groovy │ └── Git.groovy ├── test │ ├── com │ │ └── mycompany │ │ └── jenkins │ │ ├── BuildShould.groovy │ │ └── GitShould.groovy │ └── mocks │ └── WorkflowScriptStub.groovy
src
目录类似于标准Java源目录结构。 执行管道时,此目录将添加到类路径中。
在测试中,我使用的是Spock测试框架,这是将groovy用于单元测试的一个很好的好处。
共享库全局变量
vars
目录托管脚本,这些脚本定义了可从管道访问的全局变量。 每个<name>.groovy
文件的基本名称是一个camelCased
标识符。
└── vars
└── simplePipeline.groovy
官方文档将“全局变量”用于我认为类似于函数的内容。 我不是詹金斯(Jenkins)还是时髦专家,所以我将使用与不混淆别人的相同命名法。
我的vars
文件夹中唯一的文件: simplePipeline.groovy
是一个自定义步骤指令。 这是一个步骤,因为它包含带有特殊声明call(Map args)
的函数。
def call(Map args) {
someCodeHere() }
当您从管道中的任何位置调用simplePipeline(args)
时,将触发该call
函数。
我在这里不打算讨论很多细节,但是请注意,您可以使用其他几个不同的“全局变量”。
管道示例
为了让您了解使用JSL的管道的外观,这是我一直在从事的项目中的一个示例。 虽然仍然有很多改进的空间。
jsl = library(
identifier: 'jenkins-shared-library@17.0.0' ,
retriever: modernSCM(
[
$ class : 'GitSCMSource' ,
remote : ' ssh://git@bitbucket.mycompany.com/ftl/myservice.git ' ,
'bitbucket-cicd-ssh-rw' credentialsId: 'bitbucket-cicd-ssh-rw'
]
) ) def buildData = environment.gatherBuildData(
jsl: jsl,
projectName: 'myservice' ,
projectRepositoryUrl: ' https://bitbucket.mycompany.com/projects/ftl/repos/myservice ' ,
teamName: 'FTL' ,
servicesNames: [ 'myservice' ],
servicesUrls: [
myservice: [
test: ' http://myservice.dev.mycompany.com ' ,
pre : ' http://myservice.pre.mycompany.com ' pre : ' http://myservice.pre.mycompany.com ' ,
pro : ' http://myservice.pro.mycompany.com '
]
],
mainBranch: 'master' ) bitbucket(buildData).jobInProgress() def slack = newSlack(
jsl: jsl,
buildData: buildData,
officialChannel: '#ftl-builds' ,
testChannel: '#ftl-builds-test' ,
whenBranch: 'master' ) dockerPipeline(jsl: jsl, type: 'maven' , buildData: buildData)
.withSlack(slack)
.setBuildDescription()
.build( "" "
./mvnw versions:set -D newVersion= '${buildData.version}' -D generateBackupPoms= false
./mvnw clean package -D skipTests
"" ")
.unitTests( './mvnw test' )
.integrationTestsWithPostgres( './mvnw verify -D skipTests' )
.pactTests( "" "
./mvnw test \
-D skipTests= true \
-D skipPacts= false \
-D pact.provider.version= '${buildData.version}' \
-D pact.verifier.publishResults=
"" ")
.gitTag(
tag: buildData.version,
whenBranch: 'master'
) deployment(jsl: jsl, buildData: buildData)
.withSlack(slack)
.deployTest(
serviceName: 'myservice' ,
artifactDir: './myservice-parent/myservice-webapp/target/' ,
artifactName: "myservice-${buildData.version}.zip" ,
whenBranch: 'master'
)
.deployPre(
serviceName: 'myservice' ,
artifactDir: './myservice-parent/myservice-webapp/target/' ,
artifactName: "myservice-${buildData.version}.zip" ,
whenBranch: 'master'
)
.gatling(
environment: 'PRE' ,
type: 'maven' ,
command: "" "
./mvnw gatling:execute \
-pl myservice-parent/myservice-stress \
-D myservice.stress.environment=pre
"" ",
whenBranch: 'master'
)
.promoteArtifactFromPreToPro(
serviceName: 'myservice' ,
artifactName: "myservice-${buildData.version}.zip" ,
whenBranch: 'master'
)
.createJiraTicketRequestingDeploymentToPro(
whenBranch: 'master'
) bitbucket(buildData).jobSucceeded()
结束
总结一下。 Jenkins共享库需要时间和精力来正确学习和设置。 尝试使管线尽可能声明性,并仅对其中包含逻辑的部分进行单元测试。
在用Groovy编写管道的任何自定义代码之前,请首先检查是否有用于它的插件。 詹金斯(Jenkins)有成千上万个,这就是它如此受欢迎的主要原因。
如果您很幸运,并且使用适当的工具在生产中只处理容器,那么应该更容易简化管道。
另一方面,如果您要处理大量的遗留应用程序,那么没有容器和晦涩的bash脚本,那么您可能不愿看Ansible,而不是将管道重写为时髦的东西。 但是,这是另一个话题。
翻译自: https://www.javacodegeeks.com/2019/05/private-jenkins-shared-libraries.html
詹金斯搭建