How to bypass Stage that depends on an offline agent?

Jenkins setup:
Jenkins Version: 2.4.14.3 lts

For the past few days I have had a problem connecting with a Windows agent.

I’m using a parallel stage for running on Windows and Linux.
And I was using a setting to enable building or not.

As long as both agents are online no worries.

But now, I have a connection problem with one of the agents (for Jenkins it is OFFLINE)
so I end up with this trace in the logs

Still waiting to schedule task
Windows is offline

and the job is waiting for a construction which will never be done (and which is not planned)

here is my initial Stage

// parallel 1 start
stage('Test On Windows') {
    agent { node { label 'agent_windows' } }
    steps {
        script {
            echo "Test if build on windows"
            if (IN_OS_TARGET.contains('Windows')) {
                //stageResult Valid options are SUCCESS, UNSTABLE, FAILURE, NOT_BUILT and ABORTED
                catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
                    echo "TODO Build on windows "
                    sh 'exit 0'
                }
            } else {
                //stageResult Valid options are SUCCESS, UNSTABLE, FAILURE, NOT_BUILT and ABORTED
                catchError(buildResult: 'SUCCESS', stageResult: 'NOT_BUILT') {
                    sh 'exit 1'
                }
            }
                        }
    }
    // post {
    //     always {
    //     }
    // }
}
// parallel 1 end

To solve this problem, I modified it like this:

// parallel 1 start
stage('Test On Windows') {
    when {
        beforeAgent true
        expression {
            return Jenkins.instance.getNode('agent_windows').toComputer().isOnline()
        }
    }
    agent { node { label 'agent_windows' } }
    steps {
        script {
            echo "Test if build on windows"
            if (IN_OS_TARGET.contains('Windows')) {
                //stageResult Valid options are SUCCESS, UNSTABLE, FAILURE, NOT_BUILT and ABORTED
                catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
                    echo "TODO Build on windows "
                    sh 'exit 0'
                }
            } else {
                //stageResult Valid options are SUCCESS, UNSTABLE, FAILURE, NOT_BUILT and ABORTED
                catchError(buildResult: 'SUCCESS', stageResult: 'NOT_BUILT') {
                    sh 'exit 1'
                }
            }
        }
    }
    // post {
    //     always {
    //     }
    // }
}
// parallel 1 end

The good point: the job is no longer blocked, but the stage has status FAILURE

in addition, I have this trace in the logs
‘Scripts not permitted to use staticMethod jenkins.model.Jenkins getInstance. Administrators can decide whether to approve or reject this signature.’

Ideally I want to use the “when” condition with testing the agent is On Line and if the target is selected.

the desired behavior:
If the agent is online and the target selected starts the build
If the agent is offline and the target selected, the step should take the status FAILURE
If the target is not selected, the step should take the status NOT_BUILD

Jenkins.getInstance() should always be blocked from users.

You should surface a NonCPS shared library step which explicitly returns the info you want from the instance runtime.

import jenkins.model.Jenkins

@NonCPS
Boolean call(String label = 'agent_windows') {
    Jenkins.instance.getNode(label)?.toComputer()?.isOnline() ?: false
}

So that you can call it from your pipeline. See also Extending with Shared Libraries

For example, if you call it vars/isAgentOnline.groovy , you can change your code like

stage('Test On Windows') {
    when {
        beforeAgent true
        expression {
            isAgentOnline('agent_windows')
        }
    }
2 Likes

thank you for your answer, it addresses the ‘Jenkins.getInstance()’ access problem

I have not yet set up a shared library (because we are in the POC migration phase towards production).

So with your solution, if the agent is offline, the ‘when’ condition is not valid and therefore the status is FAILURE.

how can I intercept and modify the NOT_BUILD state, is this possible?

At-scale, in production, I use only scripted pipeline. I provide an alternate DSL for users rather than use declarative. That being said, I would look to the docs for declarative. I constructed my answer based on what I know about scripted pipeline and the example you gave in your question containing declarative.

I looked at the docs and nothing obvious jumped at me Pipeline Syntax

I suggest filing a feature request Pipeline: Declarative (see Jira issue link in menu to right) where you request modifying the stage status in this case under these “when” conditions before an agent gets used.

1 Like