Capturing The Return Value Of The JFROG CLI in a jenkins pipeline

Hi,

Im trying to capture the return value of a jfrog-cli command ( using the jenkins jfrog cli plugin ) in a pipeline script, the TARGET variable is a filename on the remote artifactory which either exists or doesn’t… I’d expect data to return a count, but all it returns is null, can anyone help?

def data = jf 'rt s ${TARGET} --count'

The console output shows the following… but 1 isn’t assigned to the variable

12:10:33 [Info] Searching artifacts...
12:10:35 [Info] Found 1 artifact.
1

Additionally Capturing the resultant object…

[linuxDebian] /home/jenkins/tools/io.jenkins.plugins.jfrog.JfrogInstallation/jfrog-cli/jf rt s {TARGET} --count
13:03:46 [Info] Searching artifacts…
13:03:47 [Info] Found 1 artifact.
1
[Pipeline] echo
class org.codehaus.groovy.runtime.NullObject

Jenkins setup:
Using jenkins 2.414.2 and the latest version of the jfrog cli plugin.

Hi @steelhead31 and welcome to this community. :wave:

The issue you’re encountering might be related to how Jenkins handles the return values of shell commands, especially when executed within a pipeline.
In Jenkins pipeline scripts, the return value of a shell command isn’t as directly accessible as you might expect in a typical shell script.
Instead, the result of a shell command is treated as the standard output, and you need to capture and process it accordingly.
Well, at least, that’s the way I think I understand it, I don’t know the JFrog plugin, so it may or may not use the underlying

Here’s how I think you could capture and process the result of your jfcommand thanks to the shell:

def result = sh(script: "jf rt s ${TARGET} --count", returnStatus: true)
if (result == 0) {
    echo "The command succeeded."
} else {
    echo "The command failed with exit code ${result}."
}

// If you want to capture the standard output of the command
def output = sh(script: "jf rt s ${TARGET} --count", returnStdout: true).trim()
echo "Command output: ${output}"

Make sure that the jf command is available in the environment where the Jenkins pipeline runs and that it’s in the system’s PATH.

I have similar issue. The problem is that I don’t have control to install jf on the Jenkins node. I installed jf using global tool jfrog-cli hence I can only call `jf using similar like

def myData = jf ‘rt s blabla’

is there anyway to capture the result of myData?

I’ve had the same problem, and managed to get around it by using the Pipeline Utility Steps plugin. This provides a ‘tee’ block that records the output of commands within to a specified file which can then be manipulated with something like a python script.

My pipeline looked similar to below:

pipeline {
    stages {
        stage('Pipeline Step'){
            steps {
                script {
                    tee('search_output.txt'){
                        jf "rt s --spec spec-file.json "
                    }
                    sh "python3 search_manipulator.py -i search_output.txt"
                }
            }
        }
    }
}
1 Like

According to (some, perhaps older) documentation for the plugin, this should work:

String version = jf '-v'
echo "JFrog CLI version output: $version"

But it doesn’t.

In other documentation that section is missing.

I solved this by running jf through the sh command in a scripted pipeline like this:

withEnv([
     // required for the JFrog plugin to work
    "JFROG_BINARY_PATH=${tool 'jfrog-cli'}",
    // The jf plugin is using this directory. By setting it here, jf through sh will
    // use the same directory
    "JFROG_CLI_HOME_DIR=${env.WORKSPACE_TMP}/jfrog/${env.BUILD_NUMBER}/.jfrog",
    // Optional. Use sh '${JFROG_BINARY_PATH}/jf ...' instead of sh 'jf ...' if not set.
    "PATH+=${tool 'jfrog-cli'}"
]) {
    jf '-v'  // If you don't need the output, run jf as normal
    // You also need to run a jf command like this before you run one through sh,
    // so that your Artifactory server configured in Jenkins will be configured
    // for the jf commands run through sh

    def data = sh(script: 'jf rt s ${TARGET} --count', returnStdout: true)
    echo(data) 
}

The plugin is using the installed jf binary.

JFROG_BINARY_PATH tells the plugin where to find the jf binary.
JFROG_CLI_HOME_DIR tells the jf binary where it should look for its configuration. If not given, defaults to ~/.jfrog.

2 Likes

Hi @poddingue ,

using sh(script : "jf rt ...") is different with jf "rt ...".

  • sh(script: "jf rt ...") is using the jf command line in Jenkins agent. It requires the Jenkins agent ( maybe container, windows, linux ) contains jf binary and appropriate credential setup
  • jf "rt ..." is using the jfrog plugin, and the tool installation and credential setup is handled by Jenkins controller itself ( via Manage JenkinsToolsJFrog CLI installations )

@steelhead31 As I know, the jfrog plugin doesn’t have that stdout ability.

check details as below
  • pipeline
    
      withEnv([ "JFROG_BINARY_PATH=${tool 'jfrog-cli'}", "JFROG_CLI_LOG_LEVEL=DEBUG" ]) {
          println ".. start .. "
          String version = jf '-v'
          println ".. version: ${version} .."
      }
      
  • console output
    
      [Pipeline] echo
       .. start .. 
      [Pipeline] jf
       Executing sh script inside container jnlp of pod jenkins-marslo-sandbox-3-s9wqh-2btks
       Executing command: "/home/devops/tools/io.jenkins.plugins.jfrog.JfrogInstallation/jfrog-cli/jf" "c" "add" "artifactoryha-dev" "--user=srv-ssd-fw-devops" ******** "--url=https://artifactory.sample.com" "--artifactory-url=https://artifactory.sample.com/artifactory" "--distribution-url=https://artifactory.sample.com/distribution" "--xray-url=https://artifactory.sample.com/xray" "--interactive=false" "--overwrite=true" 
       exit
       05:00:54 [Debug] JFrog CLI version: 2.72.2
       05:00:54 [Debug] OS/Arch: linux/amd64
       05:00:54 [Debug] Trace ID for JFrog Platform logs: 1beccad112266359
       05:00:54 [Debug] JFrog CLI version: 2.72.2
       05:00:54 [Debug] OS/Arch: linux/amd64
       05:00:54 [Debug] Trace ID for JFrog Platform logs: 1beccad112266359
       05:00:54 [Debug] Locking config file to run config AddOrEdit command.
       05:00:54 [Debug] Creating lock in: /home/devops/workspace/marslo/sandbox@tmp/jfrog/3/.jfrog/locks/config
       05:00:54 [Debug] Locking config file to run config AddOrEdit command.
       05:00:54 [Debug] Creating lock in: /home/devops/workspace/marslo/sandbox@tmp/jfrog/3/.jfrog/locks/config
       05:00:54 [Debug] config file is released.
       05:00:54 [Debug] config file is released.
       05:00:54 [Debug] Sending HTTP GET request to: https://artifactory.sample.com/artifactory/api/security/encryptedPassword
       05:00:54 [Debug] Sending HTTP GET request to: https://artifactory.sample.com/artifactory/api/security/encryptedPassword
       05:00:54 [Debug] Releasing lock: /home/devops/workspace/marslo/sandbox@tmp/jfrog/3/.jfrog/locks/config/jfrog-cli.conf.lck.59.1734584454681310364
       05:00:54 [Debug] Usage Report: Sending info...
       05:00:54 [Debug] Releasing lock: /home/devops/workspace/marslo/sandbox@tmp/jfrog/3/.jfrog/locks/config/jfrog-cli.conf.lck.59.1734584454681310364
       05:00:54 [Debug] Usage Report: Sending info...
       05:00:54 [Debug] Sending HTTP GET request to: https://artifactory.sample.com/artifactory/api/system/version
       05:00:54 [Debug] Sending HTTP GET request to: https://artifactory.sample.com/artifactory/api/system/version
       05:00:54 [Debug] Artifactory response: 200 OK
       05:00:54 [Debug] Artifactory response: 200 OK
       05:00:54 [Debug] JFrog Artifactory version is: 7.90.8
       05:00:54 [Debug] JFrog Artifactory version is: 7.90.8
       05:00:54 [Debug] Sending HTTP POST request to: https://artifactory.sample.com/artifactory/api/system/usage
       05:00:54 [Debug] Sending HTTP POST request to: https://artifactory.sample.com/artifactory/api/system/usage
       Executing sh script inside container jnlp of pod jenkins-marslo-sandbox-3-s9wqh-2btks
       Executing command: "/home/devops/tools/io.jenkins.plugins.jfrog.JfrogInstallation/jfrog-cli/jf" "-v" 
       exit
       jf version 2.72.2
       jf version 2.72.2
      [Pipeline] echo
       .. version: null ..
      [Pipeline] }
      

BTW, for the workable solution with env JFROG_CLI_HOME_DIR=${env.WORKSPACE_TMP}/jfrog/${env.BUILD_NUMBER}/.jfrog, it should using "$HOME/tools/io.jenkins.plugins.jfrog.JfrogInstallation/jfrog-cli/jf" instead of jf, because :

  • pipeline

    println ".. start .. "
    String output = sh( script: '''
                                    which -a jf;
                                    jf -v;
                                    /home/devops/tools/io.jenkins.plugins.jfrog.JfrogInstallation/jfrog-cli/jf -v
                                '''.stripIndent(),
                                returnStdout: true
                    ).trim()
    println ".. output ..:\n${output}"
    
  • console output

    [Pipeline] echo
     .. start .. 
    [Pipeline] sh (hide)
     + which -a jf
     + jf -v
     + /home/devops/tools/io.jenkins.plugins.jfrog.JfrogInstallation/jfrog-cli/jf -v
    [Pipeline] echo
     .. output ..:
     /usr/bin/jf
     /bin/jf
     jf version 2.59.1
     jf version 2.72.2
    
1 Like