创建可恢复的jenkins管道脚本

创建可恢复的jenkins管道脚本,jenkins,jenkins-workflow,jenkins-pipeline,Jenkins,Jenkins Workflow,Jenkins Pipeline,我最近正在考虑使用Jenkins管道脚本,一个问题是我没有找到一种创建内部可重用UTIL代码的智能方法,想象一下,我有一个通用函数helloworld,它将被许多管道作业使用,所以我希望创建一个utils.jar可以将它注入作业类路径 我注意到Jenkins和的概念类似,但我担心这个插件: 因为它是一个插件,所以我们需要通过jenkins插件管理器安装/升级它,然后可能需要重新启动才能应用更改,这不是我想要看到的,因为UTIL可能会更改,始终添加,我们希望它可以立即可用 其次,这是jenkins

我最近正在考虑使用Jenkins管道脚本,一个问题是我没有找到一种创建内部可重用UTIL代码的智能方法,想象一下,我有一个通用函数
helloworld
,它将被许多管道作业使用,所以我希望创建一个
utils.jar
可以将它注入作业类路径

我注意到Jenkins和的概念类似,但我担心这个插件:

因为它是一个插件,所以我们需要通过jenkins插件管理器安装/升级它,然后可能需要重新启动才能应用更改,这不是我想要看到的,因为UTIL可能会更改,始终添加,我们希望它可以立即可用

其次,这是jenkins的官方共享库,我不想(或者他们不会应用我们)将私有代码放入jenkins repo

有什么好主意吗?

使用()可以让所有管道脚本都可以访问代码。您不必为此构建插件,也不必重新启动Jenkins

例如,这是调用此公共函数的


编辑(2017年2月): 该库可以通过Jenkins的内部Git服务器访问,也可以通过其他方式(例如通过Chef)部署到Jenkins用户主目录中的
workflow lib/
目录。(仍有可能,但非常不顺利)

可以通过以下方式配置全局库:

  • @Library('github.com/…')
    注释位于
    Jenkinsfile
    中,指向共享库repo的URL
  • 在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存储库管理工具。。。