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

UI for downstream jobs launched with 'build' step

    Details

    • Sprint:
      Blue Ocean 1.1, Blue Ocean 1.2-beta1, Blue Ocean 1.2-beta2, Blue Ocean 1.4 - beta 3, Blue Ocean 1.5 - beta 2
    • Similar Issues:
    • Released As:
      1.14.0

      Description

      Improvement on roadmap

      This improvement is on the Blue Ocean project roadmap. Check the roadmap page for updates.

      Same pipeline as JENKINS-38337

      stage "Stage 1"
      stage ("Trigger jobs") {
          parallel(
              downstream1: {
                  build 'downstream1'
              },
              downstream2: {
                  build 'downstream2'
              }
          )
      }
      

      In the logs, we see things like Starting building: downstream2 #3, however unlike the classic console, this is not a link, so you can't browse to the other build.

       

      Out of scope: 

      When the "don't wait" mode is used, there is no link to the resultant downstream job, so no need to link it back  ( ie build job: 'downer', wait: false)

       

       

        Attachments

          Issue Links

            Activity

            Hide
            jamesdumay James Dumay added a comment -

            Vincent Latombe Is this a freestyle job that you are triggering downstream? what if we included the log of the downstream job in the step?

            Show
            jamesdumay James Dumay added a comment - Vincent Latombe Is this a freestyle job that you are triggering downstream? what if we included the log of the downstream job in the step?
            Hide
            vlatombe Vincent Latombe added a comment -

            In my case I'm triggering another pipeline

            Show
            vlatombe Vincent Latombe added a comment - In my case I'm triggering another pipeline
            Hide
            jamesdumay James Dumay added a comment -

            Vincent Latombe interesting - whats the use case there?

            Show
            jamesdumay James Dumay added a comment - Vincent Latombe interesting - whats the use case there?
            Hide
            vlatombe Vincent Latombe added a comment - - edited

            My main pipeline is doing packaging while there are several downstream pipelines run in parallel which does platform deployment. There are a couple of reasons to do this:

            • locking (the upstream is a multibranch pipeline, I want to limit number of downstream executions)
            • ability to re-run a single downstream in case of failure : we are deploying to cloud infrastructures, which have eventual consistency issues and are causing various timeouts/flakiness issues (each downstream is reporting its individual status to GH)
            • log rendering: the base console output for parallel branches is interleaved which makes investigation very complex if these are included within the same pipeline (and the current pipeline log drilldown is really not user-friendly)
            Show
            vlatombe Vincent Latombe added a comment - - edited My main pipeline is doing packaging while there are several downstream pipelines run in parallel which does platform deployment. There are a couple of reasons to do this: locking (the upstream is a multibranch pipeline, I want to limit number of downstream executions) ability to re-run a single downstream in case of failure : we are deploying to cloud infrastructures, which have eventual consistency issues and are causing various timeouts/flakiness issues (each downstream is reporting its individual status to GH) log rendering: the base console output for parallel branches is interleaved which makes investigation very complex if these are included within the same pipeline (and the current pipeline log drilldown is really not user-friendly)
            Hide
            jamesdumay James Dumay added a comment -

            Vincent Latombe though would it be fair to say that Blue Ocean has solved the "log rendering" use case for parallel steps? There is a CloudBees plugin called "checkpoint" that solves the "re-run downstream job" use case.

            Not sure if I understand the Locking use case. Could you please describe that?

            Show
            jamesdumay James Dumay added a comment - Vincent Latombe though would it be fair to say that Blue Ocean has solved the "log rendering" use case for parallel steps? There is a CloudBees plugin called "checkpoint" that solves the "re-run downstream job" use case. Not sure if I understand the Locking use case. Could you please describe that?
            Hide
            vlatombe Vincent Latombe added a comment -

            Concerning logs, I think it is pretty much solved by BO indeed.

            Checkpoint, I don't think the current feature solves it because the use case would be to restart only a few (the failed ones) of the tests that are executed in parallel, not all of them.

            Locking: on paper, https://jenkins.io/doc/pipeline/steps/lockable-resources/#lock-lock-shared-resource could solve it but haven't taken time to evaluate if it fully covers the use case.

            Show
            vlatombe Vincent Latombe added a comment - Concerning logs, I think it is pretty much solved by BO indeed. Checkpoint, I don't think the current feature solves it because the use case would be to restart only a few (the failed ones) of the tests that are executed in parallel, not all of them. Locking: on paper, https://jenkins.io/doc/pipeline/steps/lockable-resources/#lock-lock-shared-resource could solve it but haven't taken time to evaluate if it fully covers the use case.
            Hide
            michaelneale Michael Neale added a comment -

            Yes I think there needs to either be log decorations of affordances for when other jobs are invoked

            Show
            michaelneale Michael Neale added a comment - Yes I think there needs to either be log decorations of affordances for when other jobs are invoked
            Hide
            tsniatowski Tomasz Śniatowski added a comment -

            We're trying to avoid UI issues when there are sub-steps in a parallel pipeline stage (JENKINS-38442) by triggering sub-builds instead – but as the UI has no links to these sub-builds the experience is not great either way. Any chance triggered build info could be a link?

            Show
            tsniatowski Tomasz Śniatowski added a comment - We're trying to avoid UI issues when there are sub-steps in a parallel pipeline stage ( JENKINS-38442 ) by triggering sub-builds instead – but as the UI has no links to these sub-builds the experience is not great either way. Any chance triggered build info could be a link?
            Hide
            jamesdumay James Dumay added a comment -

            Tomasz Śniatowski we certainly plan for it to be a link of some kind. We will upload a design on this issue when we get to this one so you can give us feedback

            Show
            jamesdumay James Dumay added a comment - Tomasz Śniatowski we certainly plan for it to be a link of some kind. We will upload a design on this issue when we get to this one so you can give us feedback
            Hide
            jamesdumay James Dumay added a comment -

            Ivan Meredith This one is becoming crazy important for us to solve. I'd like you to take a look after the acceptance test issues.

            Show
            jamesdumay James Dumay added a comment - Ivan Meredith This one is becoming crazy important for us to solve. I'd like you to take a look after the acceptance test issues.
            Hide
            rodrigc Craig Rodrigues added a comment -

            James Dumay what is the strategy that will be used to fix this?  One option

            would be to add a hyperlink to downstream1 and downstream2 in the UI for stage1.

             

            Another option which would be cool would be instead of adding hyperlinks,

            you could expand downstream1 and downstream2 in the UI for stage1 so that you can see all the stages being executed.  Maybe some sort of expandable/collapsible view could be used.

            Show
            rodrigc Craig Rodrigues added a comment - James Dumay what is the strategy that will be used to fix this?  One option would be to add a hyperlink to downstream1 and downstream2 in the UI for stage1 .   Another option which would be cool would be instead of adding hyperlinks, you could expand downstream1 and downstream2 in the UI for stage1 so that you can see all the stages being executed.  Maybe some sort of expandable/collapsible view could be used.
            Hide
            mbmop Mostyn Bramley-Moore added a comment -

            The first suggestion (add links to the sub builds) is most important/most useful IMO.

            The second idea also sounds interesting, but I think it would be best in addition to having links to the sub builds, not replacing the links.

            Show
            mbmop Mostyn Bramley-Moore added a comment - The first suggestion (add links to the sub builds) is most important/most useful IMO. The second idea also sounds interesting, but I think it would be best in addition to having links to the sub builds, not replacing the links.
            Hide
            mbmop Mostyn Bramley-Moore added a comment -

            After thinking about this some more, I think we should just have links to downstream builds.

            Downstream builds are likely to be long running (eg in my use case, this is why they're sub builds, made in parallel) and have large log files- the build view is already very heavy and merging downstream builds into the parent build view page could make it too slow to be useful.

            Show
            mbmop Mostyn Bramley-Moore added a comment - After thinking about this some more, I think we should just have links to downstream builds. Downstream builds are likely to be long running (eg in my use case, this is why they're sub builds, made in parallel) and have large log files- the build view is already very heavy and merging downstream builds into the parent build view page could make it too slow to be useful.
            Hide
            michaelneale Michael Neale added a comment -

            thanks Mostyn Bramley-Moore

             

            James Dumay is there a related design ticket - as there still seems some todos for the design of this (unless there is and I didn't see it). 

            Show
            michaelneale Michael Neale added a comment - thanks Mostyn Bramley-Moore .    James Dumay is there a related design ticket - as there still seems some todos for the design of this (unless there is and I didn't see it). 
            Hide
            jamesdumay James Dumay added a comment -

            Michael Neale not yet - its a WIP. We mostly need to investigate getting this data our of the flow graph when:

            • It triggers and continues
            • It triggers and waits
            Show
            jamesdumay James Dumay added a comment - Michael Neale not yet - its a WIP. We mostly need to investigate getting this data our of the flow graph when: It triggers and continues It triggers and waits
            Hide
            michaelneale Michael Neale added a comment -

            James Dumay ack.. yes it seems like an MVP would just be hyper links anyway and solve most peoples problems. Then once we have the data and that working, can investigate Craig Rodrigues idea about showing an expandable view of what is happening if it makes sense still. 

            Show
            michaelneale Michael Neale added a comment - James Dumay ack.. yes it seems like an MVP would just be hyper links anyway and solve most peoples problems. Then once we have the data and that working, can investigate Craig Rodrigues idea about showing an expandable view of what is happening if it makes sense still. 
            Hide
            michaelneale Michael Neale added a comment -

            I think we need to bring this up

            Show
            michaelneale Michael Neale added a comment - I think we need to bring this up
            Hide
            kshultz Karl Shultz added a comment -

            Testing Notes:

            • When implemented, unit tests should accompany the changes.
            • An automated test should be created to verify the validity of any links which are created in this way. There are a number of other changes in flight for the logging, and the ATH for those scenarios probably deserves a revisit
            Show
            kshultz Karl Shultz added a comment - Testing Notes: When implemented, unit tests should accompany the changes. An automated test should be created to verify the validity of any links which are created in this way. There are a number of other changes in flight for the logging, and the ATH for those scenarios probably deserves a revisit
            Hide
            michaelneale Michael Neale added a comment -

            hey Alvaro Lobato in your usage of this (I have never used it myself) - so you use the default build where it waits for downstream, or the "wait: false" set and forget? (in the former there is a link to the actual downstream run - the latter, there is no link to the actual run, just the job page) - if you aren't sure, just show me the output or the pipeline

            Show
            michaelneale Michael Neale added a comment - hey Alvaro Lobato in your usage of this (I have never used it myself) - so you use the default build where it waits for downstream, or the "wait: false" set and forget? (in the former there is a link to the actual downstream run - the latter, there is no link to the actual run, just the job page) - if you aren't sure, just show me the output or the pipeline
            Hide
            sophistifunk Josh McDonald added a comment -

            Backend changes PR: https://github.com/jenkinsci/blueocean-plugin/pull/1575

             

            I'll switch over to some other stuff to give people a chance to look at it before I whip up some UI.

            Show
            sophistifunk Josh McDonald added a comment - Backend changes PR: https://github.com/jenkinsci/blueocean-plugin/pull/1575   I'll switch over to some other stuff to give people a chance to look at it before I whip up some UI.
            Hide
            scm_issue_link SCM/JIRA link daemon added a comment -

            Code changed in jenkins
            User: Josh McDonald
            Path:
            .gitignore
            src/main/java/org/jenkinsci/plugins/workflow/support/steps/build/BuildTriggerStepExecution.java
            src/main/java/org/jenkinsci/plugins/workflow/support/steps/build/BuildUpstreamNodeAction.java
            http://jenkins-ci.org/commit/pipeline-build-step-plugin/b32359edb37879772ffba7671cc565b994ec1e2e
            Log:
            feature/JENKINS-38339-link-downstream-builds-to-trigger-node * Functionality OK, needs tests and javadocs

            Show
            scm_issue_link SCM/JIRA link daemon added a comment - Code changed in jenkins User: Josh McDonald Path: .gitignore src/main/java/org/jenkinsci/plugins/workflow/support/steps/build/BuildTriggerStepExecution.java src/main/java/org/jenkinsci/plugins/workflow/support/steps/build/BuildUpstreamNodeAction.java http://jenkins-ci.org/commit/pipeline-build-step-plugin/b32359edb37879772ffba7671cc565b994ec1e2e Log: feature/ JENKINS-38339 -link-downstream-builds-to-trigger-node * Functionality OK, needs tests and javadocs
            Hide
            scm_issue_link SCM/JIRA link daemon added a comment -

            Code changed in jenkins
            User: Josh McDonald
            Path:
            pom.xml
            src/main/java/org/jenkinsci/plugins/workflow/support/steps/build/BuildUpstreamNodeAction.java
            src/test/java/org/jenkinsci/plugins/workflow/support/steps/build/BuildTriggerStepTest.java
            http://jenkins-ci.org/commit/pipeline-build-step-plugin/0bb93ea7927af7ddac8960c024089546c4dd50d1
            Log:
            feature/JENKINS-38339-link-downstream-builds-to-trigger-node * Add unit test, javadocs, bump parent-pom to run tests from Idea

            Show
            scm_issue_link SCM/JIRA link daemon added a comment - Code changed in jenkins User: Josh McDonald Path: pom.xml src/main/java/org/jenkinsci/plugins/workflow/support/steps/build/BuildUpstreamNodeAction.java src/test/java/org/jenkinsci/plugins/workflow/support/steps/build/BuildTriggerStepTest.java http://jenkins-ci.org/commit/pipeline-build-step-plugin/0bb93ea7927af7ddac8960c024089546c4dd50d1 Log: feature/ JENKINS-38339 -link-downstream-builds-to-trigger-node * Add unit test, javadocs, bump parent-pom to run tests from Idea
            Hide
            scm_issue_link SCM/JIRA link daemon added a comment -

            Code changed in jenkins
            User: Josh McDonald
            Path:
            pom.xml
            http://jenkins-ci.org/commit/pipeline-build-step-plugin/bbdef0c0427ce71e0e494dc2f0440b402fbc495c
            Log:
            Merge branch 'master' into feature/JENKINS-38339-link-downstream-builds-to-trigger-node

            Show
            scm_issue_link SCM/JIRA link daemon added a comment - Code changed in jenkins User: Josh McDonald Path: pom.xml http://jenkins-ci.org/commit/pipeline-build-step-plugin/bbdef0c0427ce71e0e494dc2f0440b402fbc495c Log: Merge branch 'master' into feature/ JENKINS-38339 -link-downstream-builds-to-trigger-node
            Hide
            scm_issue_link SCM/JIRA link daemon added a comment -

            Code changed in jenkins
            User: Josh McDonald
            Path:
            http://jenkins-ci.org/commit/pipeline-build-step-plugin/5818a01c4bf68ccb3da2edf0b9e55d927b87bce5
            Log:
            Merge branch 'master' into feature/JENKINS-38339-link-downstream-builds-to-trigger-node

            Show
            scm_issue_link SCM/JIRA link daemon added a comment - Code changed in jenkins User: Josh McDonald Path: http://jenkins-ci.org/commit/pipeline-build-step-plugin/5818a01c4bf68ccb3da2edf0b9e55d927b87bce5 Log: Merge branch 'master' into feature/ JENKINS-38339 -link-downstream-builds-to-trigger-node
            Hide
            scm_issue_link SCM/JIRA link daemon added a comment -

            Code changed in jenkins
            User: Josh McDonald
            Path:
            src/main/java/org/jenkinsci/plugins/workflow/support/steps/build/BuildTriggerStepExecution.java
            src/main/java/org/jenkinsci/plugins/workflow/support/steps/build/BuildUpstreamNodeAction.java
            http://jenkins-ci.org/commit/pipeline-build-step-plugin/d08db2cbc0471967ad7a3d509f9faf99c001f54e
            Log:
            feature/JENKINS-38339-link-downstream-builds-to-trigger-node * Unstar imports, clean up JavaDocs

            Show
            scm_issue_link SCM/JIRA link daemon added a comment - Code changed in jenkins User: Josh McDonald Path: src/main/java/org/jenkinsci/plugins/workflow/support/steps/build/BuildTriggerStepExecution.java src/main/java/org/jenkinsci/plugins/workflow/support/steps/build/BuildUpstreamNodeAction.java http://jenkins-ci.org/commit/pipeline-build-step-plugin/d08db2cbc0471967ad7a3d509f9faf99c001f54e Log: feature/ JENKINS-38339 -link-downstream-builds-to-trigger-node * Unstar imports, clean up JavaDocs
            Hide
            scm_issue_link SCM/JIRA link daemon added a comment -

            Code changed in jenkins
            User: Josh McDonald
            Path:
            pom.xml
            http://jenkins-ci.org/commit/pipeline-build-step-plugin/6e0f22d3f292c7207629353e1cb0acdd45a2de18
            Log:
            Merge remote-tracking branch 'github-funk/feature/JENKINS-38339-link-downstream-builds-to-trigger-node' into feature/JENKINS-38339-link-downstream-builds-to-trigger-node

            Show
            scm_issue_link SCM/JIRA link daemon added a comment - Code changed in jenkins User: Josh McDonald Path: pom.xml http://jenkins-ci.org/commit/pipeline-build-step-plugin/6e0f22d3f292c7207629353e1cb0acdd45a2de18 Log: Merge remote-tracking branch 'github-funk/feature/ JENKINS-38339 -link-downstream-builds-to-trigger-node' into feature/ JENKINS-38339 -link-downstream-builds-to-trigger-node
            Hide
            scm_issue_link SCM/JIRA link daemon added a comment -

            Code changed in jenkins
            User: Andrew Bayer
            Path:
            .gitignore
            src/main/java/org/jenkinsci/plugins/workflow/support/steps/build/BuildTriggerStepExecution.java
            src/main/java/org/jenkinsci/plugins/workflow/support/steps/build/BuildUpstreamNodeAction.java
            src/test/java/org/jenkinsci/plugins/workflow/support/steps/build/BuildTriggerStepTest.java
            http://jenkins-ci.org/commit/pipeline-build-step-plugin/4e115c5a18d0696e8d56b538f650e5e35757f755
            Log:
            Merge pull request #18 from sophistifunk/feature/JENKINS-38339-link-downstream-builds-to-trigger-node

            Mark downstream runs with pointer to upstream FlowNode

            Compare: https://github.com/jenkinsci/pipeline-build-step-plugin/compare/2e4012ecac35...4e115c5a18d0

            Show
            scm_issue_link SCM/JIRA link daemon added a comment - Code changed in jenkins User: Andrew Bayer Path: .gitignore src/main/java/org/jenkinsci/plugins/workflow/support/steps/build/BuildTriggerStepExecution.java src/main/java/org/jenkinsci/plugins/workflow/support/steps/build/BuildUpstreamNodeAction.java src/test/java/org/jenkinsci/plugins/workflow/support/steps/build/BuildTriggerStepTest.java http://jenkins-ci.org/commit/pipeline-build-step-plugin/4e115c5a18d0696e8d56b538f650e5e35757f755 Log: Merge pull request #18 from sophistifunk/feature/ JENKINS-38339 -link-downstream-builds-to-trigger-node Mark downstream runs with pointer to upstream FlowNode Compare: https://github.com/jenkinsci/pipeline-build-step-plugin/compare/2e4012ecac35...4e115c5a18d0
            Hide
            stevenv Steven Visagie added a comment -

            We're extremely interested in having this functionality available. Will the proposed link work with both downstream pipelines and Jenkins classic jobs? We use a combination of both in our use case. If the downstream is a pipeline, will it navigate to the running pipeline in Blue Ocean?

            Show
            stevenv Steven Visagie added a comment - We're extremely interested in having this functionality available. Will the proposed link work with both downstream pipelines and Jenkins classic jobs? We use a combination of both in our use case. If the downstream is a pipeline, will it navigate to the running pipeline in Blue Ocean?
            Show
            sophistifunk Josh McDonald added a comment - UI changes PR:  https://github.com/jenkinsci/blueocean-plugin/pull/1675
            Hide
            sophistifunk Josh McDonald added a comment -

            Merged @ 203324c8913426d9a9fd6a7cfe82f40c157eacec

            Show
            sophistifunk Josh McDonald added a comment - Merged @ 203324c8913426d9a9fd6a7cfe82f40c157eacec
            Hide
            michaelneale Michael Neale added a comment -

            Steven Visagie good questoin, an experiment (if you have the ability to build it) would be worthwhile, but I expect it would work the same, as it doesn't necessarily care what is in the "build" step for things it triggers (ie what type it is) so ideally it would just work. 

            Show
            michaelneale Michael Neale added a comment - Steven Visagie good questoin, an experiment (if you have the ability to build it) would be worthwhile, but I expect it would work the same, as it doesn't necessarily care what is in the "build" step for things it triggers (ie what type it is) so ideally it would just work. 
            Hide
            sophistifunk Josh McDonald added a comment -

            It should be fine. It definitely won't work for classic upstream jobs tho.

            Show
            sophistifunk Josh McDonald added a comment - It should be fine. It definitely won't work for classic upstream jobs tho.
            Hide
            rodrigc Craig Rodrigues added a comment -

            I tested this fix out in 1.5 beta-2.  It works well!

            I found one minor problem in the UI, where it is difficult to identify which stage is selected in the UI.

            Keith Zantow wrote up this ticket, because I was having temporary problems with my JIRA login acces:

            JENKINS-50408

            Show
            rodrigc Craig Rodrigues added a comment - I tested this fix out in 1.5 beta-2.  It works well! I found one minor problem in the UI, where it is difficult to identify which stage is selected in the UI. Keith Zantow wrote up this ticket, because I was having temporary problems with my JIRA login acces: JENKINS-50408
            Hide
            stevenfoster Steven Foster added a comment -

            Is there a way to aggregate the triggered builds within a parallel stage? I'm launching 12 or so builds as a parallel stage (the whole build is basically just a dummy/launchpad for other builds) and clicking each individual stage to get the downstream link is very slightly bothersome

            Show
            stevenfoster Steven Foster added a comment - Is there a way to aggregate the triggered builds within a parallel stage? I'm launching 12 or so builds as a parallel stage (the whole build is basically just a dummy/launchpad for other builds) and clicking each individual stage to get the downstream link is very slightly bothersome
            Hide
            janbernloehr Jan Bernlöhr added a comment -

            How can we enabled this feature? We are using BlueOcean 1.82 with declaraitve pipelines and do not see links.

             

            stage('launch builds') {
                parallel {
                    stage('stereo/offline') {
                        steps {
                            build job: 'rebuild',
                        parameters:[
                                string(name: 'CONFIG_TO_BUILD', value: 'stereo/offline')
                            ],
                        propagate: true,
                        wait: true
                        }
                    }
                    stage('second_config') {
                        steps {
                            build job: 'rebuild',
                        parameters:[
                                string(name: 'CONFIG_TO_BUILD', value: 'second_config')
                            ],
                        propagate: true,
                        wait: true
                        }
                    }
                }
            }
            

            The invoked job 'rebuild' is also a declarative pipeline.

            Show
            janbernloehr Jan Bernlöhr added a comment - How can we enabled this feature? We are using BlueOcean 1.82 with declaraitve pipelines and do not see links.   stage( 'launch builds' ) { parallel { stage( 'stereo/offline' ) { steps { build job: 'rebuild' , parameters:[ string(name: 'CONFIG_TO_BUILD' , value: 'stereo/offline' ) ], propagate: true , wait: true } } stage( 'second_config' ) { steps { build job: 'rebuild' , parameters:[ string(name: 'CONFIG_TO_BUILD' , value: 'second_config' ) ], propagate: true , wait: true } } } } The invoked job 'rebuild' is also a declarative pipeline.
            Hide
            consek Jan Kacik added a comment -

            It is not working for parallel stages in declarative pipeline. 

            Show
            consek Jan Kacik added a comment - It is not working for parallel stages in declarative pipeline. 
            Hide
            andreimuresianu Andrei Muresianu added a comment -

            It is still a problem in December 2018.

            stage('Test Stack') {
                parallel {
                    stage('Functional Tests') {
                        steps {
                            build job: 'TEST-functional'
                        }
                    }
            
                    stage('View Tests') {
                        steps {
                            build job: 'TEST-view'
                        }
                    }
                }
                post {
                    failure {
                        echo 'Some of the functional/view tests failed. Tearing down the stack.'
                        build job: 'TEST-teardown'
                    }
                }
            } 

            None of TEST-functional, TEST-view, TEST-teardown are visible in BlueOcean (it looks like even the echo message got lost)

            However, the console output references all of the jobs - no issues there.

             

             

            Show
            andreimuresianu Andrei Muresianu added a comment - It is still a problem in December 2018. stage( 'Test Stack' ) { parallel { stage( 'Functional Tests' ) { steps { build job: 'TEST-functional' } } stage( 'View Tests' ) { steps { build job: 'TEST-view' } } } post { failure { echo 'Some of the functional/view tests failed. Tearing down the stack.' build job: 'TEST-teardown' } } } None of TEST-functional, TEST-view, TEST-teardown are visible in BlueOcean (it looks like even the echo message got lost) However, the console output references all of the jobs - no issues there.    
            Hide
            mbolesta Mike Bolesta added a comment -

            I'm also seeing this issue when the triggered build is inside a parallel stage.

            Show
            mbolesta Mike Bolesta added a comment - I'm also seeing this issue when the triggered build is inside a parallel stage.
            Hide
            yairogen Yair Ogen added a comment -

            Vincent Latombe can you update status? As Mike above I don't see links for triggered jobs in parallel step, only after the triggered job is done.

            Show
            yairogen Yair Ogen added a comment - Vincent Latombe can you update status? As Mike above I don't see links for triggered jobs in parallel step, only after the triggered job is done.
            Hide
            zakharovdi Denis Zakharov added a comment -

            Behavior and appearance in single and in parallel stages have difference. There are no link on child job if it was executed from parallel block. Can someone change bug status?

            Show
            zakharovdi Denis Zakharov added a comment - Behavior and appearance in single and in parallel stages have difference. There are no link on child job if it was executed from parallel block. Can someone change bug status?
            Hide
            stevenfoster Steven Foster added a comment -

            I have just updated blue ocean from 1.5 (where this UI feature was originally introduced, and working fine) to 1.10.1 and no longer have links to downstream jobs in my parallel steps.

            Show
            stevenfoster Steven Foster added a comment - I have just updated blue ocean from 1.5 (where this UI feature was originally introduced, and working fine) to 1.10.1 and no longer have links to downstream jobs in my parallel steps.
            Hide
            zakharovdi Denis Zakharov added a comment - - edited

            Try to use parallel sequential stages syntax. There are only one problem if we have N nested stages we get job links only in first N-1. We should add last stage in row w/o running build in it.

            pipeline{
                agent any
                stages{
                    stage('Nested parallel'){
                        parallel{
                            stage("parallel 1"){
                                stages{
                                    stage("Nested 1 with child in it"){
                                        steps{
                                            script{
                                                build "TestJob"
                                            }
                                        }
                                    }
                                    stage('Nested 2 with child in it'){
                                        steps{
                                            script{
                                                build "TestJob"
                                            }
                                        }
                                    }
                                    stage('Nested 3 w/o childs'){
                                        steps{
                                            echo "E-mail"
                                        }
                                    }
            
                                }
                            }
                            stage("parallel 2"){
                                stages{
                                    stage("Nested 1 with child in it"){
                                        steps{
                                            script{
                                                build "TestJob"
                                            }
                                        }
                                    }
                                    stage('Nested 2 with child in it'){
                                        steps{
                                            script{
                                                build "TestJob"
                                            }
                                        }
                                    }
                                    stage('Nested 3 w/o childs'){
                                        steps{
                                            echo "E-mail"
                                        }
                                    }
            
                                }
                            }
                        }
                    }
                }
            }
            
            
            Show
            zakharovdi Denis Zakharov added a comment - - edited Try to use parallel sequential stages syntax. There are only one problem if we have N nested stages we get job links only in first N-1. We should add last stage in row w/o running build in it. pipeline{ agent any stages{ stage( 'Nested parallel' ){ parallel{ stage( "parallel 1" ){ stages{ stage( "Nested 1 with child in it" ){ steps{ script{ build "TestJob" } } } stage( 'Nested 2 with child in it' ){ steps{ script{ build "TestJob" } } } stage( 'Nested 3 w/o childs' ){ steps{ echo "E-mail" } } } } stage( "parallel 2" ){ stages{ stage( "Nested 1 with child in it" ){ steps{ script{ build "TestJob" } } } stage( 'Nested 2 with child in it' ){ steps{ script{ build "TestJob" } } } stage( 'Nested 3 w/o childs' ){ steps{ echo "E-mail" } } } } } } } }
            Hide
            yairogen Yair Ogen added a comment -

            Denis Zakharov
            I tried this. Doesn't work. I get the links only after the triggered builds finish.
            During the parallel run, I only see the build name and the number in the console but no link in blue ocean ui.
             

            Show
            yairogen Yair Ogen added a comment - Denis Zakharov I tried this. Doesn't work. I get the links only after the triggered builds finish. During the parallel run, I only see the build name and the number in the console but no link in blue ocean ui.  
            Hide
            hariananthan Hari Ananthan added a comment - - edited

            Build Link for jobs launched inside parallel stages would be most appreciated! Without this, we are kinda stuck having to open so many windows to track what's going on. Especially since many of our stages are propagate : false and/or wait: false.

            EDIT : Actually the exact bug is that Links don't show up if a parallel stage has only one build.

            If parallel stage has 2 or more builds in series, then the links show up.

             

            For non-parallel stages, the URL shows up, but only after the child build is finished. So another request - create the URL link while the job is running. Some of our jobs take many minutes or hours and so having a live link would be really really useful.

            Thank you!

             

            Show
            hariananthan Hari Ananthan added a comment - - edited Build Link for jobs launched inside parallel stages would be most appreciated! Without this, we are kinda stuck having to open so many windows to track what's going on. Especially since many of our stages are propagate : false and/or wait: false. EDIT : Actually the exact bug is that Links don't show up if a parallel stage has  only one build. If parallel stage has 2 or more builds in series, then the links show up.   For non-parallel stages, the URL shows up, but only after the child build is finished. So another request - create the URL link while the job is running. Some of our jobs take many minutes or hours and so having a live link would be really really useful. Thank you!  
            Hide
            sophistifunk Josh McDonald added a comment -

            I'll look into this a bit today. Might be more difficult than it seems tho. Fairly warned, be ye, says I.

             

            I'll keep you guys posted.

             

            Show
            sophistifunk Josh McDonald added a comment - I'll look into this a bit today. Might be more difficult than it seems tho. Fairly warned, be ye, says I.   I'll keep you guys posted.  
            Hide
            hariananthan Hari Ananthan added a comment -

            Thanks a lot Josh. Here is a testcase and some pictures to illustrate the bug in case the description wasn't clear.

            P1_1 and P1_2 show links, but P2 doesn't.

            I am getting around now by simply adding a dummy "stage" before P2 in that branch of the parallel stage.

             

            pipeline {

                agent any

                stages {

                    stage('Parallel Stage') {

                        parallel {

                            stage('P1') {

                                stages {

                                    stage('P1_1') { steps

            { build job: 'child', parameters: [[$class: 'StringParameterValue', name: 'STAGE', value: 'P1_1']] }

                                    }

                                    stage('P1_2') { steps

            { build job: 'child', parameters: [[$class: 'StringParameterValue', name: 'STAGE', value: 'P1_2']] }

                                    }

                                }

                            }

                            stage('P2')

            {                     steps \{ build job: 'child', parameters: [[$class: 'StringParameterValue', name: 'STAGE', value: 'P2']] }

                            }

                        }

                    }

                }

            }

             

             

            Show
            hariananthan Hari Ananthan added a comment - Thanks a lot Josh. Here is a testcase and some pictures to illustrate the bug in case the description wasn't clear. P1_1 and P1_2 show links, but P2 doesn't. I am getting around now by simply adding a dummy "stage" before P2 in that branch of the parallel stage.   pipeline {     agent any     stages {         stage('Parallel Stage') {             parallel {                 stage('P1') {                     stages {                         stage('P1_1') { steps { build job: 'child', parameters: [[$class: 'StringParameterValue', name: 'STAGE', value: 'P1_1']] }                         }                         stage('P1_2') { steps { build job: 'child', parameters: [[$class: 'StringParameterValue', name: 'STAGE', value: 'P1_2']] }                         }                     }                 }                 stage('P2') {                     steps \{ build job: 'child', parameters: [[$class: 'StringParameterValue', name: 'STAGE', value: 'P2']] }                 }             }         }     } }    
            Hide
            yairogen Yair Ogen added a comment -

            For me adding an empty non-build step - doesn't solve the issue. I see links but only after the job was completed (either success or failure)

            Show
            yairogen Yair Ogen added a comment - For me adding an empty non-build step - doesn't solve the issue. I see links but only after the job was completed (either success or failure)
            Hide
            sophistifunk Josh McDonald added a comment -

            Still trying to figure this one out, but it's definitely a bug, and only seems to affect declarative pipelines, which makes for a nice test case of the same pipeline in both declarative and original pipeline versions.

            Show
            sophistifunk Josh McDonald added a comment - Still trying to figure this one out, but it's definitely a bug, and only seems to affect declarative pipelines, which makes for a nice test case of the same pipeline in both declarative and original pipeline versions.
            Show
            sophistifunk Josh McDonald added a comment - Fix PR here:  https://github.com/jenkinsci/blueocean-plugin/pull/1918
            Hide
            sophistifunk Josh McDonald added a comment -

            Fixed in master @ 3a9b64269d037ce25b17b3e088e29cfde43fe098

            Show
            sophistifunk Josh McDonald added a comment - Fixed in master @ 3a9b64269d037ce25b17b3e088e29cfde43fe098
            Hide
            zakharovdi Denis Zakharov added a comment -

            Josh McDonald thank you. When can we get build with this fix?

            Show
            zakharovdi Denis Zakharov added a comment - Josh McDonald thank you. When can we get build with this fix?
            Hide
            zakharovdi Denis Zakharov added a comment -

            It was rollbacked in BO 1.13.2. Can someone reopen it?

            Show
            zakharovdi Denis Zakharov added a comment - It was rollbacked in BO 1.13.2. Can someone reopen it?
            Hide
            sophistifunk Josh McDonald added a comment -

            Pull request to fix the regression (and extra tests) is here: https://github.com/jenkinsci/blueocean-plugin/pull/1933 - give it a few days as most of the reviewers are away from the office right now.

             

            Show
            sophistifunk Josh McDonald added a comment - Pull request to fix the regression (and extra tests) is here: https://github.com/jenkinsci/blueocean-plugin/pull/1933  - give it a few days as most of the reviewers are away from the office right now.  
            Hide
            sophistifunk Josh McDonald added a comment -

            Fixed in fc3e3a9f5cd13f535d88a173499bb929478f5b1f

            Show
            sophistifunk Josh McDonald added a comment - Fixed in fc3e3a9f5cd13f535d88a173499bb929478f5b1f
            Hide
            timethos Tim Huang added a comment -

            Hello, I am on Blue Ocean 1.17.0, and I do not see a link to my downstream jobs. Was there a regression?

             

            Show
            timethos Tim Huang added a comment - Hello, I am on Blue Ocean 1.17.0, and I do not see a link to my downstream jobs. Was there a regression?  
            Hide
            timethos Tim Huang added a comment - - edited

            I have more information on the matter - I was triggering downstream jobs within a `parallel` step (not sure if this has anything to do with it). In an earlier sequential stage, if I trigger another downstream build job, it causes itself and the ones in the parallel steps (that didn't show up before) to show up in their respective "Triggered Jobs" sections.

             

            Below is my groovy script. In the first sequential stage there is a downstream no-op job I made that, when triggered, seems to make the "Triggered Jobs" section show up for the other two downstream jobs that are triggered in the parallel stages further down. Without the no-op job, the "Triggered Jobs" section won't show up for the other two. The formatting of this code won't paste right (missing newlines here and there), so apologies.

            pipeline {
             agent none options {
              // Ideally, PRs build in less than 5
              timeout(time: 15, unit: 'MINUTES')
             } environment {
              CI = 'true'
              AWS_ACCESS_KEY_ID = credentials('aws-access-key-id-test')
              AWS_SECRET_ACCESS_KEY = credentials('aws-secret-access-key-test')
             } stages {
              stage('Abort previous builds on PR') {
               steps {
                // Not sure how this works, but… https://stackoverflow.com/a/52811034
                milestone label: '', ordinal: Integer.parseInt(env.BUILD_ID) - 1
                milestone label: '', ordinal: Integer.parseInt(env.BUILD_ID)
            
                // NOTE: Triggering this no-op job makes all Triggered Builds show up!!!
                build 'Utilities/TriggeringThisInStepsMakesTriggeredBuildsShowUp'
               }
              }  stage('PR tests') {
               failFast false
               parallel {
                stage('Linting & formatting') {
                 agent {
                  node {
                   label 'Node'
                  }
                 }     steps {
                  script {
                   pullRequest.createStatus(status: 'pending',
                    context: 'Format & Syntax (backend)',
                    description: 'Checking code quality…',
                    targetUrl: env.RUN_DISPLAY_URL)       try {
                    sh '! git diff --name-only ^HEAD origin/trunk | grep "^backend"'
                    echo "No changes found, skipping tests."        pullRequest.createStatus(status: 'success',
                     context: 'Format & Syntax (backend)',
                     description: 'Skipped (no changes).')
                   } catch (e) {
                    echo "Changes found, running tests."        ansiColor('xterm') {
                     // Check for it-block .only() calls which skip all other
                     // tests in a suite. These should NEVER be version-checked.
                     sh "! git grep '\\<it\\.only\\>'"         sh 'rm -rf ./frontend'
                     sh 'yarn'
                     sh 'yarn eslint ./backend'
                     sh 'yarn prettier -c "./backend/**/*.js"'         pullRequest.createStatus(status: 'success',
                      context: 'Format & Syntax (backend)',
                      description: 'Squeaky clean! You win today.')
                    }
                   }
                  }
                 }
                 post {
                  failure {
                   script {
                    pullRequest.createStatus(status: 'failure',
                     context: 'Format & Syntax (backend)',
                     description: 'Wow, did you even look at how malformed your code is?',
                     targetUrl: env.RUN_DISPLAY_URL)
                   }
                  }
                 }
                }    stage('Frontend tests') {
                 agent {
                  node {
                   label 'Node'
                  }
                 }     steps {
                  script {
                   pullRequest.createStatus(status: 'pending',
                    context: 'Unit tests (frontend)',
                    description: 'Making sure you didn\'t break anything…',
                    targetUrl: env.RUN_DISPLAY_URL)       try {
                    sh '! git diff --name-only ^HEAD origin/trunk | grep "^frontend"'
                    sh '! git diff --name-only ^HEAD origin/trunk | grep "^shared-utilities"'
                    echo "No changes found, skipping tests."        pullRequest.createStatus(status: 'success',
                     context: 'Unit tests (frontend)',
                     description: 'Skipped (no changes).')
                   } catch (e) {
                    echo "Changes found, running tests."        sh 'rm -rf ./backend'
                    sh 'yarn'
                    dir('frontend') {
                     ansiColor('xterm') {
                      sh 'yarn test:ci --coverage --json --outputFile=test-results.json'
                     }
                    }        pullRequest.createStatus(status: 'success',
                     context: 'Unit tests (frontend)',
                     description: 'Hot damn, they passed!')
                   }
                  }
                 }
                 post {
                  always {
                   script {
                    if (fileExists('frontend/test-results.json')) {
                     archiveArtifacts artifacts: 'frontend/test-results.json', fingerprint: true
                    }
                   }
                  }
                  failure {
                   script {
                    pullRequest.createStatus(status: 'failure',
                     context: 'Unit tests (frontend)',
                     description: 'What did you do???',
                     targetUrl: env.RUN_DISPLAY_URL)
                   }
                  }
                 }
                }    stage('Backend tests') {
                 agent {
                  node {
                   label 'Node'
                  }
                 }     steps {
                  script {
                   pullRequest.createStatus(status: 'pending',
                    context: 'Unit tests (backend)',
                    description: 'Making sure you didn\'t break anything…',
                    targetUrl: env.RUN_DISPLAY_URL)       try {
                    sh '! git diff --name-only ^HEAD origin/trunk | grep "^backend"'
                    sh '! git diff --name-only ^HEAD origin/trunk | grep "^shared-utilities"'
                    echo "No changes found, skipping tests."        pullRequest.createStatus(status: 'success',
                     context: 'Unit tests (backend)',
                     description: 'Skipped (no changes).')
                   } catch (e) {
                    echo "Changes found, running tests."        COMMIT = sh(script: 'git rev-parse HEAD', returnStdout: true).trim()
                    build job: 'Build_Phases/test-backend-parallel', parameters: [
                     [$class: 'StringParameterValue', name: 'COMMIT', value: COMMIT]
                    ], wait: true        pullRequest.createStatus(status: 'success',
                     context: 'Unit tests (backend)',
                     description: 'Wow, way to go!!')
                   }
                  }
                 }
                 post {
                  failure {
                   script {
                    pullRequest.createStatus(status: 'failure',
                     context: 'Unit tests (backend)',
                     description: 'Something terrible has happened.',
                     targetUrl: env.RUN_DISPLAY_URL)
                   }
                  }
                 }
                }    stage('Shared-utilities tests') {
                 agent {
                  node {
                   label 'Node'
                  }
                 }     steps {
                  script {
                   pullRequest.createStatus(status: 'pending',
                    context: 'Unit tests (shared-utilities)',
                    description: 'Making sure you didn\'t break anything…',
                    targetUrl: env.RUN_DISPLAY_URL)       try {
                    sh '! git diff --name-only ^HEAD origin/trunk | grep "^shared-utilities"'
                    echo "No changes found, skipping tests."        pullRequest.createStatus(status: 'success',
                     context: 'Unit tests (shared-utilities)',
                     description: 'Skipped (no changes).')
                   } catch (e) {
                    echo "Changes found, running tests."        sh 'rm -rf ./frontend && rm -rf ./backend'
                    sh 'yarn'
                    dir('shared-utilities') {
                     ansiColor('xterm') {
                      sh 'yarn test --coverage --json --outputFile=test-results.json'
                     }
                    }        pullRequest.createStatus(status: 'success',
                     context: 'Unit tests (shared-utilities)',
                     description: 'Congratulations, you may work another day.')
                   }
                  }
                 }
                 post {
                  always {
                   script {
                    if (fileExists('shared-utilities/test-results.json')) {
                     archiveArtifacts artifacts: 'shared-utilities/test-results.json', fingerprint: true
                    }
                   }
                  }
                  failure {
                   script {
                    pullRequest.createStatus(status: 'failure',
                     context: 'Unit tests (shared-utilities)',
                     description: 'Look, I get it. It\'s hard. FIX THIS!!!',
                     targetUrl: env.RUN_DISPLAY_URL)
                   }
                  }
                 }
                }    stage('Browser tests') {
                 agent {
                  node {
                   label 'Node'
                  }
                 }     environment {
                  CLIENT = 'main'
                  HEADLESS = 'true'
                  APP_ROOT = 'http://localhost:9002'
                  LD_LIBRARY_PATH = '/opt/google/chrome/lib/:$LD_LIBRARY_PATH'
                 }     steps {
                  script {
                   pullRequest.createStatus(status: 'pending',
                    context: 'E2E tests (Chrome)',
                    description: 'Making sure you didn\'t break anything…',
                    targetUrl: env.RUN_DISPLAY_URL)       try {
                    sh '! git diff --name-only ^HEAD origin/trunk | grep "^backend"'
                    sh '! git diff --name-only ^HEAD origin/trunk | grep "^frontend"'
                    sh '! git diff --name-only ^HEAD origin/trunk | grep "^shared-utilities"'
                    echo "No changes found, skipping tests."        pullRequest.createStatus(status: 'success',
                     context: 'E2E tests (Chrome)',
                     description: 'Skipped (no changes).')
                   } catch (e) {
                    echo "Changes found, running tests."        COMMIT = sh(script: 'git rev-parse HEAD', returnStdout: true).trim()
                    build job: 'Build_Phases/test-browser-parallel', parameters: [
                     [$class: 'StringParameterValue', name: 'COMMIT', value: COMMIT]
                    ]        pullRequest.createStatus(status: 'success',
                     context: 'E2E tests (Chrome)',
                     description: 'FULL FUNNEL SUCCESS, BEYOTCH!')
                   }
                  }
                 }
                 post {
                  failure {
                   script {
                    pullRequest.createStatus(status: 'failure',
                     context: 'E2E tests (Chrome)',
                     description: 'Oh no. Ohhhhhh no. This is bad.',
                     targetUrl: env.RUN_DISPLAY_URL)
                   }
                  }
                 }
                }    stage('Bundle test (admin)') {
                 agent {
                  node {
                   label 'Node'
                  }
                 }     environment {
                  CLIENT = 'admin'
                  AWS_ACCESS_KEY_ID = credentials('aws-access-key-id-deploy-production')
                  AWS_SECRET_ACCESS_KEY = credentials('aws-secret-access-key-deploy-production')
                 }     steps {
                  script {
                   pullRequest.createStatus(status: 'pending',
                    context: 'Bundle test (admin)',
                    description: 'Blending…',
                    targetUrl: env.RUN_DISPLAY_URL)       try {
                    sh '! git diff --name-only ^HEAD origin/trunk | grep "^cli"'
                    sh '! git diff --name-only ^HEAD origin/trunk | grep "^frontend"'
                    echo "No changes found, skipping tests."        pullRequest.createStatus(status: 'success',
                     context: 'Bundle test (admin)',
                     description: 'Skipped (no changes).')
                   } catch (e) {
                    echo "Changes found, running tests."        sh 'yarn'
                    sh 'yarn start -e production -n client node ./frontend/bin/client/build.js'        pullRequest.createStatus(status: 'success',
                     context: 'Bundle test (admin)',
                     description: 'Ah, the sweet smell of minified text.')
                   }
                  }
                 }
                 post {
                  failure {
                   script {
                    pullRequest.createStatus(status: 'failure',
                     context: 'Bundle test (admin)',
                     description: 'Uh-oh.',
                     targetUrl: env.RUN_DISPLAY_URL)
                   }
                  }
                 }
                }    stage('Bundle test (main)') {
                 agent {
                  node {
                   label 'Node'
                  }
                 }     environment {
                  CLIENT = 'main'
                  AWS_ACCESS_KEY_ID = credentials('aws-access-key-id-deploy-production')
                  AWS_SECRET_ACCESS_KEY = credentials('aws-secret-access-key-deploy-production')
                 }     steps {
                  script {
                   pullRequest.createStatus(status: 'pending',
                    context: 'Bundle test (main)',
                    description: 'Blending…',
                    targetUrl: env.RUN_DISPLAY_URL)       try {
                    sh '! git diff --name-only ^HEAD origin/trunk | grep "^cli"'
                    sh '! git diff --name-only ^HEAD origin/trunk | grep "^frontend"'
                    echo "No changes found, skipping tests."        pullRequest.createStatus(status: 'success',
                     context: 'Bundle test (main)',
                     description: 'Skipped (no changes).')
                   } catch (e) {
                    echo "Changes found, running tests."        sh 'yarn'
                    sh 'yarn start -e production -n client node ./frontend/bin/client/build.js'        pullRequest.createStatus(status: 'success',
                     context: 'Bundle test (main)',
                     description: 'Ah, the sweet smell of minified text.')
                   }
                  }
                 }
                 post {
                  failure {
                   script {
                    pullRequest.createStatus(status: 'failure',
                     context: 'Bundle test (main)',
                     description: 'Uh-oh.',
                     targetUrl: env.RUN_DISPLAY_URL)
                   }
                  }
                 }
                }    stage('Bundle test (quote-widget)') {
                 agent {
                  node {
                   label 'Node'
                  }
                 }     environment {
                  CLIENT = 'quote-widget'
                  AWS_ACCESS_KEY_ID = credentials('aws-access-key-id-deploy-production')
                  AWS_SECRET_ACCESS_KEY = credentials('aws-secret-access-key-deploy-production')
                 }     steps {
                  script {
                   pullRequest.createStatus(status: 'pending',
                    context: 'Bundle test (quote-widget)',
                    description: 'Blending…',
                    targetUrl: env.RUN_DISPLAY_URL)       try {
                    sh '! git diff --name-only ^HEAD origin/trunk | grep "^cli"'
                    sh '! git diff --name-only ^HEAD origin/trunk | grep "^frontend"'
                    echo "No changes found, skipping tests."
            
                    pullRequest.createStatus(status: 'success',
                     context: 'Bundle test (quote-widget)',
                     description: 'Skipped (no changes).')
                   } catch (e) {
                    echo "Changes found, running tests."        sh 'yarn'
                    sh 'yarn start -e production -n client node ./frontend/bin/client/build.js'        pullRequest.createStatus(status: 'success',
                     context: 'Bundle test (quote-widget)',
                     description: 'Ah, the sweet smell of minified text.')
                   }
                  }
                 }
                 post {
                  failure {
                   script {
                    pullRequest.createStatus(status: 'failure',
                     context: 'Bundle test (quote-widget)',
                     description: 'Uh-oh.',
                     targetUrl: env.RUN_DISPLAY_URL)
                   }
                  }
                 }
                }
               }
              }
             }
            }

             

             

            Show
            timethos Tim Huang added a comment - - edited I have more information on the matter - I was triggering downstream jobs within a `parallel` step (not sure if this has anything to do with it). In an earlier sequential stage, if I trigger another downstream build job, it causes itself and the ones in the parallel steps (that didn't show up before) to show up in their respective "Triggered Jobs" sections.   Below is my groovy script. In the first sequential stage there is a downstream no-op job I made that, when triggered, seems to make the "Triggered Jobs" section show up for the other two downstream jobs that are triggered in the parallel stages further down. Without the no-op job, the "Triggered Jobs" section won't show up for the other two. The formatting of this code won't paste right (missing newlines here and there), so apologies. pipeline { agent none options { // Ideally, PRs build in less than 5 timeout(time: 15, unit: 'MINUTES') } environment { CI = 'true' AWS_ACCESS_KEY_ID = credentials('aws-access-key-id-test') AWS_SECRET_ACCESS_KEY = credentials('aws-secret-access-key-test') } stages { stage('Abort previous builds on PR') { steps { // Not sure how this works, but… https://stackoverflow.com/a/52811034 milestone label: '', ordinal: Integer.parseInt(env.BUILD_ID) - 1 milestone label: '', ordinal: Integer.parseInt(env.BUILD_ID) // NOTE: Triggering this no-op job makes all Triggered Builds show up!!! build 'Utilities/TriggeringThisInStepsMakesTriggeredBuildsShowUp' } } stage('PR tests') { failFast false parallel { stage('Linting & formatting') { agent { node { label 'Node' } } steps { script { pullRequest.createStatus(status: 'pending', context: 'Format & Syntax (backend)', description: 'Checking code quality…', targetUrl: env.RUN_DISPLAY_URL) try { sh '! git diff --name-only ^HEAD origin/trunk | grep "^backend"' echo "No changes found, skipping tests." pullRequest.createStatus(status: 'success', context: 'Format & Syntax (backend)', description: 'Skipped (no changes).') } catch (e) { echo "Changes found, running tests." ansiColor('xterm') { // Check for it-block .only() calls which skip all other // tests in a suite. These should NEVER be version-checked. sh "! git grep '\\<it\\.only\\>'" sh 'rm -rf ./frontend' sh 'yarn' sh 'yarn eslint ./backend' sh 'yarn prettier -c "./backend/**/*.js"' pullRequest.createStatus(status: 'success', context: 'Format & Syntax (backend)', description: 'Squeaky clean! You win today.') } } } } post { failure { script { pullRequest.createStatus(status: 'failure', context: 'Format & Syntax (backend)', description: 'Wow, did you even look at how malformed your code is?', targetUrl: env.RUN_DISPLAY_URL) } } } } stage('Frontend tests') { agent { node { label 'Node' } } steps { script { pullRequest.createStatus(status: 'pending', context: 'Unit tests (frontend)', description: 'Making sure you didn\'t break anything…', targetUrl: env.RUN_DISPLAY_URL) try { sh '! git diff --name-only ^HEAD origin/trunk | grep "^frontend"' sh '! git diff --name-only ^HEAD origin/trunk | grep "^shared-utilities"' echo "No changes found, skipping tests." pullRequest.createStatus(status: 'success', context: 'Unit tests (frontend)', description: 'Skipped (no changes).') } catch (e) { echo "Changes found, running tests." sh 'rm -rf ./backend' sh 'yarn' dir('frontend') { ansiColor('xterm') { sh 'yarn test:ci --coverage --json --outputFile=test-results.json' } } pullRequest.createStatus(status: 'success', context: 'Unit tests (frontend)', description: 'Hot damn, they passed!') } } } post { always { script { if (fileExists('frontend/test-results.json')) { archiveArtifacts artifacts: 'frontend/test-results.json', fingerprint: true } } } failure { script { pullRequest.createStatus(status: 'failure', context: 'Unit tests (frontend)', description: 'What did you do???', targetUrl: env.RUN_DISPLAY_URL) } } } } stage('Backend tests') { agent { node { label 'Node' } } steps { script { pullRequest.createStatus(status: 'pending', context: 'Unit tests (backend)', description: 'Making sure you didn\'t break anything…', targetUrl: env.RUN_DISPLAY_URL) try { sh '! git diff --name-only ^HEAD origin/trunk | grep "^backend"' sh '! git diff --name-only ^HEAD origin/trunk | grep "^shared-utilities"' echo "No changes found, skipping tests." pullRequest.createStatus(status: 'success', context: 'Unit tests (backend)', description: 'Skipped (no changes).') } catch (e) { echo "Changes found, running tests." COMMIT = sh(script: 'git rev-parse HEAD', returnStdout: true).trim() build job: 'Build_Phases/test-backend-parallel', parameters: [ [$class: 'StringParameterValue', name: 'COMMIT', value: COMMIT] ], wait: true pullRequest.createStatus(status: 'success', context: 'Unit tests (backend)', description: 'Wow, way to go!!') } } } post { failure { script { pullRequest.createStatus(status: 'failure', context: 'Unit tests (backend)', description: 'Something terrible has happened.', targetUrl: env.RUN_DISPLAY_URL) } } } } stage('Shared-utilities tests') { agent { node { label 'Node' } } steps { script { pullRequest.createStatus(status: 'pending', context: 'Unit tests (shared-utilities)', description: 'Making sure you didn\'t break anything…', targetUrl: env.RUN_DISPLAY_URL) try { sh '! git diff --name-only ^HEAD origin/trunk | grep "^shared-utilities"' echo "No changes found, skipping tests." pullRequest.createStatus(status: 'success', context: 'Unit tests (shared-utilities)', description: 'Skipped (no changes).') } catch (e) { echo "Changes found, running tests." sh 'rm -rf ./frontend && rm -rf ./backend' sh 'yarn' dir('shared-utilities') { ansiColor('xterm') { sh 'yarn test --coverage --json --outputFile=test-results.json' } } pullRequest.createStatus(status: 'success', context: 'Unit tests (shared-utilities)', description: 'Congratulations, you may work another day.') } } } post { always { script { if (fileExists('shared-utilities/test-results.json')) { archiveArtifacts artifacts: 'shared-utilities/test-results.json', fingerprint: true } } } failure { script { pullRequest.createStatus(status: 'failure', context: 'Unit tests (shared-utilities)', description: 'Look, I get it. It\'s hard. FIX THIS!!!', targetUrl: env.RUN_DISPLAY_URL) } } } } stage('Browser tests') { agent { node { label 'Node' } } environment { CLIENT = 'main' HEADLESS = 'true' APP_ROOT = 'http://localhost:9002' LD_LIBRARY_PATH = '/opt/google/chrome/lib/:$LD_LIBRARY_PATH' } steps { script { pullRequest.createStatus(status: 'pending', context: 'E2E tests (Chrome)', description: 'Making sure you didn\'t break anything…', targetUrl: env.RUN_DISPLAY_URL) try { sh '! git diff --name-only ^HEAD origin/trunk | grep "^backend"' sh '! git diff --name-only ^HEAD origin/trunk | grep "^frontend"' sh '! git diff --name-only ^HEAD origin/trunk | grep "^shared-utilities"' echo "No changes found, skipping tests." pullRequest.createStatus(status: 'success', context: 'E2E tests (Chrome)', description: 'Skipped (no changes).') } catch (e) { echo "Changes found, running tests." COMMIT = sh(script: 'git rev-parse HEAD', returnStdout: true).trim() build job: 'Build_Phases/test-browser-parallel', parameters: [ [$class: 'StringParameterValue', name: 'COMMIT', value: COMMIT] ] pullRequest.createStatus(status: 'success', context: 'E2E tests (Chrome)', description: 'FULL FUNNEL SUCCESS, BEYOTCH!') } } } post { failure { script { pullRequest.createStatus(status: 'failure', context: 'E2E tests (Chrome)', description: 'Oh no. Ohhhhhh no. This is bad.', targetUrl: env.RUN_DISPLAY_URL) } } } } stage('Bundle test (admin)') { agent { node { label 'Node' } } environment { CLIENT = 'admin' AWS_ACCESS_KEY_ID = credentials('aws-access-key-id-deploy-production') AWS_SECRET_ACCESS_KEY = credentials('aws-secret-access-key-deploy-production') } steps { script { pullRequest.createStatus(status: 'pending', context: 'Bundle test (admin)', description: 'Blending…', targetUrl: env.RUN_DISPLAY_URL) try { sh '! git diff --name-only ^HEAD origin/trunk | grep "^cli"' sh '! git diff --name-only ^HEAD origin/trunk | grep "^frontend"' echo "No changes found, skipping tests." pullRequest.createStatus(status: 'success', context: 'Bundle test (admin)', description: 'Skipped (no changes).') } catch (e) { echo "Changes found, running tests." sh 'yarn' sh 'yarn start -e production -n client node ./frontend/bin/client/build.js' pullRequest.createStatus(status: 'success', context: 'Bundle test (admin)', description: 'Ah, the sweet smell of minified text.') } } } post { failure { script { pullRequest.createStatus(status: 'failure', context: 'Bundle test (admin)', description: 'Uh-oh.', targetUrl: env.RUN_DISPLAY_URL) } } } } stage('Bundle test (main)') { agent { node { label 'Node' } } environment { CLIENT = 'main' AWS_ACCESS_KEY_ID = credentials('aws-access-key-id-deploy-production') AWS_SECRET_ACCESS_KEY = credentials('aws-secret-access-key-deploy-production') } steps { script { pullRequest.createStatus(status: 'pending', context: 'Bundle test (main)', description: 'Blending…', targetUrl: env.RUN_DISPLAY_URL) try { sh '! git diff --name-only ^HEAD origin/trunk | grep "^cli"' sh '! git diff --name-only ^HEAD origin/trunk | grep "^frontend"' echo "No changes found, skipping tests." pullRequest.createStatus(status: 'success', context: 'Bundle test (main)', description: 'Skipped (no changes).') } catch (e) { echo "Changes found, running tests." sh 'yarn' sh 'yarn start -e production -n client node ./frontend/bin/client/build.js' pullRequest.createStatus(status: 'success', context: 'Bundle test (main)', description: 'Ah, the sweet smell of minified text.') } } } post { failure { script { pullRequest.createStatus(status: 'failure', context: 'Bundle test (main)', description: 'Uh-oh.', targetUrl: env.RUN_DISPLAY_URL) } } } } stage('Bundle test (quote-widget)') { agent { node { label 'Node' } } environment { CLIENT = 'quote-widget' AWS_ACCESS_KEY_ID = credentials('aws-access-key-id-deploy-production') AWS_SECRET_ACCESS_KEY = credentials('aws-secret-access-key-deploy-production') } steps { script { pullRequest.createStatus(status: 'pending', context: 'Bundle test (quote-widget)', description: 'Blending…', targetUrl: env.RUN_DISPLAY_URL) try { sh '! git diff --name-only ^HEAD origin/trunk | grep "^cli"' sh '! git diff --name-only ^HEAD origin/trunk | grep "^frontend"' echo "No changes found, skipping tests." pullRequest.createStatus(status: 'success', context: 'Bundle test (quote-widget)', description: 'Skipped (no changes).') } catch (e) { echo "Changes found, running tests." sh 'yarn' sh 'yarn start -e production -n client node ./frontend/bin/client/build.js' pullRequest.createStatus(status: 'success', context: 'Bundle test (quote-widget)', description: 'Ah, the sweet smell of minified text.') } } } post { failure { script { pullRequest.createStatus(status: 'failure', context: 'Bundle test (quote-widget)', description: 'Uh-oh.', targetUrl: env.RUN_DISPLAY_URL) } } } } } } } }    
            Hide
            rossm Ross M added a comment -

            do we know what version this feature works. because it was working before 1.7.*

            Show
            rossm Ross M added a comment - do we know what version this feature works. because it was working before 1.7.*
            Hide
            joakimnyman Joakim Nyman added a comment -

            I just installed 1.18.1 in hope of getting the "Starting building:" to be clickable but it is not. What is the status here?

            Show
            joakimnyman Joakim Nyman added a comment - I just installed 1.18.1 in hope of getting the "Starting building:" to be clickable but it is not. What is the status here?
            Hide
            iamwangu wangu added a comment -

            It is not work with Blue Ocean 1.19.0

            Show
            iamwangu wangu added a comment - It is not work with Blue Ocean 1.19.0
            Hide
            wernerwessely Werner Wessely added a comment - - edited

            For anybody struggling with this and in need of some inspiration for a workaround, we are using a wrapper for the job step which prints a link to the downstream build until this issue is fixed. Better than nothing:

             

            def getBlueOceanLink(obj, jobName) {
              def buildNumber
            
              if(obj instanceof Exception) {
                obj.toString().split(" ").each {
                  if(it.contains("#")) {
                    buildNumber = it.substring(1)
                  }
                }
              } else if(obj instanceof org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper) {
                buildNumber = obj.getNumber()
              } else {
                return "Can not determine Blue Ocean link!!!"
              }
            
              return "For detailed information see: http://<YOUR JENKINS>/blue/organizations/jenkins/${jobName}/detail/${jobName}/${buildNumber}/pipeline"
            }
            
            // Wrapper:
            def linkBuild(job, parameters) {
                def buildInfo
                try {
                    buildInfo = build(job: job, parameters: parameters, wait: true, propagate: true)
                } catch (Exception e) {
                    println getBlueOceanLink(e, job)
                    throw e
                }
                println getBlueOceanLink(buildInfo, job)
            }
            
            // Usage:
            stage ("My stage") {
             linkBuild("My job", [
              string(name: "my param", value: some_value)
             ])
            }

            If anybody has come up with something better I would love to hear it!

            Show
            wernerwessely Werner Wessely added a comment - - edited For anybody struggling with this and in need of some inspiration for a workaround, we are using a wrapper for the job step which prints a link to the downstream build until this issue is fixed. Better than nothing:   def getBlueOceanLink(obj, jobName) {   def buildNumber    if (obj  instanceof  Exception) {     obj.toString().split( " " ).each {        if (it.contains( "#" )) {         buildNumber = it.substring(1)       }     }   }  else   if (obj  instanceof  org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper) {     buildNumber = obj.getNumber()   }  else  {      return   "Can not determine Blue Ocean link!!!"   }    return   "For detailed information see: http: //<YOUR JENKINS>/blue/organizations/jenkins/${jobName}/detail/${jobName}/${buildNumber}/pipeline" } // Wrapper: def linkBuild(job, parameters) {     def buildInfo      try  {         buildInfo = build(job: job, parameters: parameters, wait:  true , propagate:  true )     }  catch  (Exception e) {         println getBlueOceanLink(e, job)          throw  e     }     println getBlueOceanLink(buildInfo, job) } // Usage: stage ( "My stage" ) { linkBuild( "My job" , [   string(name:  "my param" , value: some_value) ]) } If anybody has come up with something better I would love to hear it!

              People

              • Assignee:
                Unassigned
                Reporter:
                vlatombe Vincent Latombe
              • Votes:
                38 Vote for this issue
                Watchers:
                63 Start watching this issue

                Dates

                • Created:
                  Updated: