如何在舞台视图和Blue Ocean UI中设置Jenkins阶段或管道并行分支状态(不稳定,失败等)?

时间:2017-01-11 10:36:08

标签: 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'
            }
        }
    )
}

我的全球职能:

// 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
}

问题

虽然一般功能有效,但除了将管道标记为失败之外,UI响应不会。我希望能够将并行分支标记为失败,以便在Blue Ocean UI中,很容易看出哪个平台无法构建。

Blue Ocean UI with failed parallel branch in try/catch block

将舞台标记为失败也是有用的,因此当不在Blue Ocean UI中时,舞台视图会显示哪一个失败(除非只有在该阶段终止管道时才会发生这种情况)尽管一旦蓝海离开Beta这不再是一个问题了。

Stage View failed stage (Above) and as is (Below)

问题

  • 如何将并行分支标记为失败,以便在蓝海UI中显示红叉?也许使用像currentBuild.result

  • 这样的环境变量
  • 整个舞台是否有类似的事情可以在舞台视图中显示出来? (不太重要)

2 个答案:

答案 0 :(得分:4)

可以通过将并行步骤和阶段步骤包装在try块中来实现UI响应,将错误从并行分支内的try / catch块抛出到stage块。不像设置属性那样干净,但对Blue Ocean和Stage View都有正确的UI响应。

switch (l, r) {
case let (l as A, r as A):
    print("(\(l), \(r)) is (A, A)")
default:
    print("failed to match tuple")
}

答案 1 :(得分:1)

这在蓝海对我有效:

stage("Global Stage") {
  def parallelStages = [failfast: false]
  parallelStages["Branch 1"] = {
     //Code for branch 1
  }
  parallelStages["Branch 2"] = {
     //Code for branch 2
  }
  catchError(buildResult: 'SUCCESS', message: 'Branch Failed', stageResult: 'UNSTABLE')
  { parallel parallelStages }
}

这可以正确地将失败的并行分支标记为Blue Ocean中的UNSTABLE,不影响其他阶段的结果,并将整个构建标记为SUCCESS