Changes in Jenkinsfile [eda8175:2aa2056f]
- File:
-
- 1 edited
-
Jenkinsfile (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
Jenkinsfile
reda8175 r2aa2056f 6 6 node ('master'){ 7 7 8 // Globals 9 BuildDir = pwd tmp: true 10 SrcDir = pwd tmp: false 11 Settings = null 12 StageName = '' 13 14 // Local variables 8 boolean bIsSandbox = env.BRANCH_NAME == "jenkins-sandbox" 15 9 def err = null 16 10 def log_needed = false 11 12 stage_name = '' 13 14 compiler = null 15 arch_name = '' 16 architecture = '' 17 18 do_alltests = false 19 do_benchmark = false 20 do_doc = false 21 do_publish = false 22 do_sendemail = true 23 24 builddir = pwd tmp: true 25 srcdir = pwd tmp: false 17 26 18 27 currentBuild.result = "SUCCESS" … … 24 33 notify_server(0) 25 34 26 Settings =prepare_build()35 prepare_build() 27 36 28 37 clean() … … 52 61 err = caughtError 53 62 54 echo err.toString()55 56 63 //An error has occured, the build log is relevent 57 64 log_needed = true 58 65 59 66 //Store the result of the build log 60 currentBuild.result = "${ StageName} FAILURE".trim()67 currentBuild.result = "${stage_name} FAILURE".trim() 61 68 } 62 69 63 70 finally { 64 71 //Send email with final results if this is not a full build 65 if( Settings && !Settings.Silent ) { 66 email(log_needed, Settings.IsSandbox) 72 if( do_sendemail ) { 73 echo 'Notifying users of result' 74 email(currentBuild.result, log_needed, bIsSandbox) 67 75 } 68 76 … … 77 85 78 86 //=========================================================================================================== 79 // Main compilation routines80 //===========================================================================================================81 def clean() {82 build_stage('Cleanup') {83 // clean the build by wipping the build directory84 dir(BuildDir) {85 deleteDir()86 }87 }88 }89 90 //Compilation script is done here but environnement set-up and error handling is done in main loop91 def checkout() {92 build_stage('Checkout') {93 //checkout the source code and clean the repo94 final scmVars = checkout scm95 Settings.GitNewRef = scmVars.GIT_COMMIT96 Settings.GitOldRef = scmVars.GIT_PREVIOUS_COMMIT97 98 echo GitLogMessage()99 }100 }101 102 def build() {103 build_stage('Build') {104 // Build outside of the src tree to ease cleaning105 dir (BuildDir) {106 //Configure the conpilation (Output is not relevant)107 //Use the current directory as the installation target so nothing escapes the sandbox108 //Also specify the compiler by hand109 targets=""110 if( Settings.RunAllTests ) {111 targets="--with-target-hosts='host:debug,host:nodebug'"112 } else {113 targets="--with-target-hosts='host:debug'"114 }115 116 sh "${SrcDir}/configure CXX=${Settings.Compiler.cpp_cc} ${Settings.Architecture.flags} ${targets} --with-backend-compiler=${Settings.Compiler.cfa_cc} --quiet"117 118 //Compile the project119 sh 'make -j 8 --no-print-directory'120 }121 }122 }123 124 def test() {125 build_stage('Test') {126 127 dir (BuildDir) {128 //Run the tests from the tests directory129 if ( Settings.RunAllTests ) {130 sh 'make --no-print-directory -C tests all-tests debug=yes'131 sh 'make --no-print-directory -C tests all-tests debug=no '132 }133 else {134 sh 'make --no-print-directory -C tests'135 }136 }137 }138 }139 140 def benchmark() {141 build_stage('Benchmark') {142 143 if( !Settings.RunBenchmark ) return144 145 dir (BuildDir) {146 //Append bench results147 sh "make --no-print-directory -C benchmark jenkins githash=${Settings.GitNewRef} arch=${Settings.Architecture} | tee ${SrcDir}/bench.json"148 }149 }150 }151 152 def build_doc() {153 build_stage('Documentation') {154 155 if( !Settings.BuildDocumentation ) return156 157 dir ('doc/user') {158 make_doc()159 }160 161 dir ('doc/refrat') {162 make_doc()163 }164 }165 }166 167 def publish() {168 build_stage('Publish') {169 170 if( !Settings.Publish ) return171 172 //Then publish the results173 sh 'curl --silent --show-error -H \'Content-Type: application/json\' --data @bench.json https://cforall.uwaterloo.ca:8082/jenkins/publish > /dev/null || true'174 }175 }176 177 //===========================================================================================================178 //Routine responsible of sending the email notification once the build is completed179 //===========================================================================================================180 def GitLogMessage() {181 if (!Settings || !Settings.GitOldRef || !Settings.GitNewRef) return "\nERROR retrieveing git information!\n"182 183 sh "${SrcDir}/tools/PrettyGitLogs.sh ${BuildDir} ${Settings.GitOldRef} ${Settings.GitNewRef}"184 185 def gitUpdate = readFile("${BuildDir}/GIT_UPDATE")186 def gitLog = readFile("${BuildDir}/GIT_LOG")187 def gitDiff = readFile("${BuildDir}/GIT_DIFF")188 189 return """190 The branch ${env.BRANCH_NAME} has been updated.191 ${gitUpdate}192 193 Check console output at ${env.BUILD_URL} to view the results.194 195 - Status --------------------------------------------------------------196 197 BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result}198 199 - Log -----------------------------------------------------------------200 ${gitLog}201 -----------------------------------------------------------------------202 Summary of changes:203 ${gitDiff}204 """205 }206 207 //Standard build email notification208 def email(boolean log, boolean bIsSandbox) {209 //Since tokenizer doesn't work, figure stuff out from the environnement variables and command line210 //Configurations for email format211 echo 'Notifying users of result'212 213 def project_name = (env.JOB_NAME =~ /(.+)\/.+/)[0][1].toLowerCase()214 def email_subject = "[${project_name} git][BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result}] - branch ${env.BRANCH_NAME}"215 def email_body = """This is an automated email from the Jenkins build machine. It was216 generated because of a git hooks/post-receive script following217 a ref change which was pushed to the Cforall repository.218 """ + GitLogMessage()219 220 def email_to = "cforall@lists.uwaterloo.ca"221 222 if( Settings && !Settings.IsSandbox ) {223 //send email notification224 emailext body: email_body, subject: email_subject, to: email_to, attachLog: log225 } else {226 echo "Would send email to: ${email_to}"227 echo "With title: ${email_subject}"228 echo "Content: \n${email_body}"229 }230 }231 232 //===========================================================================================================233 87 // Helper classes/variables/routines 234 88 //=========================================================================================================== 235 //Description of a compiler (Must be serializable since pipelines are persistent) 236 class CC_Desc implements Serializable { 237 public String cc_name 238 public String cpp_cc 239 public String cfa_cc 240 241 CC_Desc(String cc_name, String cpp_cc, String cfa_cc) { 242 this.cc_name = cc_name 243 this.cpp_cc = cpp_cc 244 this.cfa_cc = cfa_cc 245 } 246 } 247 248 //Description of an architecture (Must be serializable since pipelines are persistent) 249 class Arch_Desc implements Serializable { 250 public String name 251 public String flags 252 253 Arch_Desc(String name, String flags) { 254 this.name = name 255 this.flags = flags 256 } 257 } 258 259 class BuildSettings implements Serializable { 260 public final CC_Desc Compiler 261 public final Arch_Desc Architecture 262 public final Boolean RunAllTests 263 public final Boolean RunBenchmark 264 public final Boolean BuildDocumentation 265 public final Boolean Publish 266 public final Boolean Silent 267 public final Boolean IsSandbox 268 public final String DescLong 269 public final String DescShort 270 271 public String GitNewRef 272 public String GitOldRef 273 274 BuildSettings(java.util.Collections$UnmodifiableMap param, String branch) { 275 switch( param.Compiler ) { 276 case 'gcc-6': 277 this.Compiler = new CC_Desc('gcc-6', 'g++-6', 'gcc-6') 278 break 279 case 'gcc-5': 280 this.Compiler = new CC_Desc('gcc-5', 'g++-5', 'gcc-5') 281 break 282 case 'gcc-4.9': 283 this.Compiler = new CC_Desc('gcc-4.9', 'g++-4.9', 'gcc-4.9') 284 break 285 case 'clang': 286 this.Compiler = new CC_Desc('clang', 'clang++', 'gcc-6') 287 break 288 default : 289 error "Unhandled compiler : ${cc}" 290 } 291 292 switch( param.Architecture ) { 293 case 'x64': 294 this.Architecture = new Arch_Desc('x64', '--host=x86_64') 295 break 296 case 'x86': 297 this.Architecture = new Arch_Desc('x86', '--host=i386') 298 break 299 default : 300 error "Unhandled architecture : ${arch}" 301 } 302 303 this.RunAllTests = param.RunAllTests 304 this.RunBenchmark = param.RunBenchmark 305 this.BuildDocumentation = param.BuildDocumentation 306 this.Publish = param.Publish 307 this.Silent = param.Silent 308 this.IsSandbox = (branch == "jenkins-sandbox") 309 310 def full = param.RunAllTests ? " (Full)" : "" 311 this.DescShort = "${ this.Compiler.cc_name }:${ this.Architecture.name }${full}" 312 313 this.DescLong = """Compiler : ${ this.Compiler.cc_name } (${ this.Compiler.cpp_cc }/${ this.Compiler.cfa_cc }) 314 Architecture : ${ this.Architecture.name } 315 Arc Flags : ${ this.Architecture.flags } 316 Run All Tests : ${ this.RunAllTests.toString() } 317 Run Benchmark : ${ this.RunBenchmark.toString() } 318 Build Documentation : ${ this.BuildDocumentation.toString() } 319 Publish : ${ this.Publish.toString() } 320 Silent : ${ this.Silent.toString() } 321 """ 322 323 this.GitNewRef = '' 324 this.GitOldRef = '' 325 } 89 //Helper routine to collect information about the git history 90 def collect_git_info() { 91 92 checkout scm 93 94 //create the temporary output directory in case it doesn't already exist 95 def out_dir = pwd tmp: true 96 sh "mkdir -p ${out_dir}" 97 98 //parse git logs to find what changed 99 gitRefName = env.BRANCH_NAME 100 sh "git reflog > ${out_dir}/GIT_COMMIT" 101 git_reflog = readFile("${out_dir}/GIT_COMMIT") 102 gitRefOldValue = (git_reflog =~ /moving from (.+) to (.+)/)[0][1] 103 gitRefNewValue = (git_reflog =~ /moving from (.+) to (.+)/)[0][2] 326 104 } 327 105 328 106 def prepare_build() { 329 // prepare the properties330 107 properties ([ \ 331 108 [$class: 'ParametersDefinitionProperty', \ … … 371 148 ]]) 372 149 373 final settings = new BuildSettings(params, env.BRANCH_NAME) 374 375 currentBuild.description = settings.DescShort 376 echo settings.DescLong 377 378 return settings 150 compiler = compiler_from_params( params.Compiler ) 151 arch_name = params.Architecture 152 architecture = architecture_from_params( arch_name ) 153 154 do_alltests = (params.RunAllTests == 'true') 155 do_benchmark = (params.RunBenchmark == 'true') 156 do_doc = (params.BuildDocumentation == 'true') 157 do_publish = (params.Publish == 'true') 158 do_sendemail = ! (params.Silent == 'true') 159 160 collect_git_info() 161 162 def full = do_alltests ? " (Full)" : "" 163 currentBuild.description = "${compiler.cc_name}:${arch_name}${full}" 164 165 echo """Compiler : ${ compiler.cc_name } (${ compiler.cpp_cc }/${ compiler.cfa_cc }) 166 Architecture : ${ arch_name } 167 Arc Flags : ${ architecture } 168 Run All Tests : ${ params.RunAllTests.toString() } 169 Run Benchmark : ${ params.RunBenchmark.toString() } 170 Build Documentation : ${ params.BuildDocumentation.toString() } 171 Publish : ${ params.Publish.toString() } 172 Silent : ${ params.Silent.toString() } 173 """ 379 174 } 380 175 381 176 def build_stage(String name, Closure block ) { 382 StageName = name 383 echo " -------- ${StageName} -------- " 177 stage_name = name 384 178 stage(name, block) 385 179 } … … 404 198 } 405 199 } 200 201 //Description of a compiler (Must be serializable since pipelines are persistent) 202 class CC_Desc implements Serializable { 203 public String cc_name 204 public String cpp_cc 205 public String cfa_cc 206 207 CC_Desc(String cc_name, String cpp_cc, String cfa_cc) { 208 this.cc_name = cc_name 209 this.cpp_cc = cpp_cc 210 this.cfa_cc = cfa_cc 211 } 212 } 213 214 def compiler_from_params(cc) { 215 switch( cc ) { 216 case 'gcc-6': 217 return new CC_Desc('gcc-6', 'g++-6', 'gcc-6') 218 break 219 case 'gcc-5': 220 return new CC_Desc('gcc-5', 'g++-5', 'gcc-5') 221 break 222 case 'gcc-4.9': 223 return new CC_Desc('gcc-4.9', 'g++-4.9', 'gcc-4.9') 224 break 225 case 'clang': 226 return new CC_Desc('clang', 'clang++', 'gcc-6') 227 break 228 default : 229 error "Unhandled compiler : ${cc}" 230 } 231 } 232 233 def architecture_from_params( arch ) { 234 switch( arch ) { 235 case 'x64': 236 return '--host=x86_64' 237 break 238 case 'x86': 239 return '--host=i386' 240 break 241 default : 242 error "Unhandled architecture : ${arch}" 243 } 244 } 245 246 //=========================================================================================================== 247 // Main compilation routines 248 //=========================================================================================================== 249 def clean() { 250 build_stage('Cleanup') { 251 // clean the build by wipping the build directory 252 dir(builddir) { 253 deleteDir() 254 } 255 256 //Clean all temporary files to make sure no artifacts of the previous build remain 257 sh 'git clean -fdqx' 258 259 //Reset the git repo so no local changes persist 260 sh 'git reset --hard' 261 } 262 } 263 264 //Compilation script is done here but environnement set-up and error handling is done in main loop 265 def checkout() { 266 build_stage('Checkout') { 267 //checkout the source code and clean the repo 268 checkout scm 269 } 270 } 271 272 def build() { 273 build_stage('Build') { 274 // Build outside of the src tree to ease cleaning 275 dir (builddir) { 276 //Configure the conpilation (Output is not relevant) 277 //Use the current directory as the installation target so nothing escapes the sandbox 278 //Also specify the compiler by hand 279 targets="" 280 if(do_alltests) { 281 targets="--with-target-hosts='host:debug,host:nodebug'" 282 } else { 283 targets="--with-target-hosts='host:debug'" 284 } 285 286 sh "${srcdir}/configure CXX=${compiler.cpp_cc} ${architecture} ${targets} --with-backend-compiler=${compiler.cfa_cc} --quiet" 287 288 //Compile the project 289 sh 'make -j 8 --no-print-directory' 290 } 291 } 292 } 293 294 def test() { 295 build_stage('Test') { 296 297 dir (builddir) { 298 //Run the tests from the tests directory 299 if ( do_alltests ) { 300 sh 'make --no-print-directory -C tests all-tests debug=yes' 301 sh 'make --no-print-directory -C tests all-tests debug=no ' 302 } 303 else { 304 sh 'make --no-print-directory -C tests' 305 } 306 } 307 } 308 } 309 310 def benchmark() { 311 build_stage('Benchmark') { 312 313 if( !do_benchmark ) return 314 315 dir (builddir) { 316 //Append bench results 317 sh "make --no-print-directory -C benchmark jenkins githash=${gitRefNewValue} arch=${arch_name} | tee ${srcdir}/bench.json" 318 } 319 } 320 } 321 322 def build_doc() { 323 build_stage('Documentation') { 324 325 if( !do_doc ) return 326 327 dir ('doc/user') { 328 make_doc() 329 } 330 331 dir ('doc/refrat') { 332 make_doc() 333 } 334 } 335 } 336 337 def publish() { 338 build_stage('Publish') { 339 340 if( !do_publish ) return 341 342 //Then publish the results 343 sh 'curl --silent --show-error -H \'Content-Type: application/json\' --data @bench.json https://cforall.uwaterloo.ca:8082/jenkins/publish > /dev/null || true' 344 } 345 } 346 347 //=========================================================================================================== 348 //Routine responsible of sending the email notification once the build is completed 349 //=========================================================================================================== 350 def gitBranchUpdate(String gitRefOldValue, String gitRefNewValue) { 351 def update = "" 352 sh "git rev-list ${gitRefOldValue}..${gitRefNewValue} > GIT_LOG"; 353 readFile('GIT_LOG').eachLine { rev -> 354 sh "git cat-file -t ${rev} > GIT_TYPE" 355 def type = readFile('GIT_TYPE') 356 357 update += " via ${rev} (${type})\n" 358 } 359 def rev = gitRefOldValue 360 sh "git cat-file -t ${rev} > GIT_TYPE" 361 def type = readFile('GIT_TYPE') 362 363 update += " from ${rev} (${type})\n" 364 return update 365 366 def output=readFile('result').trim() 367 echo "output=$output"; 368 } 369 370 //Standard build email notification 371 def email(String status, boolean log, boolean bIsSandbox) { 372 //Since tokenizer doesn't work, figure stuff out from the environnement variables and command line 373 //Configurations for email format 374 def project_name = (env.JOB_NAME =~ /(.+)\/.+/)[0][1].toLowerCase() 375 376 def gitLog = 'Error retrieving git logs' 377 def gitDiff = 'Error retrieving git diff' 378 def gitUpdate = 'Error retrieving update' 379 380 try { 381 gitUpdate = gitBranchUpdate(gitRefOldValue, gitRefNewValue) 382 383 sh "git rev-list --format=short ${gitRefOldValue}...${gitRefNewValue} > GIT_LOG" 384 gitLog = readFile('GIT_LOG') 385 386 sh "git diff --stat ${gitRefNewValue} ${gitRefOldValue} > GIT_DIFF" 387 gitDiff = readFile('GIT_DIFF') 388 } 389 catch (Exception error) { 390 echo error.toString() 391 echo error.getMessage() 392 } 393 394 def email_subject = "[${project_name} git][BUILD# ${env.BUILD_NUMBER} - ${status}] - branch ${env.BRANCH_NAME}" 395 def email_body = """This is an automated email from the Jenkins build machine. It was 396 generated because of a git hooks/post-receive script following 397 a ref change was pushed to the repository containing 398 the project "UNNAMED PROJECT". 399 400 The branch ${env.BRANCH_NAME} has been updated. 401 ${gitUpdate} 402 403 Check console output at ${env.BUILD_URL} to view the results. 404 405 - Status -------------------------------------------------------------- 406 407 BUILD# ${env.BUILD_NUMBER} - ${status} 408 409 - Log ----------------------------------------------------------------- 410 ${gitLog} 411 ----------------------------------------------------------------------- 412 Summary of changes: 413 ${gitDiff} 414 """ 415 416 def email_to = "cforall@lists.uwaterloo.ca" 417 418 if( !bIsSandbox ) { 419 //send email notification 420 emailext body: email_body, subject: email_subject, to: email_to, attachLog: log 421 } else { 422 echo "Would send email to: ${email_to}" 423 echo "With title: ${email_subject}" 424 echo "Content: \n${email_body}" 425 } 426 }
Note:
See TracChangeset
for help on using the changeset viewer.