概要
現在、多数のプラットフォーム ビルドで構成されるパイプラインを構成しています。パイプラインの開始時に、ユーザーはビルドまたはスキップするプラットフォームを選択できます。
各プラットフォームの「ビルド」ステージが成功するか失敗するかに応じて、下流ステージのステップでそのプラットフォーム ビルドのステータスを確認し、実行するかどうかを決定できます。これにより、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 に表示されるように、ステージ全体で同様のことが可能ですか? (あまり重要ではありません)