Search code examples
jenkinsjenkins-declarative-pipeline

Running non-matrix stages in parallel to a matrix in Jenkins declarative-pipeline


I'm converting our enterprise build so that it uses the 'matrix' directive (https://www.jenkins.io/blog/2019/11/22/welcome-to-the-matrix/), but am having trouble optimizing it. In the pre-matrix world, we have a build step (produces jars), followed by a parallel 'package' step (produces linux and windows distros), essentially followed by a 'system test' phase (execute the windows and linux distros on various JVMs), and we do some 'code quality' inspection in parallel to the package-and-system-test phases.

Much of this seems to lend itself to using 'matrix'. So, the 'packaging' is clearly a matrix to get windows and linux platforms crafted. And the 'system test' is another dual-axis matrix of platform and jvm. I can easily make one matrix follow the other. So far, so good.

However, I'm stuck with the 'code quality' stuff as an outlier. Is there a way to run those stages parallel to the matrix runs. They are independent once the build is created (they do not need to wait for packaging). They are also time consuming, so running them serially with the two matrix phases makes the build longer. Jenkins complains if you put a matrix inside a parallel stage.

Any ideas on how to run non-matrix stages in parallel to a matrix?


Solution

  • I came up with a somewhat IMHO "better" solution:

    stage {
        matrix {
            axes {
                axis {
                    name 'ORIGAXIS'
                    values 'ALPHA','BETA','BAR','BAZ'
                }
            }
            stages {
               stage ("alpha") {
                   when { expression { env.ORIGAXIS == "ALPHA" } }
                   steps {
                       alpha()
                   }           
               stage ("beta") {
                   when { expression { env.ORIGAXIS == "BETA" } }
                   steps {
                       beta()
                   }
               }
               stage ("Tests") {
                   when { allOf
                       expression { env.ORIGAXIS != "ALPHA" }
                       expression { env.ORIGAXIS != "BETA" }
                   }
                   stages {
                       stage("First") {
                          originalFirst( ...)
                        }
                       stage("Second") {
                          originalSecond(...)
                       }
                    }
                }
         }
    }
    

    Of course, the final layout is not perfect. But, it works, is not that much cumbersome and still easily maintainable.