Home > Software engineering >  In a Jenkins pipeline, why is this not showing the return string?
In a Jenkins pipeline, why is this not showing the return string?

Time:05-03

I have the following scriptive pipeline that adds a tag to an existingt ECR image in AWS

node("linux") {
    stage("test") {
        docker.withRegistry("https://0123456789.dkr.ecr.us-east-1.amazonaws.com", "myCreds") {
            String rc = null
            sh """
                aws ecr batch-get-image --repository-name repo-name --image-ids imageTag=1.0.286 --query images[].imageManifest --output text > manifest.json
                cat manifest.json
            """
            try {
                rc = sh(script: """
                          aws ecr put-image --repository-name repo-name --image-tag qa-1.0.286 --image-manifest file://manifest.json
                         """,
                         returnStdout: true).trim()
            }
            catch(err) {
                println "rc=$rc"
            }
        }
    }
}

When I run the pipeline, I get this in the console output.

  aws ecr put-image --repository-name repo-name --image-tag qa-1.0.286 --image-manifest file://./manifest.json

An error occurred (ImageAlreadyExistsException) when calling the PutImage operation: Image with digest 'sha256:ff44828207c7c7df75a8be2e08057da438b4b7f3063acab34ea7ebbcb7dd50a6' and tag 'qa-1.0.286' already exists in the repository with name 'repo-name' in registry with id '0123456789'
[Pipeline] echo
rc=null

Why is rc=null instead of the An error occurred... string above it in the console output? I've used this way to capture a shell script outputs, but why doesn't it work here? What's the proper way to do it in this case?

CodePudding user response:

The problem is that the shell step captures standard output and the aws client prints the message into standard error

You can forward the stderr into stdout with 2>&1 at the end of your command, for example:

aws ecr put-image --repository-name repo-name --image-tag qa-1.0.286 --image-manifest file://manifest.json 2>&1

But the other problem is that when the command inside sh fails, it throws an exception and it doesn't assign the value to the variable, so you need to make sure, that the command always succeeds, for example with adding || : (execute an empty command if the previous command fails)

The downside is that you will need to check the output variable to check if the command failed.

The snippet could then look like this:

String rc = null
sh """
    aws ecr batch-get-image --repository-name repo-name --image-ids imageTag=1.0.286 --query images[].imageManifest --output text > manifest.json
    cat manifest.json
"""

rc = sh(script:
"""
    aws ecr put-image --repository-name repo-name --image-tag qa-1.0.286 --image-manifest file://manifest.json 2>&1 || :
""", returnStdout: true).trim()

if (rc.contains("error occurred")) {
// the command invocation failed
}
  • Related