8

概要

現在、多数のプラットフォーム ビルドで構成されるパイプラインを構成しています。パイプラインの開始時に、ユーザーはビルドまたはスキップするプラットフォームを選択できます。

各プラットフォームの「ビルド」ステージが成功するか失敗するかに応じて、下流ステージのステップでそのプラットフォーム ビルドのステータスを確認し、実行するかどうかを決定できます。これにより、1 つ以上のプラットフォームが失敗した場合、パイプラインは他のプラットフォームを試行して完了することができます (ユーザーが確認した場合)。

進捗

現状では、私のパイプラインはこれを達成し、ユーザーがパイプラインの開始時にプラットフォームを含めたり除外したり、プラットフォームが失敗した場合にパイプラインがビルドを続行することを許可したりできます (ただし、パイプラインを失敗としてマークします)。これにより、ビルド ファイルのアーカイブ/gtest の発行などを下流の段階/ステップで行うことができます。これが私の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 でビルドに失敗したプラットフォームを簡単に確認できるように、並列ブランチを失敗としてマークできるようにしたいと考えています。

ブルー オーシャン UI で、try/catch ブロックで並列分岐が失敗した

また、ステージを失敗としてマークすると便利です。ブルー オーシャン UI にないときは、ステージ ビューにどのステージが失敗したかが表示されます (パイプラインがそのステージで終了した場合にのみ発生する場合を除きます)。もう本当に問題にはなりません。

Stage View 失敗したステージ (上) とそのまま (下)

質問

  • ブルー オーシャン UI に赤い十字が表示されるように、並列ブランチを失敗としてマークするにはどうすればよいですか? おそらく、次のような環境変数を使用してcurrentBuild.result

  • Stage View に表示されるように、ステージ全体で同様のことが可能ですか? (あまり重要ではありません)

4

2 に答える 2