jenkinsjenkins-pipelinejenkins-shared-libraries

Executing shell commands from inside Pipeline Shared Library


I'm writing a shared library that will get used in Pipelines.

class Deployer implements Serializable {
    def steps
    Deployer(steps) {
        this.steps = steps
    }
    
    def deploy(env) {
        // convert environment from steps to list
        def process = "ls -l".execute(envlist, null)
        process.consumeProcessOutput(output, error)
        process.waitFor()
        println output
        println error
    }
}

In the Jenkinsfile, I import the library, call the class and execute the deploy function inside a script section:

stage('mystep') {
    steps {
        script {
            def deployer = com.mypackage.HelmDeployer("test")
            deployer.deploy()
        }
    }
}

However, no output or errors are printed on the Console log.

Is it possible to execute stuff inside a shared library class? If so, how, and what am I doing wrong?


Solution

  • Yes, it is possible but not really an obvious solution. Every call that is usually done in the Jenkinsfile but was moved to the shared-library needs to reference the steps object you passed.

    You can also reference the Jenkins environment by calling steps.env.

    I will give you a short example:

    class Deployer implements Serializable {
       def steps
       Deployer(steps) {
          this.steps = steps
       }
    
        def callMe() {
            // Always call the steps object
            steps.echo("Test")
            steps.echo("${steps.env.BRANCH_NAME}")
            steps.sh("ls -al")
    
            // Your command could look something like this:
            // def process = steps.sh(script: "ls -l", returnStdout: true).execute(steps.env, null)
            ...
        }
    }
    

    You also have to import the object of the shared library and create an instance of it. Define the following outside of your Pipeline.

    import com.mypackage.Deployer // path is relative to your src/ folder of the shared library
    def deployer = new Deployer(this) // 'this' references to the step object of the Jenkins
    

    Then you can call it in your pipeline as the following:

    ... script { deployer.test() } ...