简体   繁体   中英

Jenkins pipeline skip stage if copying fails

Let's say we have a simple pipeline setup like this:

pipeline {
   stages {
      stage('Stage1') {
         sh '''
           echo 'Copying files'
           cp ./file1 ./directory1
         '''
      }
      stage('Stage2') {
         sh '''
           echo 'This stage should still work and run'
           cp ./directory2/files ./directory2/subdirectory
         '''
      }
      stage('Stage3') { ... }
      ...
   }
}

Whenever I don't have the files in Stage1 or Stage2, it fails the build saying:

'cp cannot stat./file1./directory1' or 'cp cannot stat./directory2/files./directory2/subdirectory'

Of course if the files exist, both stages work perfectly fine. The problem is that the build fails for the rest of the stages if a stage fails. So if Stage1 fails because there are no files, it fails every stage after and they don't even run, same goes for if Stage2 fails, then we know that Stage1 succeeded but then Stage3 and onwards fails and does not even run.

Is there a way to make it so that if the cp command fails and the cp cannot stat shows, to just skip the stage and proceed to the next one? Or at least make it so that only that stage fails and it can proceed to build the next stage(s)?

This can be achieved using the catchError

pipeline {
    agent any
    stages {
       
        stage('1') {
            steps {
                script{
                catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
                    echo 'Copying files'
                    cp ./file1 ./directory1
                }
              }
            }
        }
        stage('2') {
            steps {
                script{
                catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
                    echo 'This stage should still work and run'
                    cp ./directory2/files ./directory2/subdirectory
                }
              }
            }
        }

        stage('3') {
            steps {
                sh 'exit 0'
            }
        }
    }
}

From above pipeline script, all stages will executed. If the cp command will not work for either of stage 1 or stage 2, it will show as failed for that particular stage but rest all stages will execute.

Similar to below screenshot:

在此处输入图像描述


Modified Answer

Following pipeline script include sh ''' ''' , which need not have to be present inside the catchError block.

You can include only those commands inside catchError for which you want to catch the errors.


pipeline {
    agent any
    stages {

        stage('1') {
            steps {
                sh """
                
                echo 'Hello World!!!!!!!!'
                curl https://www.google.com/
                
                """ 

                catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
                    echo 'Copying files'
                    cp ./file1 ./directory1
                }
            }
        }
        stage('2') {
            steps {
                catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
                    echo 'This stage should still work and run'
                    cp ./directory2/files ./directory2/subdirectory
                }
            }
        }

        stage('3') {
            steps {
                sh 'exit 0'
            }
        }
    }
}

Here is an simple way of skipping the stage when a file does not exist, using the when directive:

pipeline {
   agent any   
   stages {
      stage('Stage1') {
         when { expression { fileExists './file1' } }
         steps {
            sh '''
            echo 'Copying files'
            cp ./file1 ./directory1
            '''
         }
      }
      stage('Stage2') {
         when { expression { fileExists './directory2/files' } }
         steps {
            sh '''
            echo 'This stage should still work and run'
            cp ./directory2/files ./directory2/subdirectory
            '''
         }
      }
      stage('Stage3') {
         steps {
            echo "stage 3"
         }
      }
   }
}

In above case you have to specify the path twice, in the when directive and in the sh step, it is better to handle it in a another way eg using variables or closures. Because of the restrictions in the declarative pipeline, I would recommend you to use the scripted pipeline instead.

You could just check if the file exists before you try to copy it using a conditional like this:

[ -f./directory2/files ] && cp./directory2/files./directory2/subdirectory || echo "File does not exist"

Source and more info

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM