Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-53162

Blueocean support for visualizing stages in parallel block in scripted pipeline

      As suggested in JENKINS-38442 I created this new feature request which I would like to use to explicitely target the support for visualising one level of stages in parallel blocks, like:

      parallel (
        "first": {
          stage("JUnit") {
          }
          stage("Firefox") { 
          }
        },
        "second" : {
          stage("D3Unit") {
          }
          stage("Edge") {
          }
        },
        "third" : {
          stage("Safari") {
          }
        }
      )
      

      As an example on how a possible visualization could look like please check the attached png.

          [JENKINS-53162] Blueocean support for visualizing stages in parallel block in scripted pipeline

          Very interested in this as we only used scripted pipelines and was disappointed that the other issue only addressed declarative.

          Jared Kauppila added a comment - Very interested in this as we only used scripted pipelines and was disappointed that the other issue only addressed declarative.

          Hi,

          I would definitely love to see this on scripted pipelines as well

          Vladislav Zedano added a comment - Hi, I would definitely love to see this on scripted pipelines as well

          leromarinvit added a comment -

          I dug into this a little and found that BlueOcean explicitly disables rendering sequential stages in parallel branches unless the build is a declarative pipeline run. So a quick and dirty workaround is to fake a declarative pipeline in a scripted one. Then arrange your stages similarly to what declarative would do (namely create a wrapper stage with the same name as each parallel branch), and it will be rendered nicely.

          Needless to say, this is an ugly hack and might break in unforeseen ways. Though it seems to work in my tests, and the only side effect I saw was that a "Restart from Stage" option appeared in the build's menu, with an empty dropdown list. This seems benign enough, but I don't know what else it could cause, so be warned.

          So how do you fake a declarative run? BlueOcean checks for an action of type ExecutionModelAction, so that's what we have to add:

          import org.jenkinsci.plugins.pipeline.modeldefinition.actions.ExecutionModelAction
          import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTStages
          
          if (!currentBuild.rawBuild.getAction(ExecutionModelAction))
              currentBuild.rawBuild.addAction(new ExecutionModelAction(new ModelASTStages(null)))
          

          This won't work in a sandboxed script, but it does in a global shared library. So it's probably not worth the effort (and potential risk) to make jobs with hand-written parallel-sequential stages render properly, but it might just be a workaround if you generate jobs with such a structure from library functions.

          leromarinvit added a comment - I dug into this a little and found that BlueOcean explicitly disables rendering sequential stages in parallel branches unless the build is a declarative pipeline run. So a quick and dirty workaround is to fake a declarative pipeline in a scripted one. Then arrange your stages similarly to what declarative would do (namely create a wrapper stage with the same name as each parallel branch), and it will be rendered nicely. Needless to say, this is an ugly hack and might break in unforeseen ways. Though it seems to work in my tests, and the only side effect I saw was that a "Restart from Stage" option appeared in the build's menu, with an empty dropdown list. This seems benign enough, but I don't know what else it could cause, so be warned. So how do you fake a declarative run? BlueOcean checks for an action of type ExecutionModelAction , so that's what we have to add: import org.jenkinsci.plugins.pipeline.modeldefinition.actions.ExecutionModelAction import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTStages if (!currentBuild.rawBuild.getAction(ExecutionModelAction)) currentBuild.rawBuild.addAction( new ExecutionModelAction( new ModelASTStages( null ))) This won't work in a sandboxed script, but it does in a global shared library. So it's probably not worth the effort (and potential risk) to make jobs with hand-written parallel-sequential stages render properly, but it might just be a workaround if you generate jobs with such a structure from library functions.

          leromarinvit: Doesn't work for me using BlueOcean 1.8.2. That is: The job's green but BlueOcean still won't show me any stages which have been defined inside a parallel branch. Which version of BlueOcean did you use?

          Joerg Schwaerzler added a comment - leromarinvit : Doesn't work for me using BlueOcean 1.8.2. That is: The job's green but BlueOcean still won't show me any stages which have been defined inside a parallel branch. Which version of BlueOcean did you use?

          Jake Hilborn added a comment -

          leromarinvit Wow that actually works for scripted pipelines. The key is to have a stage inside the parallel block that has the same name as the parallel stage. Here's a working example.

          parallel (
            "one": {
              stage("one") {
                stage("one-child1") {
                  println "one-child1"
                }
                stage("one-child2") {
                  println "one-child2"
                }
              }
            },
            "two": {
              stage("two") {
                stage("two-child1") {
                  println "two-child1"
                }
                stage("two-child2") {
                  println "two-child2"
                }
              }
            },
            "three": {
              stage("three") {
                stage("three-child1") {
                  println "three-child1"
                }
                stage("three-child2") {
                  println "three-child2"
                }
              }
            }
          ) 

          Jake Hilborn added a comment - leromarinvit Wow that actually works for scripted pipelines. The key is to have a stage inside the parallel block that has the same name as the parallel stage. Here's a working example. parallel ( "one" : { stage( "one" ) { stage( "one-child1" ) { println "one-child1" } stage( "one-child2" ) { println "one-child2" } } }, "two" : { stage( "two" ) { stage( "two-child1" ) { println "two-child1" } stage( "two-child2" ) { println "two-child2" } } }, "three" : { stage( "three" ) { stage( "three-child1" ) { println "three-child1" } stage( "three-child2" ) { println "three-child2" } } } )

          Damien Merlin added a comment -

          Hi Jake,

          Can you please let us know which version of Jenkins and Bitbucket Plugin you are using ?

          I tested your pipeline code using Jenkins ver. 2.176.1 and Blue Ocean version 1.17.0 and the rendering is showing only one stage per parallel.

          Thanks

           

          Damien Merlin added a comment - Hi Jake, Can you please let us know which version of Jenkins and Bitbucket Plugin you are using ? I tested your pipeline code using Jenkins ver. 2.176.1 and Blue Ocean version 1.17.0 and the rendering is showing only one stage per parallel. Thanks  

          Jake Hilborn added a comment - - edited

          I believe I tested this on Jenkins 2.164.2. However, it doesn't work well enough to be usable. Console logs are duplicated and shown in multiple stages when using this sequential inside parallel hack. It makes the approach useless. For example, in the image I posted above, I would see "one-child2" console messages inside the "one-child2" stage and the "two-child2" stage which makes debugging very confusing.

          Jake Hilborn added a comment - - edited I believe I tested this on Jenkins 2.164.2. However, it doesn't work well enough to be usable. Console logs are duplicated and shown in multiple stages when using this sequential inside parallel hack. It makes the approach useless. For example, in the image I posted above, I would see "one-child2" console messages inside the "one-child2" stage and the "two-child2" stage which makes debugging very confusing.

          Damien Merlin added a comment -

          Thanks for your input Jake.

           

          Damien Merlin added a comment - Thanks for your input Jake.  

          Andrius Štikonas added a comment - - edited

          It doesn't seem any less usable than declarative pipeline. I tried with Jenkins version 2.182 and Blue Ocean 1.17.0.

          When I view logs while job is running all branches with sequential parallel stages show the same logs of first branch (everything shows fine after job completes) but that's not specific to scripted pipeline (see https://issues.jenkins-ci.org/browse/JENKINS-58009).

          Andrius Štikonas added a comment - - edited It doesn't seem any less usable than declarative pipeline. I tried with Jenkins version 2.182 and Blue Ocean 1.17.0. When I view logs while job is running all branches with sequential parallel stages show the same logs of first branch (everything shows fine after job completes) but that's not specific to scripted pipeline (see  https://issues.jenkins-ci.org/browse/JENKINS-58009 ).

          It seems that in latest Blue Ocean it works well and is usable.

          Shall we close this as fixed?

          Andrius Štikonas added a comment - It seems that in latest Blue Ocean it works well and is usable. Shall we close this as fixed?

          Jesse Glick added a comment -

          stikonas if you have one, a minimal example (script + screenshot) would be appreciated.

          Jesse Glick added a comment - stikonas if you have one, a minimal example (script + screenshot) would be appreciated.

          Andrius Štikonas added a comment - - edited

          My example is the same as above. It's just that in version 1.9.0 all those bugs that prevented clicking on stages got fixed (they affected declarative pipeline too).

           

          import org.jenkinsci.plugins.pipeline.modeldefinition.actions.ExecutionModelAction
          import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTStages
          
          if (!currentBuild.rawBuild.getAction(ExecutionModelAction))
              currentBuild.rawBuild.addAction(new ExecutionModelAction(new ModelASTStages(null)))
          
          parallel (
            "one": {
              stage("one") {
                stage("one-child1") {
                  println "one-child1"
                }
                stage("one-child2") {
                  println "one-child2"
                }
              }
            },
            "two": {
              stage("two") {
                stage("two-child1") {
                  println "two-child1"
                }
                stage("two-child2") {
                  println "two-child2"
                }
              }
            },
            "three": {
              stage("three") {
                stage("three-child1") {
                  println "three-child1"
                }
                stage("three-child2") {
                  println "three-child2"
                }
              }
            }
          ) 
          
          

          Andrius Štikonas added a comment - - edited My example is the same as above. It's just that in version 1.9.0 all those bugs that prevented clicking on stages got fixed (they affected declarative pipeline too).   import org.jenkinsci.plugins.pipeline.modeldefinition.actions.ExecutionModelAction import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTStages if (!currentBuild.rawBuild.getAction(ExecutionModelAction)) currentBuild.rawBuild.addAction( new ExecutionModelAction( new ModelASTStages( null ))) parallel ( "one" : { stage( "one" ) { stage( "one-child1" ) { println "one-child1" } stage( "one-child2" ) { println "one-child2" } } }, "two" : { stage( "two" ) { stage( "two-child1" ) { println "two-child1" } stage( "two-child2" ) { println "two-child2" } } }, "three" : { stage( "three" ) { stage( "three-child1" ) { println "three-child1" } stage( "three-child2" ) { println "three-child2" } } } )

          Jesse Glick added a comment -

          If you have to use currentBuild.rawBuild, or import generally, then this is clearly not fixed.

          Jesse Glick added a comment - If you have to use currentBuild.rawBuild , or import generally, then this is clearly not fixed.

          Hui Jun Ng added a comment -

          Yup I agree with jglick on that. The example stikonas shared is a workaround instead of a fix. I would imagine a fix would be that it simply works out of the box similar to how it does for declarative pipeline.

           

          Hui Jun Ng added a comment - Yup I agree with jglick on that. The example stikonas shared is a workaround instead of a fix. I would imagine a fix would be that it simply works out of the box similar to how it does for declarative pipeline.  

          Olivier Lamy added a comment -

          Olivier Lamy added a comment - https://github.com/jenkinsci/blueocean-plugin/pull/2024

          Great to see this is finally available

          olamy: Can you already tell when there will be a release containing this fix?

          Joerg Schwaerzler added a comment - Great to see this is finally available olamy : Can you already tell when there will be a release containing this fix?

            olamy Olivier Lamy
            macdrega Joerg Schwaerzler
            Votes:
            72 Vote for this issue
            Watchers:
            74 Start watching this issue

              Created:
              Updated:
              Resolved: