Jenkins doesn't fail on exceptions?

I’m using Jenkins on a Windows server. I set up a simple pipeline that should simply clone a repo with python files, eventually run pytest on the test files and fail the pipeline if the tests didn’t finish successfully. But this is not working.

For a particular reason the python code raises an NotADirectoryError: [WinError 267] The directory name is invalid: 'C:\\Windows\\TEMP\\tmpeola6z2l\\Test.log' the reason might be lack of access rights. However Jenkins just goes on, where I would expect it would automatically fail, what’s wrong here?

This is the related code part

stage("Run tests")
        {
            steps {
                echo "Running tests"
                script {
                        bat """
                        call C:\\Users\\fai\\Anaconda3\\condabin\\conda.bat activate pytests 
                        call python -m pip install pytest
                        call python -m pytest %WORKSPACE% || exit 0
                        """
                }
            }
        }

FWIW, it wouldn’t also be cached if it was put in a try/catch-block either.

Thanks in advance for any hint

I don’t know about bat, but for sh command || exit 0 says run this command, then on failure, exit 0, so then sh would say “yep, exit 0 is good” and keeps going.

I would expect if you remove || exit 0 it’ll work as you expect

btw you only need script {} when you want to add scripted elements to declarative pipeline

1 Like

Thanks, but It wouldn’t change if I switch to exit 1 or generally removing || exit 0 as you suggested

looks like call will run without messing with the parent. is there a reason you have call infront of everything?

oh that’s interesting. well batch doesn’t seem to run the 3 commands sequentially if I skip call or add & between the commands

It is certainly correct to use CALL in front of conda.bat, and it should be OK with python as well.

The CALL documentation refers to the behaviour that, if file1.bat runs file2.bat without CALL, then subsequent commands of file1.bat will not be executed at all. This behaviour is somewhat like exec in POSIX sh, except it is the default. COMMAND.COM in MS-DOS works this way (perhaps to minimise memory use) and CMD.EXE in Windows remains compatible with that. If there is a chance that the python commands might find a python.bat file along the PATH, then it is safest to use CALL.

I’m not sure how CALL works with || though.

POSIX sh has “set -e” to make the shell exit if a command returns with a nonzero exit code. CMD.EXE does not have a similar feature.

One thing you could try is replace the || exit with a separate ERRORLEVEL check

call python -m pytest %WORKSPACE%
IF ERRORLEVEL 1 (
    ECHO pytest exit code is not zero
    EXIT 1
)

in order to verify whether the exit code is lost between pytest and CMD, or between CMD and Jenkins.

1 Like

Thanks @kon , @halkeye

I adapted the steps path like:

try {
   bat """
   call C:\\Users\\fihle\\Anaconda3\\condabin\\conda.bat activate pytests 
   call python -m pip install pytest
   call python -m pytest %WORKSPACE% || EXIT /b 1
                          
   IF NOT %ERRORLEVEL% == 0 ( 
      echo "ABORT: " %ERRORLEVEL%
      exit /b 1
   )
   """
}
catch (e)
{
   echo "Exception occured"
}

If now I would replace %ERRORCODE% with something fixed != 0, it’ll enter the if-branch, exit the batch with error 1 and Jenkins fails. However %ERRORCODE% is always 0, the python status never gets picked up by it

UPDATE

I think I found the solution, it is with calling bat( instead of bat """, currently verifying

Yep verified and not misleading at all

stage("Run tests")
        {
            steps {
                echo "Running tests"
                script {
                        try {
                            errorCode = bat( label: '', returnStdout: true, script: """
                            call C:\\Users\\fihle\\Anaconda3\\condabin\\conda.bat activate pytests 
                            call python -m pip install pytest
                            call python -m pytest %WORKSPACE%
                            
                            IF NOT %ERRORLEVEL% == 0 ( 
                                echo "ABORT: " %ERRORLEVEL%
                                exit /b %ERRORLEVEL%
                              )
                            """)
                        }
                        catch (e)
                        {
                            error("Tests didn't finish successfully: ${e}")
                        }
                }
            }
        }

Resolves the issue