在多个作业中重用詹金斯管道的阶段
Reusing stages of a jenkins pipeline in multiple jobs
我的团队正在迁移到 Jenkins 2,我正在使用管道插件,以便我们的构建可以存在于我们的存储库中。因为在我们公司分配存储库有很多开销,所以我们有一个包含许多子项目和子模块的存储库。
我想要的 是每个子模块的 Junit/checkstyle/etc 报告的单独构建和报告,以及每个子模块的最后 "build and deploy" 步骤项目把它们放在一起。
我目前的计划 是为每个子模块创建单独的作业,以便它们获得自己的 junit/checkstyle/etc 报告页面。然后有一个多作业项目来协调子项目的子模块构建。由于所有子项目都是简单的 jar 构建,我想将大部分逻辑放在一个公共文件中,让我们在子项目的根目录下调用它 JenkinsfileForJars。所以回购结构是
- 子项目
- JenkinsfileForJars.groovy
- 子模块A
- 詹金斯文件
- 子模块B
- 詹金斯文件
我的 Jenkins 文件包含
def submoduleName = "submoduleA"
def pipeline
node {
pipeline = load("${env.WORKSPACE}/subproject/JenkinsfileForJars.groovy")
}
pipeline.build()
pipeline.results()
我的 JenkinsfileForJars 包含
def build() {
stage('Build') {
// Run the maven build
dir("subproject") {
sh "./gradlew ${submoduleName}:build"
}
}
}
def results() {
stage('Results') {
dir("subproject/${submoduleName}") {
junit 'build/test-results/TEST-*.xml'
archive 'build/libs/*.jar'
publishHTML([allowMissing: false, alwaysLinkToLastBuild: false, keepAll: false, reportDir: 'build/reports/cobertura/', reportFiles: 'frame-summary.html', reportName: 'Cobertura Report'])
publishHTML([allowMissing: false, alwaysLinkToLastBuild: false, keepAll: false, reportDir: 'build/reports/findbugs/', reportFiles: 'main.html', reportName: 'Fidbugs Report'])
publishHTML([allowMissing: false, alwaysLinkToLastBuild: false, keepAll: false, reportDir: 'build/reports/pmd/', reportFiles: 'main.html', reportName: 'PMD Report'])
step([$class: 'CheckStylePublisher', pattern: 'build/reports/checkstyle/main.xml', unstableTotalAll: '200', usePreviousBuildAsReference: true])
}
}
}
return this;
当我 运行 上面的 Jenkinsfile 时,我得到以下错误:
Running on master in /var/lib/jenkins/workspace/jobA
[Pipeline] {
[Pipeline] load
[Pipeline] { (/var/lib/jenkins/workspace/jobA/subproject/JenkinsfileForJars.groovy)
[Pipeline] }
[Pipeline] // load
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
java.lang.NullPointerException: Cannot invoke method build() on null object
据我所知,我正在按照 loading manual scripts and the example given 文档中显示的内容来加载脚本。我不明白为什么我的脚本在加载命令后为空。
如何让我的 Jenkinsfile 加载 JenkinsfileForJars.groovy?
可能存在两种可能的问题:
- 为什么把负载放在一个节点结构中。此导入不需要计算资源,因此您不需要它。
- 对构建的调用应该放在节点结构中。并且可能对结果的调用也应该在(相同的)节点结构内,以确保正确的结果被存档(如果您使用多个(从属)节点)。
(这可能应该是您问题下方的评论,但我没有足够的积分在此处添加评论。)
问题与上面评论中 Blake Mitchell 提到的 SCM 结帐有关。
由于您是从子模块加载 groovy 函数,如果您只想在主模块上保留裸仓库,则需要首先检查子模块,最好是在构建代理/从模块上。
def pipeline
node( 'myAgentLabel' ) {
stage ( 'checkout SCM' ) {
checkout([
$class: 'GitSCM'
,branches: scm.branches
,extensions: scm.extensions
+ [[ $class: 'SubmoduleOption', disableSubmodules: false, parentCredentials: true, recursiveSubmodules: true, reference: '', trackingSubmodules: false]]
,doGenerateSubmoduleConfigurations: false
,userRemoteConfigs: scm.userRemoteConfigs
])
pipeline = load( "${env.WORKSPACE}/path/to/submodule/myGroovyFunctions.grooovy" )
}
pipeline.build()
}
请注意,在结帐示例中,对 scm.* 属性的访问也需要由 Jenkins 中的管理员列入白名单(进程内脚本批准)
我的团队正在迁移到 Jenkins 2,我正在使用管道插件,以便我们的构建可以存在于我们的存储库中。因为在我们公司分配存储库有很多开销,所以我们有一个包含许多子项目和子模块的存储库。
我想要的 是每个子模块的 Junit/checkstyle/etc 报告的单独构建和报告,以及每个子模块的最后 "build and deploy" 步骤项目把它们放在一起。
我目前的计划 是为每个子模块创建单独的作业,以便它们获得自己的 junit/checkstyle/etc 报告页面。然后有一个多作业项目来协调子项目的子模块构建。由于所有子项目都是简单的 jar 构建,我想将大部分逻辑放在一个公共文件中,让我们在子项目的根目录下调用它 JenkinsfileForJars。所以回购结构是
- 子项目
- JenkinsfileForJars.groovy
- 子模块A
- 詹金斯文件
- 子模块B
- 詹金斯文件
我的 Jenkins 文件包含
def submoduleName = "submoduleA"
def pipeline
node {
pipeline = load("${env.WORKSPACE}/subproject/JenkinsfileForJars.groovy")
}
pipeline.build()
pipeline.results()
我的 JenkinsfileForJars 包含
def build() {
stage('Build') {
// Run the maven build
dir("subproject") {
sh "./gradlew ${submoduleName}:build"
}
}
}
def results() {
stage('Results') {
dir("subproject/${submoduleName}") {
junit 'build/test-results/TEST-*.xml'
archive 'build/libs/*.jar'
publishHTML([allowMissing: false, alwaysLinkToLastBuild: false, keepAll: false, reportDir: 'build/reports/cobertura/', reportFiles: 'frame-summary.html', reportName: 'Cobertura Report'])
publishHTML([allowMissing: false, alwaysLinkToLastBuild: false, keepAll: false, reportDir: 'build/reports/findbugs/', reportFiles: 'main.html', reportName: 'Fidbugs Report'])
publishHTML([allowMissing: false, alwaysLinkToLastBuild: false, keepAll: false, reportDir: 'build/reports/pmd/', reportFiles: 'main.html', reportName: 'PMD Report'])
step([$class: 'CheckStylePublisher', pattern: 'build/reports/checkstyle/main.xml', unstableTotalAll: '200', usePreviousBuildAsReference: true])
}
}
}
return this;
当我 运行 上面的 Jenkinsfile 时,我得到以下错误:
Running on master in /var/lib/jenkins/workspace/jobA
[Pipeline] {
[Pipeline] load
[Pipeline] { (/var/lib/jenkins/workspace/jobA/subproject/JenkinsfileForJars.groovy)
[Pipeline] }
[Pipeline] // load
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
java.lang.NullPointerException: Cannot invoke method build() on null object
据我所知,我正在按照 loading manual scripts and the example given 文档中显示的内容来加载脚本。我不明白为什么我的脚本在加载命令后为空。
如何让我的 Jenkinsfile 加载 JenkinsfileForJars.groovy?
可能存在两种可能的问题:
- 为什么把负载放在一个节点结构中。此导入不需要计算资源,因此您不需要它。
- 对构建的调用应该放在节点结构中。并且可能对结果的调用也应该在(相同的)节点结构内,以确保正确的结果被存档(如果您使用多个(从属)节点)。
(这可能应该是您问题下方的评论,但我没有足够的积分在此处添加评论。)
问题与上面评论中 Blake Mitchell 提到的 SCM 结帐有关。 由于您是从子模块加载 groovy 函数,如果您只想在主模块上保留裸仓库,则需要首先检查子模块,最好是在构建代理/从模块上。
def pipeline
node( 'myAgentLabel' ) {
stage ( 'checkout SCM' ) {
checkout([
$class: 'GitSCM'
,branches: scm.branches
,extensions: scm.extensions
+ [[ $class: 'SubmoduleOption', disableSubmodules: false, parentCredentials: true, recursiveSubmodules: true, reference: '', trackingSubmodules: false]]
,doGenerateSubmoduleConfigurations: false
,userRemoteConfigs: scm.userRemoteConfigs
])
pipeline = load( "${env.WORKSPACE}/path/to/submodule/myGroovyFunctions.grooovy" )
}
pipeline.build()
}
请注意,在结帐示例中,对 scm.* 属性的访问也需要由 Jenkins 中的管理员列入白名单(进程内脚本批准)