问题
I've recently moved to the Pipeline plugin in Jenkins. I've successfully used freestyle jobs before for my project, but now would like to test something new.
My project builds for Windows and Linux, in release and in debug mode, and uses a parameter, called device
, to configure some C preprocessor macros: globally #define
d frame_width
and frame_height
differ, depending on device
value.
Here is my Jenkinsfile:
def device_config(device) {
def device_config = "";
switch(device) {
case ~/^dev_[Aa]$/:
device_config="""-DGLOBAL_FRAME_WIDTH=640\
-DGLOBAL_FRAME_HEIGHT=480"""
break;
case ~/^dev_[Ss]$/:
device_config="""-DGLOBAL_FRAME_WIDTH=320\
-DGLOBAL_FRAME_HEIGHT=240"""
break;
default:
echo "warning: Unknown device \"$device\" using default config from CMake"
break;
}
return device_config
}
pipeline {
agent {
label 'project_device_linux'
}
environment {
device='dev_A'
}
stages {
stage('Configure') {
steps {
script {
dc = device_config("${env.device}")
}
dir('build') {
sh """cmake .. -DOpenCV_DIR="/usr/local" -DCMAKE_BUILD_TYPE="Debug"\
-DCHECK_MEMORY_LEAKS=ON\
-DENABLE_DEVELOPER_MODE=OFF\
-DUNIT_TEST_RAW_PATH=${env.tmpfs_path}\
$dc"""
}
}
}
stage('Build') {
steps {
dir('build') {
sh "make -j 16"
}
}
}
stage('Test'){
steps {
dir('build') {
sh "make check"
}
}
}
}
}
Now I'd like to repeat all those stages for another device, dev_s
, for "Release" build type, and for Windows also. There are also some minor differences, depending on parameters: for example, "Release" builds should have included publishing of compiled binaries and excluded check for memory leaks. Also, if I've got it correctly, Windows slave does not understand sh
build step and uses bat
for that purpose.
How can I do it without copy-pasteing of code and in parallel on 2 nodes, one running Linux, and another one, running Windows?
Obviously, there should be several nested loops, but it is not clear for me, what to emit on each loop iteration.
Forgot to mention, I'd like to run everything from the Gitlab trigger on Push events.
UPDATE
Currently I end up with something like the following
#!/usr/bin/env groovy
def device_config(device) {
def result = "";
switch(device) {
case ~/^dev_[Aa]$/:
result ="""-DFRAME_WIDTH=640\
-DFRAME_HEIGHT=480"""
break;
case ~/^dev_[Ss]$/:
result ="""-DFRAME_WIDTH=320\
-DFRAME_HEIGHT=240"""
break;
default:
echo "warning: Unknown device \"$device\" using default config from CMake"
break;
}
return result;
}
oses = ['linux', 'windows']
devices = ['dev_A', 'dev_S']
build_types = ['Debug', 'Release']
node {
stage('Checkout') {
checkout_steps = [:]
for (os in oses) {
for (device in devices) {
for (build_type in build_types) {
def label = "co-${os}-${device}-${build_type}"
def node_label = "project && ${os}"
checkout_steps[label] = {
node(node_label) {
checkout scm
}
}
}
}
}
parallel checkout_steps
}
stage('Configure') {
config_steps = [:]
for (os in oses) {
for (device in devices) {
for (build_type in build_types) {
def label = "configure-${os}-${device}-${build_type}"
def node_label = "project && ${os}"
def dc = device_config("${device}")
cmake_parameters = """-DCMAKE_BUILD_TYPE="${build_type}"\
-DCHECK_MEMORY_LEAKS=ON\
$dc"""
if(os == 'linux') {
config_steps[label] = {
node(node_label) {
dir('build') {
sh """cmake .. -DOpenCV_DIR=/usr/local ${cmake_parameters}"""
}
}
}
} else {
config_steps[label] = {
node(node_label) {
dir('build') {
bat """cmake .. -G"Ninja" -DOpenCV_DIR=G:/opencv_2_4_11/build ${cmake_parameters}"""
}
}
}
}
}
}
}
parallel config_steps
}
}
What I don't like is that some node-specific settings, like paths, are set in the Jenkinsfile. Hope to figure out, how to set them in node settings in Jenkins.
I also see in logs, that only Release
+ dev_S
configuration is applied - there is some kind of closure and late binding. Search reveals that it is a known and already fixed issue - I have to plan to figure out how to deal with closures.
来源:https://stackoverflow.com/questions/47814891/implement-matrix-config-in-jenkins-pipeline