Jenkins简介
一、简介
Jenkins是一款开源的CI&CD软件,可以用于自动化执行各种任务,包括构建、测试和部署软件等;它支持各种运行方式,可通过系统包、Docker或独立的Java程序。
二、安装与运行
1、安装
- 必须项
需要安装Java 8
- 下载
下载适合操作系统的安装包运行安装。
安装后会自动运行Jenkins;也可以直接下载war包并运行。
2、运行
-
打开终端进入到Jenkins安装目录(或war包所在目录)
-
运行
java -jar jenkins.war --httpPort=8080
首次访问时会提示(admin)初始密码路径:
C:\Users\acer123\.jenkins\secrets\initialAdminPassword
也可以在用户Configure - Password
中修改密码。
3、问题及处理方法
- 实例已离线
登录后向导(SetupWizard)中显示”该Jenkins实例似乎已离线。”:
此时需要访问http://localhost:8080/pluginManager/advanced,修改升级站点URL的值为:
http://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json
然后重启jenkins。
- 插件安装
直接安装插件时报SunCertPathBuilderException错:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.build(Unknown Source)
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source)
at java.security.cert.CertPathBuilder.build(Unknown Source)
Caused: sun.security.validator.ValidatorException: PKIX path building failed
at sun.security.validator.PKIXValidator.doBuild(Unknown Source)
at sun.security.validator.PKIXValidator.engineValidate(Unknown Source)
at sun.security.validator.Validator.validate(Unknown Source)
at sun.security.ssl.X509TrustManagerImpl.validate(Unknown Source)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(Unknown Source)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
Caused: javax.net.ssl.SSLHandshakeException
at sun.security.ssl.Alerts.getSSLException(Unknown Source)
at sun.security.ssl.SSLSocketImpl.fatal(Unknown Source)
at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
......
Caused: java.io.IOException: Failed to load https://updates.jenkins.io/download/plugins/ant/1.11/ant.hpi to C:\Users\acer123\.jenkins\plugins\ant.jpi.tmp
at hudson.model.UpdateCenter$UpdateCenterConfiguration.download(UpdateCenter.java:1287)
Caused: java.io.IOException: Failed to download from https://updates.jenkins.io/download/plugins/ant/1.11/ant.hpi
at hudson.model.UpdateCenter$UpdateCenterConfiguration.download(UpdateCenter.java:1321)
at hudson.model.UpdateCenter$DownloadJob._run(UpdateCenter.java:1869)
at hudson.model.UpdateCenter$InstallationJob._run(UpdateCenter.java:2153)
at hudson.model.UpdateCenter$DownloadJob.run(UpdateCenter.java:1843)
at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at hudson.remoting.AtmostOneThreadExecutor$Worker.run(AtmostOneThreadExecutor.java:118)
at java.lang.Thread.run(Unknown Source)
处理方式:
手工访问上面报错中的下载地址,下载后在 插件管理 -- 高级
菜单的上传插件功能区上传安装即可。
- 更有效的处理方式
在Plugin Manager中设置升级站点的URL为:
http://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json
修改jenkins运行目录updates/default.json
中的文件内容:
C:\Users\acer123\.jenkins\updates\default.json
将https://updates.jenkins.io/download
统一替换为http://mirrors.tuna.tsinghua.edu.cn/jenkins
并重新启动即可。
三、流水线(Pipeline)语法
流水线是用户定义的一个持续交付(CD)流水线模型,它向Jenkins中添加了一组强大的工具, 可以将用例持续集成到CD流水线中。它定义了整个构建过程,包括构建、布署、测试和交付应用程序。
流水线最基本的部分是”步骤”(step),步骤的基本作用是告诉Jenkins要做什么,并作为声明性语法和脚本流水线(Pipeline)语法的基本构建块。
1、相关述语
- 节点(node)
节点是Jenkins运行的机器,称为节点。在脚本流水线语法中使用节点块。
node{
}
- 阶段(stage)
此块中包含流水线中的一系列步骤,例如:构建、测试和部署流程都集中在一个阶段。通常情况通过阶段块就可以看到Jenkins流水线的全过程。
stages {
stage('Build') {
steps {
//...
}
}
stage('Test') {
steps {
//...
}
}
}
嵌套、并行、串行:
pipeline {
agent none
stages {
stage('Non-Sequential Stage') {
agent {
label 'for-non-sequential'
}
steps {
echo "On Non-Sequential Stage"
}
}
stage('Sequential') {
agent {
label 'for-sequential'
}
environment {
FOR_SEQUENTIAL = "some-value"
}
stages {
stage('In Sequential 1') {
steps {
echo "In Sequential 1"
}
}
stage('In Sequential 2') {
steps {
echo "In Sequential 2"
}
}
stage('Parallel In Sequential') {
parallel {
stage('In Parallel 1') {
steps {
echo "In Parallel 1"
}
}
stage('In Parallel 2') {
steps {
echo "In Parallel 2"
}
}
}
}
}
}
}
}
- 工具(tools)
定义用来自动安装并设置到PATH上的内容,如果没有指定代理(agent none
),则忽略该部分。
pipeline {
agent any
tools {
maven 'apache-maven-3.0.1'
}
stages {
stage('Example') {
steps {
sh 'mvn --version'
}
}
}
}
- 步骤(step)
步骤是在指定时间执行的单个任务,例如执行shell命令:
...
steps {
sh 'make'
}
...
- 脚本(script)
script是一个定义在step中的脚本流水线(Scripted Pipeline):
pipeline {
agent any
stages {
stage('Example') {
steps {
echo 'Hello World'
script {
def browsers = ['chrome', 'firefox']
for (int i = 0; i < browsers.size(); ++i) {
echo "Testing the ${browsers[i]} browser"
}
}
}
}
}
}
-
流程控制(Flow Control)
脚本流水线(Scripted Pipeline)从Jenkinsfile的顶部向下连续执行,也支持
if/eles
和try/catch/finally
流程控制语法:if/else
node { stage('Example') { if (env.BRANCH_NAME == 'master') { echo 'I only execute on the master branch' } else { echo 'I execute elsewhere' } } }
try/catch/finally
node { stage('Example') { try { sh 'exit 1' } catch (exc) { echo 'Something failed, I should sound the klaxons!' throw } } }
-
When
when语法允许Pipeline根据给定条件确定是否应执行该stage;when块中必须至少包含一个条件,如果包含多个条件,则所有子条件都必须返回true时才执行stage:
pipeline {
agent any
stages {
stage('Example Build') {
steps {
echo 'Hello World'
}
}
stage('Example Deploy') {
when {
branch 'production'
}
steps {
echo 'Deploying'
}
}
}
}
2、内置条件
- branch
当正在构建的分支与给定的分支模式匹配时执行stage:
when { branch 'master' }
- buildingTag
当构建生成一个标记时执行stage:
when { buildingTag() }
- changelog
如果构建的SCM(Source Coce Management)更改日志(changelog)包含指定的正则表达式时执行stage:
when { changelog '.*^\\[DEPENDENCY\\] .+$' }
- changeset
如果构建的SCM变更集(changeset)包含一个或多个与给定模式匹配的文件,则执行stage:
when { changeset "**/*.js" }
- changeRequest
如果当前的构建是为了”变更请求”(例如GitHub上的Pull Request等)时执行stage:
when { changeRequest() }
when { changeRequest target: 'master' }
when { changeRequest authorEmail: "[\\w_-.]+@example.com", comparator: 'REGEXP' }
当没有传递参数时,stage将在每个更改请求上运行。
- environment
当指定的环境变量被设置为给定的值时执行stage:
when { environment name: 'DEPLOY_TO', value: 'production' }
- equals
当期望值等于实际值时执行stage:
when { equals expected: 2, actual: currentBuild.number }
- expression
当指定的Groovy表达式计算结果为true时执行stage:
when { expression { return params.DEBUG_BUILD } }
- tag
如果TAG_NAME变量与给定的模式匹配,则执行stage:
when { tag "release-*" }
- not
当嵌套条件为false时执行stage,必须包含一个条件:
when { not { branch 'master' } }
- allOf
当所有嵌套条件都为真时执行stage,必须至少包含一个条件:
when { allOf { branch 'master'; environment name: 'DEPLOY_TO', value: 'production' } }
- anyOf
当至少有一个嵌套条件为真时执行stage,必须至少包含一个条件:
when { anyOf { branch 'master'; branch 'staging' } }
- triggeredBy
当当前构建被给定的参数触发时,执行stage:
when { triggeredBy 'SCMTrigger' }
when { triggeredBy 'TimerTrigger' }
- example
pipeline {
agent any
stages {
stage('Example Build') {
steps {
echo 'Hello World'
}
}
stage('Example Deploy') {
when {
expression { BRANCH_NAME ==~ /(production|staging)/ }
anyOf {
environment name: 'DEPLOY_TO', value: 'production'
environment name: 'DEPLOY_TO', value: 'staging'
}
}
steps {
echo 'Deploying'
}
}
}
}
3、指令(Directives)
- environment
environment指令定义所有步骤的环境变量或特定于阶段的step:
pipeline {
agent any
environment {
CC = 'clang'
}
stages {
stage('Example') {
environment {
AN_ACCESS_KEY = credentials('my-predefined-secret-text')
}
steps {
sh 'printenv'
}
}
}
}
其中,定义在最外层的environment块将应用于pipeline中的所有step;定义在stage中的environment块只将给定的环境变量应用到此stage中的步骤;在environment块中可以通过credentials()
方法访问预定义的凭证。
- options
options指令允许在pipeline里配置特定于流水线的选项:
pipeline {
agent any
options {
timeout(time: 1, unit: 'HOURS')
}
stages {
stage('Example') {
steps {
echo 'Hello World'
}
}
}
}
上面为Pipeline运行设置一个超时周期,在此之后Jenkins会中止此Pipeline。
- parameters
parameters指令提供了用户在触发Pipeline时应该提供的参数列表:
pipeline {
agent any
parameters {
string(name: 'PERSON', defaultValue: 'Mr Jenkins', description: 'Who should I say hello to?')
text(name: 'BIOGRAPHY', defaultValue: '', description: 'Enter some information about the person')
booleanParam(name: 'TOGGLE', defaultValue: true, description: 'Toggle this value')
choice(name: 'CHOICE', choices: ['One', 'Two', 'Three'], description: 'Pick something')
password(name: 'PASSWORD', defaultValue: 'SECRET', description: 'Enter a password')
}
stages {
stage('Example') {
steps {
echo "Hello ${params.PERSON}"
echo "Biography: ${params.BIOGRAPHY}"
echo "Toggle: ${params.TOGGLE}"
echo "Choice: ${params.CHOICE}"
echo "Password: ${params.PASSWORD}"
}
}
}
}
- triggers
triggers指令定义了重新触发管道的自动方式:
pipeline {
agent any
triggers {
cron('H */4 * * 1-5')
}
stages {
stage('Example') {
steps {
echo 'Hello World'
}
}
}
}
4、声明式流水线
所有有效的声明式Pipelines必须定义在pipeline
块中,例如:
pipeline {
/* insert Declarative Pipeline here */
}
Declarative Pipeline中的基有本语句和表达式遵循与Groovy相同的语法规则,但有以下例外:
-
没有分号作为语句分隔符,每个语句必须在它自己的行上。
-
块必须只包含章节(Sections)、指令(Directives)、步骤(Steps)或赋值语句。
-
属性引用语句被视为无参方法调用,例如:
input
会被当作input()
。
Jenkinsfile (Declarative Pipeline):
pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'make'
}
}
stage('Test'){
steps {
sh 'make check'
junit 'reports/**/*.xml'
}
}
stage('Deploy') {
steps {
sh 'make publish'
}
}
}
}
其中:
- agent any
表示在任何可用的代理上,执行流水线。
- stage(‘Xxx’)
定义Xxx阶段。
steps{}
在steps中定义此阶段需要执行的步骤。
5、脚本流水线
脚本流水线在轻量级执行程序的帮助下在Jenkins主机上运行,它使用很少的资源将流水线(pipeline)转换为原子命令。
脚本流水线通过一个或多个node块执行核心工作:
Jenkinsfile (Scripted Pipeline):
node {
stage('Build') {
//...
}
stage('Test') {
//...
}
stage('Deploy') {
//...
}
}
虽然stage块在脚本化流水线语法中是可选的,但使用stage块可以清楚的显示Jenkins UI中的每个任务子集。
四、样例
1、Hello World
- 创建项目
点击New Item
菜单,构建一个自由风格的软件项目。
- 配置任务
在Build内容区,添加”执行Windows批处理命令”,输入命令:echo Hello
后保存。
- 构建项目
点击 立即构建,构建完可以查看构建历史。
- 构建输出
进入某次构建历史后,点击Console Output
可以查看控制台输出内容。
2、流水线
- 创建项目
创建项目时选择 流水线 项目。
- 配置脚本
Pipeline Script内容如下:
pipeline {
agent any
stages {
stage('Stage 1') {
steps {
echo 'Hello world!'
}
}
}
post {
always {
echo 'This will always run'
}
success {
echo 'This will run only if successful'
}
failure {
echo 'This will run only if failed'
}
unstable {
echo 'This will run only if the run was marked as unstable'
}
changed {
echo 'This will run only if the state of the Pipeline has changed'
echo 'For example, if the Pipeline was previously failing but is now successful'
}
}
}
- 构建并查看输出