创建可恢复的jenkins管道脚本
我最近正在考虑使用Jenkins管道脚本,一个问题是我没有找到一种创建内部可重用UTIL代码的智能方法,想象一下,我有一个通用函数创建可恢复的jenkins管道脚本,jenkins,jenkins-workflow,jenkins-pipeline,Jenkins,Jenkins Workflow,Jenkins Pipeline,我最近正在考虑使用Jenkins管道脚本,一个问题是我没有找到一种创建内部可重用UTIL代码的智能方法,想象一下,我有一个通用函数helloworld,它将被许多管道作业使用,所以我希望创建一个utils.jar可以将它注入作业类路径 我注意到Jenkins和的概念类似,但我担心这个插件: 因为它是一个插件,所以我们需要通过jenkins插件管理器安装/升级它,然后可能需要重新启动才能应用更改,这不是我想要看到的,因为UTIL可能会更改,始终添加,我们希望它可以立即可用 其次,这是jenkins
helloworld
,它将被许多管道作业使用,所以我希望创建一个utils.jar
可以将它注入作业类路径
我注意到Jenkins和的概念类似,但我担心这个插件:
因为它是一个插件,所以我们需要通过jenkins插件管理器安装/升级它,然后可能需要重新启动才能应用更改,这不是我想要看到的,因为UTIL可能会更改,始终添加,我们希望它可以立即可用
其次,这是jenkins的官方共享库,我不想(或者他们不会应用我们)将私有代码放入jenkins repo
有什么好主意吗?使用()可以让所有管道脚本都可以访问代码。您不必为此构建插件,也不必重新启动Jenkins
例如,这是调用此公共函数的
编辑(2017年2月): 该库可以通过Jenkins的内部Git服务器访问,也可以通过其他方式(例如通过Chef)部署到Jenkins用户主目录中的
workflow lib/
目录。(仍有可能,但非常不顺利)
可以通过以下方式配置全局库:
注释位于@Library('github.com/…')
中,指向共享库repo的URLJenkinsfile
- 在Jenkins作业的文件夹级别上配置
- 在Jenkins配置中配置为全局库,其优点是代码是可信的,即不受脚本安全性的约束
第一个方法和最后一个方法的组合是一个未显式加载的共享库,然后仅使用其在
Jenkinsfile
:@library('mysharedlib')
中的名称请求该共享库。以下是我们当前为重复使用Jenkinsfile代码而使用的解决方案:
node {
curl_cmd = "curl -H 'Accept: application/vnd.github.v3.raw' -H 'Authorization: token ${env.GITHUB_TOKEN}' https://raw.githubusercontent.com/example/foobar/master/shared/Jenkinsfile > Jenkinsfile.t
sh "${curl_cmd}"
load 'Jenkinsfile.tmp'
}
我可能有点难看,但它确实可以工作,除此之外,它还允许我们在共享代码之前或之后插入一些特定于存储库的代码。根据您计划重用代码的频率,您还可以将一个函数(或一组函数)作为另一个管道的一部分加载
{
// ...your pipeline code...
git 'http://urlToYourGit/projectContainingYourScript'
pipeline = load 'global-functions.groovy'
pipeline.helloworld() // Call one of your defined function
// ...some other pipeline code...
}
与StephenKing的解决方案相比,这个解决方案似乎有点麻烦,但我喜欢这个解决方案的地方是,我的全局函数都提交给Git,任何人都可以轻松地修改它们,而不需要(几乎)了解Jenkins,只需了解Groovy的基本知识
在Groovy脚本中,如果要加载,请确保在最后添加
并返回该。这将允许您稍后拨打电话。否则,当设置pipeline=load global functions.groovy时,变量将设置为null
我更喜欢创建一个从存储库调用的buildRepo()
方法。它的签名是def call(givenConfig=[:])
,因此也可以使用参数调用它,例如:
buildRepo([
"npm": [
"cypress": false
]
])
我将参数保持在绝对最小值,并尝试依赖约定而不是配置
我提供了一个默认配置,这也是我放置文档的地方:
def defaultConfig = [
/**
* The Jenkins node, or label, that will be allocated for this build.
*/
"jenkinsNode": "BUILD",
/**
* All config specific to NPM repo type.
*/
"npm": [
/**
* Whether or not to run Cypress tests, if there are any.
*/
"cypress": true
]
]
def effectiveConfig merge(defaultConfig, givenConfig)
println "Configuration is documented here: https://whereverYouHos/getConfig.groovy"
println "Default config: " + defaultConfig
println "Given config: " + givenConfig
println "Effective config: " + effectiveConfig
使用有效的配置和存储库的内容,我创建了一个构建计划
...
derivedBuildPlan.npm.cypress = effectiveConfig.npm.cypress && packageJSON.devDependencies.cypress
...
构建计划是某些构建方法的输入,如:
node(buildPlan.jenkinsNode) {
stage("Install") {
sh "npm install"
}
stage("Build") {
sh "npm run build"
}
if (buildPlan.npm.tslint) {
stage("TSlint") {
sh "npm run tslint"
}
}
if (buildPlan.npm.eslint) {
stage("ESlint") {
sh "npm run eslint"
}
}
if (buildPlan.npm.cypress) {
stage("Cypress") {
sh "npm run e2e:cypress"
}
}
}
我在Jenkins.io上写了一篇关于这一点的博文:
我不明白你的意思。。这里的答案应该很清楚,但是这个博客也很有用:哈,很好的解释,如果是这样的话,那么这正是我想要的。就是这样:-)你可以看看所有的回购协议,它们都使用Jenkinsfile
s,其中只包含对管道的调用。我肯定会这样做。可惜您无法在Jenkinsfile中定义函数:(请参见此处:由于您的Jenkinsfile.tmp
脚本似乎已签出到Git repo,您可能只需要使用基本的Git/scm签出步骤来加载脚本,而不是手动执行卷曲。如果这允许我从存储库签出单个文件,那就太好了。但如果这可以签出整个存储库,那就太好了很明显,这不是我们想要的,因为这个repo可能非常大。在这种情况下,另一种可能是将您的Jenkinsfile.tmp
Git repo签出为自由式Jenkins作业,它只对您的Git repo进行定期轮询,然后从其他工作区加载您的Jenkins文件。我们正在更新$Jenkins_主页/工作流-lib/
通过Chef从Github自动创建目录。你也可以通过Cron作业来创建目录。我也不喜欢Jenkins的内部伪git服务器。记得在共享groovy脚本的末尾添加并返回这个。看看这个答案@Pom12使用Github Enterprise的URL是什么?你是什么意思?我的答案适用于您是否正在使用Gitlab、Github或任何Git存储库管理工具。。。