Advertisement
jimklimov

Jenkinsfile-rescan-MBPs

Mar 16th, 2018 (edited)
596
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Groovy 5.17 KB | None | 0 0
  1. #!/usr/bin/env groovy
  2.  
  3. // Jenkinsfile-rescan-MBPs
  4. // (C) 2018 by Jim Klimov
  5. // This Jenkinsfile makes-believe it is a Declarative pipeline for
  6. // the sake of commonality of our pipeline scripts (build args,
  7. // various options and stuff), but in fact this is a scripted
  8. // pipeline most of the way.
  9. // Its job is to find MultiBranchPipeline items spawned inside an
  10. // organization folder and issue a rescan request (build operation),
  11. // so we can detect new or closed PRs and branches quickly (due to
  12. // JENKINS-49526 MBPs are otherwise polled once a day, hardcoded).
  13.  
  14. import jenkins.model.*
  15. import hudson.model.*
  16. import hudson.util.PersistedList
  17. import jenkins.branch.*
  18.  
  19. // This shared array variable will be populated with the list of parallel stages
  20. def scan_stages = [:]
  21.  
  22. // WARNING: Nowadays generated clauses with pipeline steps must be CPS!
  23. //@NonCPS
  24. def parallelSubtasks(String verbose) {
  25.     def subbuilds = [:]
  26.     def jobs = Jenkins.instance.getAllItems()
  27.  
  28.     jobs.each { j ->
  29.         if (j instanceof com.cloudbees.hudson.plugins.folder.Folder) {
  30.             if (verbose.equals("true")) {
  31.                 echo 'Ignoring JOB which is a com.cloudbees.hudson.plugins.folder.Folder : ' + j.fullName
  32.             }
  33.             return
  34.         }
  35.         if (j instanceof jenkins.branch.OrganizationFolder) {
  36.             if (verbose.equals("true")) {
  37.                 echo 'Ignoring JOB which is a jenkins.branch.OrganizationFolder : ' + j.fullName
  38.             }
  39.             return
  40.         }
  41.         if (! (j instanceof org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject) ) {
  42.             if (verbose.equals("true")) {
  43.                 echo 'Ignoring JOB which is not an MBP: ' + j.fullName
  44.             }
  45.             return;
  46.         }
  47.         if ( ! j.fullName.contains("/") ) {
  48.             echo 'Ignoring MBP JOB which is not under a (organization) folder, so has and hopefully honours a schedule of its own: ' + j.fullName
  49.             return;
  50.         }
  51.         // TODO: Determine that MBP's schedule and only fire below if it is "once a day" (hardcoded)?
  52.  
  53.         subbuilds["${j.fullName}"] = {
  54.             stage("Scan ${j.fullName}") {
  55.                 // Per non-declarative pipeline syntax, no steps{} here
  56.                     echo "Rescanning '${j.fullName}' ..."
  57.                     // Jenkins refuses to "wait" for this type of job...
  58.                     // TODO: Sleep-poll the results (and logs?) of the
  59.                     // spawned child jobs.
  60.                     try {
  61.                         def bbb = build job: "${j.fullName}", quietPeriod: 0, wait: false, propagate: true
  62.                     } catch (Exception e) {
  63.                         // e.g. a disabled repo, like one where a Jenkinsfile
  64.                         // script existed earlier but was removed
  65.                         echo "Failed to trigger scan for ${j.fullName}, skipped"
  66.                     }
  67.             }
  68.         } // end of def subbuilds[j.fullName]
  69.  
  70.     } // jobs.each() clause
  71.  
  72.     return subbuilds
  73. }
  74.  
  75.  
  76. // A declarative pipeline shiny wrapper (we need it
  77. // for common ways of autosetup and params, mostly)
  78. pipeline {
  79.     options {
  80. /*
  81.         description("This job runs regularly to find and rescan multibranch pipeline jobs (e.g. generated via organization folders) to add monitoring of new PRs (and disable monitoring of merged PRs) in a timely fashion.")
  82. */
  83.         disableConcurrentBuilds()
  84.         disableResume()
  85.         durabilityHint('PERFORMANCE_OPTIMIZED')
  86.         buildDiscarder(logRotator(numToKeepStr: '10'))
  87.         skipDefaultCheckout true
  88.     }
  89.     triggers {
  90.         cron('H/15 * * * *')
  91.     }
  92.     agent {label "master||master-real||master-worker"}
  93.     parameters {
  94.         booleanParam (
  95.             defaultValue: false,
  96.             description: 'Print found and skipped items?',
  97.             name: 'JOBLIST_VERBOSE'
  98.         )
  99.     }
  100.     stages {
  101.         stage('Single-exec milestone') {
  102.             steps {
  103.                 milestone 1
  104.             } // steps clause
  105.         }
  106.     }
  107. }
  108.  
  109. // Non-declarative pipeline payload.
  110. // This code below does not work inside a pipeline{} stage{}
  111. // clause nor in the post{} clause - not even with the added
  112. // try/catches for exceptions all around.
  113. // Curiously, when this pipeline job is built by hand
  114. // or triggered by timer, it fails with lots of CPS and
  115. // marshalling exception messages in the end. Replaying
  116. // the same groovy script with no changes just works.
  117. try {
  118.     echo "DISCOVERING JOBS..."
  119.     scan_stages = parallelSubtasks( "${params.JOBLIST_VERBOSE}" )
  120. } catch (java.io.NotSerializableException e) {
  121.     echo "Ignoring NotSerializableException during parallelSubtasks()"
  122. } catch (Exception e) {
  123.     echo "Failed to find jobs or set up parallel scans"
  124.     currentBuild.result = 'FAILED'
  125.     manager.buildAborted()
  126. }
  127.  
  128. try {
  129.     echo "SCHEDULING RESCANS..."
  130.     parallel scan_stages
  131.     echo "SCHEDULING OF RESCANS COMPLETED"
  132. } catch (java.io.NotSerializableException e) {
  133.     echo "Ignoring NotSerializableException during parallelized work"
  134. } catch (Exception e) {
  135.     echo "Failed to trigger parallel scans"
  136.     currentBuild.result = 'FAILED'
  137.     manager.buildAborted()
  138. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement