ink*_*ris 7 jenkins jenkins-pipeline jenkins-blueocean
我目前正在配置一个由许多平台构建组成的管道.在管道的开头,用户可以选择要构建或跳过的平台.
根据每个平台的"构建"阶段是通过还是失败,下游阶段的步骤可以检查该平台构建的状态并确定是否运行.如果一个或多个平台发生故障,这允许管道尝试并完成其他平台(如果用户确认这样做).
目前,我的管道实现了这一点,允许用户在管道开始时包含/排除平台,并授权管道在平台发生故障时继续构建(但将管道标记为故障).这允许存档构建文件/发布gtests等,这可以在下游阶段/步骤中完成.这是我的Jenkinsfile:
// Specify whether or not to build platform by default
def buildDefinitions = [ 'windows' : true , 'macos' : true , 'ubuntu' : true ]
// Keep track of builds that fail
def failedBuilds = [:]
stage('Build Customisation') {
try {
// Wait limited amount of time for user input
timeout(time: 30, unit: 'SECONDS') {
// Update the build definitions based on user input
buildDefinitions = input(
message: 'Toggle which builds to run (Abort will use default)',
// Use custom global function to generate boolean input parameters based on a map
// Sets default value to value in input map
parameters: generateInputBoolParams( buildDefinitions )
)
}
// Continue pipeline if user input not provided within time limit
} catch ( error ) {
echo 'Using default pipeline configuration...'
}
// Check that at least one build platform is selected
if ( !mapContainsTrue( buildDefinitions ) ) {
error 'No builds selected, aborting pipeline'
}
}
stage('Conditional Build') {
parallel (
'Windows' : {
// Prevent a build failure from terminating the pipeline after this stage
try {
// Check if windows build is set to run
if ( buildDefinitions['windows'] ) {
node('windows') {
checkout(scm)
bat 'build.bat default-windows'
}
} else {
echo 'Build was disabled by user'
}
// Catch an error in the build
} catch ( error ) {
// Make note that the build failed
failedBuilds['windows'] = true
// Set the pipeline status as failure
currentBuild.result = 'FAILURE'
}
},
'MacOS' : {
try {
if ( buildDefinitions['macos'] ) {
node('macos') {
checkout(scm)
sh './build.sh default-macos'
}
} else {
echo 'Build was disabled by user'
}
} catch ( error ) {
failedBuilds['macos'] = true
currentBuild.result = 'FAILURE'
}
},
'Ubuntu' : {
try {
if ( buildDefinitions['ubuntu'] ) {
node('ubuntu') {
checkout(scm)
sh './build.sh default-ubuntu'
}
} else {
echo 'Build was disabled by user'
}
error 'test error'
} catch ( error ) {
failedBuilds['ubuntu'] = true
currentBuild.result = 'FAILURE'
}
}
)
// Check if any builds have been marked as failed
if ( mapContainsTrue( failedBuilds ) ) {
// Remove failed builds from the original map of enabled builds
def updatedBuildDefinitions = subtractMap( buildDefinitions, failedBuilds )
// Check that there are builds left to run
if ( mapContainsTrue( updatedBuildDefinitions ) ) {
// Update the original build map
buildDefinitions = updatedBuildDefinitions
// Lists the failed builds and asks whether to continue or abort the pipeline
timeout(time: 30, unit: 'SECONDS') {
input(
message: 'Builds failed ' + getKeyset( failedBuilds ) + ', do you want to continue the pipeline and skip failed builds?'
)
}
} else {
// Throw an error to terminate the pipeline if no builds are left to run
error 'No builds left to run'
}
}
}
stage('Conditional Downstream') {
parallel (
'Windows' : {
if ( buildDefinitions['windows'] ) {
echo 'You chose to run the windows build!'
} else {
echo 'The windows build was skipped'
}
},
'MacOS' : {
if ( buildDefinitions['macos'] ) {
echo 'You chose to run the macos build!'
} else {
echo 'The macos build was skipped'
}
},
'Ubuntu' : {
if ( buildDefinitions['ubuntu'] ) {
echo 'You chose to run the ubuntu build!'
} else {
echo 'The ubuntu build was skipped'
}
}
)
}
Run Code Online (Sandbox Code Playgroud)
我的全球职能:
// subtractMap.groovy
def call ( map1, map2 ) {
return map1 - map2
}
// mapContainsTrue.groovy
boolean call ( array ) {
for ( entry in array ) {
if ( entry.value == true ) {
isBuildConfigValid = true
return true
} else {
return false
}
}
}
// getKeyset.groovy
def call ( map ) {
return map.keySet() as String[]
}
// generateInputBoolParams.groovy
def call ( array ) {
def parameterList = []
for ( item in array ) {
parameterList.add( booleanParam(defaultValue: item.value, name: item.key) )
}
return parameterList
}
Run Code Online (Sandbox Code Playgroud)
虽然一般功能有效,但UI响应不会将管道标记为失败.我希望能够将并行分支标记为失败,以便在Blue Ocean UI中,很容易看出哪个平台无法构建.
将阶段标记为失败也是有用的,因此当不在Blue Ocean UI中时,阶段视图显示哪一个失败(除非只有在该阶段终止管道时才会发生这种情况)尽管一旦蓝海离开Beta,这将不会真的不再是问题了.
如何将并行分支标记为失败,以便它显示在带有红叉的Blue Ocean UI中?也许与环境变量一样currentBuild.result
整个舞台是否有类似的事情可以在舞台视图中显示出来?(不太重要)
通过将并行步骤和阶段步骤都包装在try块中,将错误从并行分支内的try / catch块抛出到阶段块,可以实现UI响应。不像设置属性那样干净,但是对于Blue Ocean和Stage View确实具有正确的UI响应。
try {
stage('example') {
try {
parallel (
'A' : {
try {
// Example...
}
catch (error) {
// Mark branch as failed somewhere
throw error
}
},
'B' : {
try {
// Example...
}
catch (error) {
// Mark branch as failed somewhere
throw error
}
}
)
}
catch (error) {
throw (error)
}
finally {
// Parallel branch A failed, do you want to continue? etc...
}
}
}
catch (error) {
println (error)
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
11069 次 |
最近记录: |