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

UI for downstream jobs launched with 'build' step

    • 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
    • 1.14.0

      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)

       

       

          [JENKINS-38339] UI for downstream jobs launched with 'build' step

          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)
                 }
                }
               }
              }
             }
            }
           }
          }

           

           

          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) } } } } } } } }    

          Ross M added a comment -

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

          Ross M added a comment - do we know what version this feature works. because it was working before 1.7.*

          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?

          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?

          wangu added a comment -

          It is not work with Blue Ocean 1.19.0

          wangu added a comment - It is not work with Blue Ocean 1.19.0

          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!

          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!

          Ryan Stewart added a comment -

          I have raised a bug for this JENKINS-60995

          as it is a regression of existing functionality 

          Ryan Stewart added a comment - I have raised a bug for this  JENKINS-60995 as it is a regression of existing functionality 

          Luis Roalter added a comment -

          Sometimes it works. but not always. For some reasons the NodeDownstreamBuildAction is missing when using the api /blue/rest/organizations/jenkins/pipelines/

          When going closer into /blue/rest/organizations/jenkins/pipelines/<project>/runs/x/nodes/y/ the information is missing in this endpoint too.

          Funny fact, I've debugged it with the Script console by replaying the code from https://github.com/jenkinsci/blueocean-plugin/blob/master/blueocean-pipeline-api-impl/src/main/java/io/jenkins/blueocean/listeners/DownstreamJobListener.java. This works and all the triggered builds are there.

           

          But for me it's too complex to dig into the blue-ocean rest and debug there.

          Any suggestion from anyone how to debug it?

          Luis Roalter added a comment - Sometimes it works. but not always. For some reasons the NodeDownstreamBuildAction is missing when using the api /blue/rest/organizations/jenkins/pipelines/ When going closer into /blue/rest/organizations/jenkins/pipelines/<project>/runs/x/nodes/y/ the information is missing in this endpoint too. Funny fact, I've debugged it with the Script console by replaying the code from https://github.com/jenkinsci/blueocean-plugin/blob/master/blueocean-pipeline-api-impl/src/main/java/io/jenkins/blueocean/listeners/DownstreamJobListener.java . This works and all the triggered builds are there.   But for me it's too complex to dig into the blue-ocean rest and debug there. Any suggestion from anyone how to debug it?

          Stuart Rowe added a comment - - edited

          I've been looking into this as well. What I've found so far:

          • The downstream runs have an associated BuildUpstreamNodeAction contributed by the build step.
          • The BuildUpstreamNodeAction action has an upstreamNodeId pointing back to the build step that triggered the downstream run.
          • This DownstreamJobListener adds a NodeDownstreamBuildAction to the node pointed to by the upstreamNodeId.
          • This upstreamNodeId doesn't match the id of the node typically selected when viewing the Blue Ocean pipeline graph (that node is typically a stage or parallel branch node)
          • There's code in PipelineNodeGraphVisitor.java that accumulates actions from nodes within a branch or stage and then adds them to the node for that branch or stage. I believe this is the source of the issue.

           

          Stuart Rowe added a comment - - edited I've been looking into this as well. What I've found so far: The downstream runs have an associated  BuildUpstreamNodeAction contributed by the build step. The BuildUpstreamNodeAction action has an upstreamNodeId pointing back to the build step that triggered the downstream run. This DownstreamJobListener adds a NodeDownstreamBuildAction  to the node pointed to by the upstreamNodeId. This upstreamNodeId doesn't match the id of the node typically selected when viewing the Blue Ocean pipeline graph (that node is typically a stage or parallel branch node) There's code in  PipelineNodeGraphVisitor.java that accumulates actions from nodes within a branch or stage and then adds them to the node for that branch or stage. I believe this is the source of the issue.  

          Roi BB added a comment -

          Hi, any estimation when the fix will be released? Tnx.

          Roi BB added a comment - Hi, any estimation when the fix will be released? Tnx.

          Logan Mzz added a comment -
          1. Issue open close to 6 years ago,
          2. Source seems to have been identified 2 years ago

          and still no fix ?

          Logan Mzz added a comment - Issue open close to 6 years ago, Source seems to have been identified 2 years ago and still no fix ?

            Unassigned Unassigned
            vlatombe Vincent Latombe
            Votes:
            61 Vote for this issue
            Watchers:
            87 Start watching this issue

              Created:
              Updated: