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)
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)
}
}
}
}
}
}
}
}
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?
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:
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!
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.
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?
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.
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.