从同一存储库加载Jenkins管道共享库

sch*_*rer 25 groovy shared-libraries jenkins jenkins-pipeline

TL; DR有没有办法将代码导入Jenkinsfile 本地存储库(除了load步骤)?

为什么?

我已经体验到,对于复杂的构建而言,它Jenkinsfile变得笨重而且不易维护.
既然构建作业是代码,那么使用与其他代码相同的方法会很棒.也就是说,我想将它分成更小(更易于维护)的单元并对它们进行单元测试.

我尝试了什么

  • 共享库:允许将Jenkins管道逻辑划分为单独模块中的较小文件,甚至可以对其进行单元测试.
    但是,它们需要位于不同的存储库中(如果不在GitHub上)必须配置到Jenkins中.
  • load步骤:允许从存储库加载groovy 脚本.
    但是,文件必须是脚本而不是"完整"的groovy类,这使得很多文件或类很难相互依赖.例如继承是不可能的.
    此外,在Jenkins作业上进行重放时不会显示这些文件,这使得它们难以开发和调试.

我的问题

  • 有没有办法(或解决方法)在同一个存储库中创建共享库,Jenkinsfile并将此库导入Jenkinsfile?
  • 或者还有其他方法我还没试过呢?

示例目录结构

与为共享库描述的目录结构类似,我希望在单个存储库中具有以下内容.

(root)
+- someModule
|   +- ...
+- jenkins           # Classes/Scripts used by Jenkins in a separate module
|   +- src                       # Groovy source files
|      +- org
|          +- foo
|              +- Bar.groovy     # for org.foo.Bar class
|   +- test                      # Groovy test files
|      +- org
|          +- foo
|              +- BarTest.groovy # Test for org.foo.Bar class
|   +- pom.xml or build.groovy   # Build for local library
+- Jenkinsfile     # Build "someModule", uses classes from "jenkins" module
Run Code Online (Sandbox Code Playgroud)

Jes*_*ick 7

解决方法:

library identifier: 'shared-library@version', retriever: legacySCM(scm)
Run Code Online (Sandbox Code Playgroud)

PR 37中当前采用的方法将无法与构建代理一起正常工作,并且无论如何仅适用于使用library步骤的脚本,而不适用于@Library注释.

顺便说一下,从load步骤加载的文件会出现在Replay中.但是,您的脚本无法静态引用此类文件中定义的类型.换句话说,您可以模拟库vars/*.groovy但不是src/**/*.groovy与当前PR 37相同的限制.


Paw*_*cha 5

我想这样做的正确方法是实现自定义SCMRetriever。

但是,您可以使用以下技巧:

假设jenkins/vars/log.groovy您的本地仓库中包含:

def info(message) {
    echo "INFO: ${message}"
}
Run Code Online (Sandbox Code Playgroud)

您Jenkinsfile可以jenkins/使用以下library步骤从目录中加载该共享库:

node('node1') { // load library
    checkout scm
    // create new git repo inside jenkins subdirectory
    sh('cd jenkins && git init && git add --all . && git commit -m init &> /dev/null') 
    def repoPath = sh(returnStdout: true, script: 'pwd').trim() + "/jenkins"
    library identifier: 'local-lib@master', retriever: modernSCM([$class: 'GitSCMSource', remote: repoPath])
}

node('node2') {
    stage('Build') {
        log.info("called shared lib") // use the loaded library
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 您的回答启发我写了一篇博客,更深入地解释了这个解决方案并涵盖了一些陷阱。https://www.code-held.com/2020/01/22/jenkins-local-shared-library/ 我还将解决方案抽象为共享库供其他人使用:https://github.com/mld- ger/jenkins-library-subfolder-loader (2认同)

Kar*_*Gil 5

你可以看看我写的插件,它允许使用你的管道作为共享库的 repo 的子目录:https : //github.com/karolgil/SharedLibrary

在构建和安装它之后,您可以简单地将以下内容放入您的管道中:

@SharedLibrary('dir/in/repo') _
Run Code Online (Sandbox Code Playgroud)

开始将其dir/in/repo用作管道的共享库。


ioc*_*nel 2

想做同样的事情并最终创建了这个:

https://github.com/jenkinsci/workflow-cps-global-lib-plugin/pull/37

这是我的使用方法:

https://github.com/syndesisio/syndesis-pipeline-library/blob/master/Jenkinsfile#L3

就我而言,我想创建一个 Jenkinsfile,它实际上tests是存储库包含的管道库。

让我知道您的想法,并随时在 PR 上添加您的评论。